nautobot 2.3.16__py3-none-any.whl → 2.4.0b1__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 (675) hide show
  1. nautobot/__init__.py +15 -0
  2. nautobot/apps/api.py +0 -2
  3. nautobot/apps/config.py +32 -3
  4. nautobot/apps/events.py +19 -0
  5. nautobot/apps/exceptions.py +0 -2
  6. nautobot/apps/ui.py +44 -9
  7. nautobot/apps/utils.py +0 -8
  8. nautobot/apps/views.py +2 -0
  9. nautobot/circuits/navigation.py +0 -57
  10. nautobot/circuits/tables.py +1 -2
  11. nautobot/circuits/templates/circuits/circuit_retrieve.html +0 -71
  12. nautobot/circuits/templates/circuits/inc/circuit_termination.html +6 -64
  13. nautobot/circuits/templates/circuits/inc/circuit_termination_cable_fragment.html +40 -0
  14. nautobot/circuits/templates/circuits/inc/circuit_termination_header_extra_content.html +26 -0
  15. nautobot/circuits/templates/circuits/provider_retrieve.html +0 -76
  16. nautobot/circuits/tests/integration/test_relationships.py +33 -24
  17. nautobot/circuits/tests/test_filters.py +4 -8
  18. nautobot/circuits/views.py +143 -26
  19. nautobot/cloud/factory.py +4 -1
  20. nautobot/cloud/models.py +1 -1
  21. nautobot/cloud/tests/test_filters.py +5 -4
  22. nautobot/core/api/fields.py +5 -5
  23. nautobot/core/api/metadata.py +28 -256
  24. nautobot/core/api/pagination.py +3 -2
  25. nautobot/core/api/renderers.py +3 -0
  26. nautobot/core/api/serializers.py +24 -244
  27. nautobot/core/api/urls.py +3 -4
  28. nautobot/core/api/utils.py +0 -62
  29. nautobot/core/api/views.py +48 -158
  30. nautobot/core/apps/__init__.py +22 -578
  31. nautobot/core/celery/__init__.py +13 -0
  32. nautobot/core/celery/log.py +4 -4
  33. nautobot/core/celery/schedulers.py +48 -3
  34. nautobot/core/cli/__init__.py +8 -0
  35. nautobot/core/constants.py +7 -0
  36. nautobot/core/events/__init__.py +116 -0
  37. nautobot/core/events/base.py +27 -0
  38. nautobot/core/events/exceptions.py +10 -0
  39. nautobot/core/events/redis_broker.py +48 -0
  40. nautobot/core/events/syslog_broker.py +19 -0
  41. nautobot/core/exceptions.py +0 -6
  42. nautobot/core/filters.py +16 -21
  43. nautobot/core/fixtures/user-data.json +59 -0
  44. nautobot/core/forms/fields.py +53 -8
  45. nautobot/core/forms/utils.py +2 -1
  46. nautobot/core/graphql/schema.py +3 -1
  47. nautobot/core/graphql/types.py +1 -1
  48. nautobot/core/jobs/__init__.py +4 -4
  49. nautobot/core/jobs/cleanup.py +13 -49
  50. nautobot/core/jobs/groups.py +1 -1
  51. nautobot/core/management/commands/generate_test_data.py +21 -0
  52. nautobot/core/management/commands/validate_models.py +1 -1
  53. nautobot/core/middleware.py +16 -0
  54. nautobot/core/models/__init__.py +1 -1
  55. nautobot/core/models/fields.py +11 -7
  56. nautobot/core/models/query_functions.py +2 -2
  57. nautobot/core/models/tree_queries.py +3 -6
  58. nautobot/core/settings.py +44 -7
  59. nautobot/core/settings.yaml +86 -8
  60. nautobot/core/tables.py +15 -65
  61. nautobot/core/tasks.py +1 -1
  62. nautobot/core/templates/components/button/default.html +7 -0
  63. nautobot/core/templates/components/button/dropdown.html +20 -0
  64. nautobot/core/templates/components/layout/one_over_two.html +19 -0
  65. nautobot/core/templates/components/layout/two_over_one.html +19 -0
  66. nautobot/core/templates/components/panel/body_content_data_table.html +27 -0
  67. nautobot/core/templates/components/panel/body_content_objects_table.html +4 -0
  68. nautobot/core/templates/components/panel/body_content_tags.html +6 -0
  69. nautobot/core/templates/components/panel/body_content_text.html +12 -0
  70. nautobot/core/templates/components/panel/body_wrapper_generic.html +3 -0
  71. nautobot/core/templates/components/panel/body_wrapper_key_value_table.html +3 -0
  72. nautobot/core/templates/components/panel/body_wrapper_table.html +3 -0
  73. nautobot/core/templates/components/panel/footer_contacts_table.html +20 -0
  74. nautobot/core/templates/components/panel/footer_content_table.html +14 -0
  75. nautobot/core/templates/components/panel/grouping_toggle.html +14 -0
  76. nautobot/core/templates/components/panel/header_extra_content_table.html +3 -0
  77. nautobot/core/templates/components/panel/panel.html +16 -0
  78. nautobot/core/templates/components/panel/stats_panel_body.html +8 -0
  79. nautobot/core/templates/components/tab/content_wrapper.html +3 -0
  80. nautobot/core/templates/components/tab/label_wrapper.html +5 -0
  81. nautobot/core/templates/components/tab/label_wrapper_distinct_view.html +3 -0
  82. nautobot/core/templates/generic/object_retrieve.html +28 -17
  83. nautobot/core/templates/inc/computed_fields/panel_data.html +4 -7
  84. nautobot/core/templates/inc/custom_fields/panel.html +2 -2
  85. nautobot/core/templates/inc/custom_fields/panel_data.html +4 -7
  86. nautobot/core/templates/inc/footer.html +1 -0
  87. nautobot/core/templates/inc/media.html +0 -3
  88. nautobot/core/templates/inc/nav_menu.html +1 -1
  89. nautobot/core/templates/inc/relationships_panel.html +1 -1
  90. nautobot/core/templates/nautobot_config.py.j2 +3 -3
  91. nautobot/core/templates/panel_table.html +12 -0
  92. nautobot/core/templates/search.html +0 -7
  93. nautobot/core/templates/utilities/render_jinja2.html +117 -0
  94. nautobot/core/templatetags/helpers.py +101 -12
  95. nautobot/core/templatetags/ui_framework.py +40 -0
  96. nautobot/core/testing/api.py +23 -128
  97. nautobot/core/testing/context.py +18 -0
  98. nautobot/core/testing/filters.py +41 -58
  99. nautobot/core/testing/mixins.py +2 -7
  100. nautobot/core/testing/views.py +25 -123
  101. nautobot/core/tests/integration/test_app_home.py +1 -0
  102. nautobot/core/tests/integration/test_app_navbar.py +1 -0
  103. nautobot/core/tests/integration/test_filters.py +2 -0
  104. nautobot/core/tests/integration/test_home.py +1 -0
  105. nautobot/core/tests/integration/test_navbar.py +1 -0
  106. nautobot/core/tests/integration/test_view_authentication.py +1 -2
  107. nautobot/core/tests/nautobot_config.py +198 -0
  108. nautobot/core/tests/runner.py +3 -3
  109. nautobot/core/tests/test_api.py +82 -201
  110. nautobot/core/tests/test_csv.py +3 -25
  111. nautobot/core/tests/test_events.py +214 -0
  112. nautobot/core/tests/test_jinja_filters.py +1 -0
  113. nautobot/core/tests/test_jobs.py +84 -13
  114. nautobot/core/tests/test_navigations.py +7 -241
  115. nautobot/core/tests/test_templatetags_helpers.py +16 -0
  116. nautobot/core/tests/test_ui.py +150 -0
  117. nautobot/core/tests/test_utils.py +0 -25
  118. nautobot/core/tests/test_views.py +123 -31
  119. nautobot/core/ui/__init__.py +0 -0
  120. nautobot/core/ui/base.py +11 -0
  121. nautobot/core/ui/choices.py +44 -0
  122. nautobot/core/ui/homepage.py +167 -0
  123. nautobot/core/ui/nav.py +279 -0
  124. nautobot/core/ui/object_detail.py +1841 -0
  125. nautobot/core/ui/utils.py +36 -0
  126. nautobot/core/urls.py +4 -9
  127. nautobot/core/utils/config.py +30 -3
  128. nautobot/core/utils/lookup.py +20 -13
  129. nautobot/core/views/__init__.py +6 -1
  130. nautobot/core/views/generic.py +47 -52
  131. nautobot/core/views/mixins.py +15 -25
  132. nautobot/core/views/paginator.py +8 -5
  133. nautobot/core/views/renderers.py +3 -3
  134. nautobot/core/views/utils.py +11 -0
  135. nautobot/core/wsgi.py +3 -3
  136. nautobot/dcim/api/serializers.py +80 -179
  137. nautobot/dcim/api/urls.py +5 -0
  138. nautobot/dcim/api/views.py +17 -4
  139. nautobot/dcim/apps.py +1 -0
  140. nautobot/dcim/choices.py +28 -0
  141. nautobot/dcim/factory.py +58 -0
  142. nautobot/dcim/filters/__init__.py +197 -24
  143. nautobot/dcim/forms.py +203 -12
  144. nautobot/dcim/graphql/types.py +2 -2
  145. nautobot/dcim/migrations/0063_interfacevdcassignment_virtualdevicecontext_and_more.py +165 -0
  146. nautobot/dcim/migrations/0064_virtualdevicecontext_status_data_migration.py +28 -0
  147. nautobot/dcim/migrations/0065_controller_capabilities_and_more.py +29 -0
  148. nautobot/dcim/migrations/0066_controllermanageddevicegroup_radio_profiles_and_more.py +33 -0
  149. nautobot/dcim/models/__init__.py +4 -0
  150. nautobot/dcim/models/device_component_templates.py +2 -2
  151. nautobot/dcim/models/device_components.py +20 -22
  152. nautobot/dcim/models/devices.py +173 -4
  153. nautobot/dcim/models/locations.py +3 -3
  154. nautobot/dcim/models/power.py +5 -6
  155. nautobot/dcim/models/racks.py +6 -6
  156. nautobot/dcim/navigation.py +25 -224
  157. nautobot/dcim/signals.py +44 -0
  158. nautobot/dcim/tables/__init__.py +5 -3
  159. nautobot/dcim/tables/devices.py +96 -2
  160. nautobot/dcim/tables/devicetypes.py +2 -2
  161. nautobot/dcim/templates/dcim/controller/base.html +10 -0
  162. nautobot/dcim/templates/dcim/controller_create.html +1 -0
  163. nautobot/dcim/templates/dcim/controller_retrieve.html +5 -1
  164. nautobot/dcim/templates/dcim/controller_wirelessnetworks.html +25 -0
  165. nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +66 -0
  166. nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +46 -0
  167. nautobot/dcim/templates/dcim/device/base.html +6 -42
  168. nautobot/dcim/templates/dcim/device/wireless.html +73 -0
  169. nautobot/dcim/templates/dcim/device.html +3 -1
  170. nautobot/dcim/templates/dcim/interface.html +1 -0
  171. nautobot/dcim/templates/dcim/interface_edit.html +1 -0
  172. nautobot/dcim/templates/dcim/locationtype.html +0 -107
  173. nautobot/dcim/templates/dcim/locationtype_retrieve.html +8 -0
  174. nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +76 -0
  175. nautobot/dcim/templates/dcim/virtualdevicecontext_update.html +34 -0
  176. nautobot/dcim/tests/test_api.py +172 -61
  177. nautobot/dcim/tests/test_filters.py +171 -109
  178. nautobot/dcim/tests/test_forms.py +2 -51
  179. nautobot/dcim/tests/test_graphql.py +0 -52
  180. nautobot/dcim/tests/test_models.py +126 -4
  181. nautobot/dcim/tests/test_signals.py +1 -0
  182. nautobot/dcim/tests/test_views.py +103 -11
  183. nautobot/dcim/urls.py +72 -27
  184. nautobot/dcim/utils.py +2 -2
  185. nautobot/dcim/views.py +369 -62
  186. nautobot/extras/api/customfields.py +2 -2
  187. nautobot/extras/api/serializers.py +91 -75
  188. nautobot/extras/api/urls.py +4 -0
  189. nautobot/extras/api/views.py +78 -15
  190. nautobot/extras/choices.py +13 -0
  191. nautobot/extras/constants.py +0 -1
  192. nautobot/extras/context_managers.py +23 -6
  193. nautobot/extras/datasources/git.py +4 -1
  194. nautobot/extras/factory.py +27 -0
  195. nautobot/extras/filters/__init__.py +59 -0
  196. nautobot/extras/forms/forms.py +125 -30
  197. nautobot/extras/forms/mixins.py +3 -11
  198. nautobot/extras/graphql/types.py +25 -1
  199. nautobot/extras/group_sync.py +3 -3
  200. nautobot/extras/health_checks.py +2 -1
  201. nautobot/extras/jobs.py +62 -26
  202. nautobot/extras/management/__init__.py +1 -0
  203. nautobot/extras/management/commands/runjob.py +7 -79
  204. nautobot/extras/management/commands/runjob_with_job_result.py +46 -0
  205. nautobot/extras/management/utils.py +87 -0
  206. nautobot/extras/managers.py +1 -3
  207. nautobot/extras/migrations/0018_joblog_data_migration.py +9 -7
  208. nautobot/extras/migrations/0117_create_job_queue_model.py +129 -0
  209. nautobot/extras/migrations/0118_task_queue_to_job_queue_migration.py +78 -0
  210. nautobot/extras/migrations/0119_remove_task_queues_from_job_and_queue_from_scheduled_job.py +28 -0
  211. nautobot/extras/models/__init__.py +4 -0
  212. nautobot/extras/models/change_logging.py +7 -3
  213. nautobot/extras/models/customfields.py +11 -12
  214. nautobot/extras/models/groups.py +9 -13
  215. nautobot/extras/models/jobs.py +218 -37
  216. nautobot/extras/models/models.py +2 -2
  217. nautobot/extras/models/relationships.py +69 -1
  218. nautobot/extras/models/secrets.py +5 -0
  219. nautobot/extras/navigation.py +20 -262
  220. nautobot/extras/plugins/__init__.py +56 -32
  221. nautobot/extras/plugins/marketplace_manifest.yml +450 -0
  222. nautobot/extras/plugins/urls.py +1 -0
  223. nautobot/extras/plugins/views.py +48 -1
  224. nautobot/extras/signals.py +39 -1
  225. nautobot/extras/tables.py +40 -6
  226. nautobot/extras/templates/extras/externalintegration_retrieve.html +0 -47
  227. nautobot/extras/templates/extras/inc/tags_panel.html +1 -5
  228. nautobot/extras/templates/extras/job_bulk_edit.html +2 -1
  229. nautobot/extras/templates/extras/job_detail.html +36 -6
  230. nautobot/extras/templates/extras/job_edit.html +5 -2
  231. nautobot/extras/templates/extras/job_list.html +2 -7
  232. nautobot/extras/templates/extras/jobqueue_retrieve.html +44 -0
  233. nautobot/extras/templates/extras/marketplace.html +278 -0
  234. nautobot/extras/templates/extras/plugins_list.html +35 -1
  235. nautobot/extras/templates/extras/plugins_tiles.html +79 -0
  236. nautobot/extras/templates/extras/role_retrieve.html +16 -0
  237. nautobot/extras/templates/extras/secret.html +0 -65
  238. nautobot/extras/templates/extras/secret_check.js +16 -0
  239. nautobot/extras/templates/extras/secret_create.html +114 -0
  240. nautobot/extras/templates/extras/secret_edit.html +1 -114
  241. nautobot/extras/templates/extras/secretsgroup_edit.html +1 -1
  242. nautobot/extras/templates/extras/templatetags/plugin_object_detail_tabs.html +2 -0
  243. nautobot/extras/templatetags/job_buttons.py +5 -4
  244. nautobot/extras/templatetags/plugins.py +69 -6
  245. nautobot/extras/test_jobs/api_test_job.py +1 -1
  246. nautobot/extras/test_jobs/atomic_transaction.py +2 -2
  247. nautobot/extras/test_jobs/dry_run.py +1 -1
  248. nautobot/extras/test_jobs/fail.py +5 -5
  249. nautobot/extras/test_jobs/file_output.py +1 -1
  250. nautobot/extras/test_jobs/file_upload_fail.py +1 -1
  251. nautobot/extras/test_jobs/file_upload_pass.py +1 -1
  252. nautobot/extras/test_jobs/ipaddress_vars.py +1 -3
  253. nautobot/extras/test_jobs/jobs_module/jobs_submodule/jobs.py +1 -1
  254. nautobot/extras/test_jobs/location_with_custom_field.py +1 -1
  255. nautobot/extras/test_jobs/log_redaction.py +1 -1
  256. nautobot/extras/test_jobs/log_skip_db_logging.py +1 -1
  257. nautobot/extras/test_jobs/modify_db.py +1 -1
  258. nautobot/extras/test_jobs/object_var_optional.py +1 -1
  259. nautobot/extras/test_jobs/object_var_required.py +1 -1
  260. nautobot/extras/test_jobs/object_vars.py +1 -1
  261. nautobot/extras/test_jobs/pass.py +3 -3
  262. nautobot/extras/test_jobs/profiling.py +1 -1
  263. nautobot/extras/test_jobs/relative_import.py +3 -3
  264. nautobot/extras/test_jobs/soft_time_limit_greater_than_time_limit.py +1 -1
  265. nautobot/extras/test_jobs/task_queues.py +1 -1
  266. nautobot/extras/tests/integration/test_plugin_banner.py +2 -0
  267. nautobot/extras/tests/test_api.py +157 -55
  268. nautobot/extras/tests/test_context_managers.py +4 -1
  269. nautobot/extras/tests/test_customfields.py +1 -1
  270. nautobot/extras/tests/test_datasources.py +1 -2
  271. nautobot/extras/tests/test_dynamicgroups.py +1 -1
  272. nautobot/extras/tests/test_filters.py +219 -535
  273. nautobot/extras/tests/test_forms.py +1 -20
  274. nautobot/extras/tests/test_job_variables.py +73 -152
  275. nautobot/extras/tests/test_jobs.py +43 -54
  276. nautobot/extras/tests/test_models.py +71 -16
  277. nautobot/extras/tests/test_relationships.py +5 -2
  278. nautobot/extras/tests/test_utils.py +23 -2
  279. nautobot/extras/tests/test_views.py +183 -43
  280. nautobot/extras/tests/test_webhooks.py +2 -1
  281. nautobot/extras/urls.py +2 -20
  282. nautobot/extras/utils.py +118 -4
  283. nautobot/extras/views.py +203 -92
  284. nautobot/extras/webhooks.py +5 -2
  285. nautobot/ipam/api/fields.py +3 -3
  286. nautobot/ipam/api/serializers.py +36 -137
  287. nautobot/ipam/api/views.py +93 -62
  288. nautobot/ipam/lookups.py +62 -101
  289. nautobot/ipam/models.py +11 -63
  290. nautobot/ipam/navigation.py +0 -90
  291. nautobot/ipam/querysets.py +2 -2
  292. nautobot/ipam/tables.py +6 -20
  293. nautobot/ipam/templates/ipam/routetarget.html +0 -28
  294. nautobot/ipam/templates/ipam/vrf.html +0 -47
  295. nautobot/ipam/tests/test_api.py +8 -419
  296. nautobot/ipam/tests/test_filters.py +39 -119
  297. nautobot/ipam/tests/test_forms.py +47 -51
  298. nautobot/ipam/tests/test_migrations.py +30 -30
  299. nautobot/ipam/tests/test_models.py +0 -41
  300. nautobot/ipam/tests/test_querysets.py +1 -63
  301. nautobot/ipam/urls.py +3 -69
  302. nautobot/ipam/utils/__init__.py +0 -24
  303. nautobot/ipam/views.py +153 -198
  304. nautobot/project-static/css/base.css +38 -3
  305. nautobot/project-static/docs/404.html +421 -19
  306. nautobot/project-static/docs/apps/index.html +421 -19
  307. nautobot/project-static/docs/apps/nautobot-apps.html +421 -19
  308. nautobot/project-static/docs/assets/extra.css +5 -1
  309. nautobot/project-static/docs/assets/javascripts/{bundle.88dd0f4e.min.js → bundle.83f73b43.min.js} +2 -2
  310. nautobot/project-static/docs/assets/javascripts/{bundle.88dd0f4e.min.js.map → bundle.83f73b43.min.js.map} +2 -2
  311. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +421 -19
  312. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +421 -19
  313. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +421 -172
  314. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +421 -19
  315. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +421 -19
  316. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +425 -21
  317. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +421 -19
  318. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +424 -22
  319. nautobot/project-static/docs/code-reference/nautobot/apps/events.html +9809 -0
  320. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +424 -63
  321. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +421 -19
  322. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +421 -19
  323. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +457 -20
  324. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +421 -19
  325. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +425 -25
  326. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +457 -19
  327. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +421 -19
  328. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +421 -19
  329. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +425 -215
  330. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +430 -342
  331. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +5799 -1054
  332. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +421 -19
  333. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +447 -176
  334. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +460 -21
  335. nautobot/project-static/docs/development/apps/api/configuration-view.html +421 -19
  336. nautobot/project-static/docs/development/apps/api/database-backend-config.html +421 -19
  337. nautobot/project-static/docs/development/apps/api/models/django-admin.html +421 -19
  338. nautobot/project-static/docs/development/apps/api/models/global-search.html +421 -19
  339. nautobot/project-static/docs/development/apps/api/models/graphql.html +421 -19
  340. nautobot/project-static/docs/development/apps/api/models/index.html +421 -19
  341. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +421 -19
  342. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +421 -19
  343. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +421 -19
  344. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +421 -19
  345. nautobot/project-static/docs/development/apps/api/platform-features/index.html +421 -19
  346. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +421 -19
  347. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +421 -19
  348. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +421 -19
  349. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +421 -19
  350. nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +424 -41
  351. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +421 -19
  352. nautobot/project-static/docs/development/apps/api/prometheus.html +421 -19
  353. nautobot/project-static/docs/development/apps/api/setup.html +425 -155
  354. nautobot/project-static/docs/development/apps/api/testing.html +421 -19
  355. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +421 -19
  356. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +421 -19
  357. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +421 -19
  358. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +421 -19
  359. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +701 -130
  360. nautobot/project-static/docs/development/apps/api/views/base-template.html +421 -19
  361. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +421 -19
  362. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +421 -19
  363. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +421 -19
  364. nautobot/project-static/docs/development/apps/api/views/index.html +423 -20
  365. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +425 -19
  366. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +451 -19
  367. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +421 -19
  368. nautobot/project-static/docs/development/apps/api/views/notes.html +421 -19
  369. nautobot/project-static/docs/development/apps/api/views/rest-api.html +421 -19
  370. nautobot/project-static/docs/development/apps/api/views/urls.html +421 -19
  371. nautobot/project-static/docs/development/apps/index.html +421 -19
  372. nautobot/project-static/docs/development/apps/migration/code-updates.html +422 -52
  373. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +422 -20
  374. nautobot/project-static/docs/development/apps/migration/from-v1.html +421 -19
  375. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +421 -19
  376. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +421 -19
  377. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +421 -19
  378. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +424 -22
  379. nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +9219 -0
  380. nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +9333 -0
  381. nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +9474 -0
  382. nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +9517 -0
  383. nautobot/project-static/docs/development/apps/porting-from-netbox.html +424 -22
  384. nautobot/project-static/docs/development/core/application-registry.html +421 -19
  385. nautobot/project-static/docs/development/core/best-practices.html +421 -19
  386. nautobot/project-static/docs/development/core/bootstrap-ui.html +421 -19
  387. nautobot/project-static/docs/development/core/caching.html +421 -19
  388. nautobot/project-static/docs/development/core/controllers.html +423 -19
  389. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +490 -45
  390. nautobot/project-static/docs/development/core/generic-views.html +421 -19
  391. nautobot/project-static/docs/development/core/getting-started.html +566 -179
  392. nautobot/project-static/docs/development/core/homepage.html +432 -30
  393. nautobot/project-static/docs/development/core/index.html +421 -19
  394. nautobot/project-static/docs/development/core/local-k8s.html +9453 -0
  395. nautobot/project-static/docs/development/core/model-checklist.html +424 -22
  396. nautobot/project-static/docs/development/core/model-features.html +421 -19
  397. nautobot/project-static/docs/development/core/natural-keys.html +421 -19
  398. nautobot/project-static/docs/development/core/navigation-menu.html +438 -26
  399. nautobot/project-static/docs/development/core/release-checklist.html +435 -45
  400. nautobot/project-static/docs/development/core/role-internals.html +421 -19
  401. nautobot/project-static/docs/development/core/settings.html +421 -19
  402. nautobot/project-static/docs/development/core/style-guide.html +421 -19
  403. nautobot/project-static/docs/development/core/templates.html +431 -22
  404. nautobot/project-static/docs/development/core/testing.html +421 -19
  405. nautobot/project-static/docs/development/core/ui-component-framework.html +11020 -0
  406. nautobot/project-static/docs/development/core/user-preferences.html +424 -22
  407. nautobot/project-static/docs/development/index.html +421 -19
  408. nautobot/project-static/docs/development/jobs/index.html +546 -160
  409. nautobot/project-static/docs/development/jobs/migration/from-v1.html +421 -19
  410. nautobot/project-static/docs/index.html +421 -19
  411. nautobot/project-static/docs/media/development/core/ui-component-framework/basic-panel-layout.png +0 -0
  412. nautobot/project-static/docs/media/development/core/ui-component-framework/button-example.png +0 -0
  413. nautobot/project-static/docs/media/development/core/ui-component-framework/dropdown-button-example.png +0 -0
  414. nautobot/project-static/docs/media/development/core/ui-component-framework/grouped-key-value-table-panel-example-1.png +0 -0
  415. nautobot/project-static/docs/media/development/core/ui-component-framework/grouped-key-value-table-panel-example-2.png +0 -0
  416. nautobot/project-static/docs/media/development/core/ui-component-framework/object-fields-panel-example.png +0 -0
  417. nautobot/project-static/docs/media/development/core/ui-component-framework/stats-panel-example.png +0 -0
  418. nautobot/project-static/docs/media/development/core/ui-component-framework/table-panels-family.png +0 -0
  419. nautobot/project-static/docs/media/development/core/ui-component-framework/text-panels-family.png +0 -0
  420. nautobot/project-static/docs/media/development/core/ui-component-framework/ui-framework-example.png +0 -0
  421. nautobot/project-static/docs/media/models/virtual_device_context_overview.drawio +73 -0
  422. nautobot/project-static/docs/media/models/virtual_device_context_overview.png +0 -0
  423. nautobot/project-static/docs/models/dcim/virtualdevicecontext.html +14 -0
  424. nautobot/project-static/docs/models/extras/jobqueue.html +14 -0
  425. nautobot/project-static/docs/models/wireless/radioprofile.html +14 -0
  426. nautobot/project-static/docs/models/wireless/supporteddatarate.html +14 -0
  427. nautobot/project-static/docs/models/wireless/wirelessnetwork.html +14 -0
  428. nautobot/project-static/docs/objects.inv +0 -0
  429. nautobot/project-static/docs/overview/application_stack.html +426 -20
  430. nautobot/project-static/docs/overview/design_philosophy.html +421 -19
  431. nautobot/project-static/docs/release-notes/index.html +445 -22
  432. nautobot/project-static/docs/release-notes/version-1.0.html +421 -19
  433. nautobot/project-static/docs/release-notes/version-1.1.html +421 -19
  434. nautobot/project-static/docs/release-notes/version-1.2.html +421 -19
  435. nautobot/project-static/docs/release-notes/version-1.3.html +421 -19
  436. nautobot/project-static/docs/release-notes/version-1.4.html +421 -19
  437. nautobot/project-static/docs/release-notes/version-1.5.html +421 -19
  438. nautobot/project-static/docs/release-notes/version-1.6.html +634 -667
  439. nautobot/project-static/docs/release-notes/version-2.0.html +421 -19
  440. nautobot/project-static/docs/release-notes/version-2.1.html +421 -19
  441. nautobot/project-static/docs/release-notes/version-2.2.html +421 -19
  442. nautobot/project-static/docs/release-notes/version-2.3.html +684 -886
  443. nautobot/project-static/docs/release-notes/version-2.4.html +10007 -0
  444. nautobot/project-static/docs/requirements.txt +2 -2
  445. nautobot/project-static/docs/search/search_index.json +1 -1
  446. nautobot/project-static/docs/sitemap.xml +334 -270
  447. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  448. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +421 -19
  449. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +421 -19
  450. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +423 -21
  451. nautobot/project-static/docs/user-guide/administration/configuration/index.html +433 -32
  452. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +421 -19
  453. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +765 -180
  454. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +421 -19
  455. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +421 -19
  456. nautobot/project-static/docs/user-guide/administration/guides/docker.html +434 -29
  457. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +421 -19
  458. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +421 -19
  459. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +421 -19
  460. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +421 -19
  461. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +421 -19
  462. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +421 -19
  463. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +421 -19
  464. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +421 -19
  465. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +421 -19
  466. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +421 -19
  467. nautobot/project-static/docs/user-guide/administration/installation/index.html +426 -20
  468. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +421 -19
  469. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +421 -19
  470. nautobot/project-static/docs/user-guide/administration/installation/services.html +421 -19
  471. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +421 -19
  472. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +442 -41
  473. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +435 -66
  474. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +435 -66
  475. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +421 -19
  476. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +421 -19
  477. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +421 -19
  478. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +421 -19
  479. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +421 -19
  480. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +421 -19
  481. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +421 -19
  482. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/tables/v2-code-nautobot-app-location.yaml +0 -16
  483. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +421 -19
  484. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +427 -21
  485. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +421 -19
  486. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +421 -19
  487. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +421 -19
  488. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +421 -19
  489. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +421 -19
  490. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +421 -19
  491. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +421 -19
  492. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +421 -19
  493. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +421 -19
  494. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +421 -19
  495. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +421 -19
  496. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +421 -19
  497. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +421 -19
  498. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +421 -19
  499. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +421 -19
  500. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +421 -19
  501. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +421 -19
  502. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +457 -20
  503. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +447 -22
  504. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +421 -19
  505. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +421 -19
  506. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +421 -19
  507. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +421 -19
  508. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +421 -19
  509. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +421 -19
  510. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +421 -19
  511. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +421 -19
  512. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +421 -19
  513. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +421 -19
  514. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +421 -19
  515. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +421 -19
  516. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +421 -19
  517. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +421 -19
  518. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +421 -19
  519. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +421 -19
  520. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +421 -19
  521. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +421 -19
  522. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +421 -19
  523. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +421 -19
  524. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +421 -19
  525. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +421 -19
  526. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +421 -19
  527. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +421 -19
  528. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +421 -19
  529. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +421 -19
  530. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +421 -19
  531. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +421 -19
  532. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +421 -19
  533. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +421 -19
  534. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +421 -19
  535. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +421 -19
  536. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +421 -19
  537. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +421 -19
  538. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +9333 -0
  539. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +424 -22
  540. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +421 -19
  541. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +421 -19
  542. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +421 -19
  543. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +421 -19
  544. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +421 -19
  545. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +421 -19
  546. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +421 -19
  547. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +421 -19
  548. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +421 -19
  549. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +421 -19
  550. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +421 -19
  551. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +421 -19
  552. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +421 -19
  553. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +421 -19
  554. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +421 -19
  555. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +421 -19
  556. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +421 -19
  557. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +421 -19
  558. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +421 -19
  559. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +424 -22
  560. nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +9271 -0
  561. nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +9175 -0
  562. nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +9169 -0
  563. nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +9235 -0
  564. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +421 -19
  565. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +421 -19
  566. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +421 -19
  567. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +421 -19
  568. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +421 -19
  569. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +421 -19
  570. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +421 -19
  571. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +421 -19
  572. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +421 -19
  573. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +421 -19
  574. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +421 -19
  575. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +421 -19
  576. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +421 -19
  577. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +421 -19
  578. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +421 -19
  579. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +421 -19
  580. nautobot/project-static/docs/user-guide/index.html +421 -19
  581. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +424 -22
  582. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +421 -19
  583. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +421 -19
  584. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +421 -19
  585. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +421 -19
  586. nautobot/project-static/docs/user-guide/platform-functionality/events.html +9575 -0
  587. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +424 -22
  588. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +421 -19
  589. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +421 -19
  590. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +421 -19
  591. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +421 -19
  592. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +421 -19
  593. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +426 -20
  594. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +424 -22
  595. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +421 -19
  596. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +421 -19
  597. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +9182 -0
  598. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +424 -22
  599. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +421 -19
  600. nautobot/project-static/docs/user-guide/platform-functionality/note.html +421 -19
  601. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +421 -19
  602. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +424 -22
  603. nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +9250 -0
  604. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +421 -19
  605. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +421 -19
  606. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +424 -22
  607. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +421 -19
  608. nautobot/project-static/docs/user-guide/platform-functionality/role.html +421 -19
  609. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +421 -19
  610. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +421 -19
  611. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +424 -22
  612. nautobot/project-static/docs/user-guide/platform-functionality/status.html +421 -19
  613. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +421 -19
  614. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +489 -56
  615. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +421 -19
  616. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +421 -19
  617. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +421 -19
  618. nautobot/project-static/img/jinja_logo.svg +97 -0
  619. nautobot/project-static/js/forms.js +5 -0
  620. nautobot/project-static/js/nav_menu.js +2 -1
  621. nautobot/tenancy/api/serializers.py +0 -2
  622. nautobot/tenancy/factory.py +1 -1
  623. nautobot/tenancy/navigation.py +0 -29
  624. nautobot/tenancy/templates/tenancy/tenant.html +4 -91
  625. nautobot/tenancy/tests/test_filters.py +29 -134
  626. nautobot/tenancy/views.py +32 -23
  627. nautobot/users/admin.py +3 -1
  628. nautobot/users/api/serializers.py +4 -5
  629. nautobot/users/api/views.py +1 -1
  630. nautobot/users/forms.py +19 -0
  631. nautobot/users/templates/users/preferences.html +22 -0
  632. nautobot/users/tests/test_filters.py +1 -19
  633. nautobot/users/tests/test_views.py +57 -0
  634. nautobot/users/utils.py +8 -0
  635. nautobot/users/views.py +48 -11
  636. nautobot/virtualization/api/serializers.py +4 -4
  637. nautobot/virtualization/filters.py +2 -20
  638. nautobot/virtualization/navigation.py +0 -48
  639. nautobot/virtualization/templates/virtualization/clustertype.html +0 -39
  640. nautobot/virtualization/tests/test_filters.py +57 -183
  641. nautobot/virtualization/views.py +18 -15
  642. nautobot/wireless/__init__.py +0 -0
  643. nautobot/wireless/api/__init__.py +0 -0
  644. nautobot/wireless/api/serializers.py +44 -0
  645. nautobot/wireless/api/urls.py +20 -0
  646. nautobot/wireless/api/views.py +34 -0
  647. nautobot/wireless/apps.py +8 -0
  648. nautobot/wireless/choices.py +345 -0
  649. nautobot/wireless/factory.py +138 -0
  650. nautobot/wireless/filters.py +167 -0
  651. nautobot/wireless/forms.py +283 -0
  652. nautobot/wireless/homepage.py +19 -0
  653. nautobot/wireless/migrations/0001_initial.py +223 -0
  654. nautobot/wireless/migrations/__init__.py +0 -0
  655. nautobot/wireless/models.py +207 -0
  656. nautobot/wireless/navigation.py +105 -0
  657. nautobot/wireless/tables.py +244 -0
  658. nautobot/wireless/templates/wireless/radioprofile_retrieve.html +81 -0
  659. nautobot/wireless/templates/wireless/supporteddatarate_retrieve.html +26 -0
  660. nautobot/wireless/templates/wireless/wirelessnetwork_create.html +88 -0
  661. nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +64 -0
  662. nautobot/wireless/tests/__init__.py +0 -0
  663. nautobot/wireless/tests/test_api.py +247 -0
  664. nautobot/wireless/tests/test_filters.py +54 -0
  665. nautobot/wireless/tests/test_models.py +22 -0
  666. nautobot/wireless/tests/test_views.py +378 -0
  667. nautobot/wireless/urls.py +13 -0
  668. nautobot/wireless/views.py +129 -0
  669. {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/METADATA +11 -14
  670. {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/RECORD +674 -551
  671. {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/WHEEL +1 -1
  672. nautobot/core/utils/navigation.py +0 -54
  673. {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/LICENSE.txt +0 -0
  674. {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/NOTICE +0 -0
  675. {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/entry_points.txt +0 -0
@@ -6,6 +6,7 @@ from django.contrib.auth.models import AnonymousUser
6
6
  from django.db import transaction
7
7
  from django.test.client import RequestFactory
8
8
 
9
+ from nautobot.core.events import publish_event
9
10
  from nautobot.extras.choices import ObjectChangeEventContextChoices
10
11
  from nautobot.extras.constants import CHANGELOG_MAX_CHANGE_CONTEXT_DETAIL
11
12
  from nautobot.extras.models import ObjectChange
@@ -211,27 +212,43 @@ def web_request_context(
211
212
  last_action = None
212
213
  last_content_type = None
213
214
  # enqueue jobhooks and webhooks, use change_context.change_id in case change_id was not supplied
214
- for object_change in (
215
+ for oc in (
215
216
  ObjectChange.objects.select_related("changed_object_type", "user")
216
217
  .filter(request_id=change_context.change_id)
217
218
  .order_by("time") # default ordering is -time but we want oldest first not newest first
218
219
  .iterator()
219
220
  ):
220
- if object_change.action != last_action or object_change.changed_object_type != last_content_type:
221
+ if oc.action != last_action or oc.changed_object_type != last_content_type:
221
222
  jobhook_queryset = None
222
223
  webhook_queryset = None
223
224
 
224
225
  if context != ObjectChangeEventContextChoices.CONTEXT_JOB_HOOK:
225
226
  # Make sure JobHooks are up to date (only once) before calling them
226
227
  did_reload_jobs, jobhook_queryset = enqueue_job_hooks(
227
- object_change, may_reload_jobs=(not jobs_reloaded), jobhook_queryset=jobhook_queryset
228
+ oc, may_reload_jobs=(not jobs_reloaded), jobhook_queryset=jobhook_queryset
228
229
  )
229
230
  if did_reload_jobs:
230
231
  jobs_reloaded = True
231
232
 
232
- webhook_queryset = enqueue_webhooks(object_change, webhook_queryset=webhook_queryset)
233
- last_action = object_change.action
234
- last_content_type = object_change.changed_object_type
233
+ # TODO: get_snapshots() currently requires a DB query per object change processed.
234
+ # We need to develop a more efficient approach: https://github.com/nautobot/nautobot/issues/6303
235
+ snapshots = oc.get_snapshots()
236
+ webhook_queryset = enqueue_webhooks(oc, snapshots=snapshots, webhook_queryset=webhook_queryset)
237
+
238
+ # topic examples: "nautobot.change.dcim.device", "nautobot.add.ipam.ipaddress"
239
+ event_topic = f"nautobot.{oc.action}.{oc.changed_object_type.app_label}.{oc.changed_object_type.model}"
240
+ event_payload = snapshots.copy()
241
+ event_payload["context"] = {
242
+ "change_context": oc.get_change_context_display(),
243
+ "change_context_detail": oc.change_context_detail,
244
+ "request_id": str(oc.request_id),
245
+ "user_name": oc.user_name,
246
+ "timestamp": str(oc.time),
247
+ }
248
+ publish_event(topic=event_topic, payload=event_payload)
249
+
250
+ last_action = oc.action
251
+ last_content_type = oc.changed_object_type
235
252
 
236
253
 
237
254
  @contextmanager
@@ -31,6 +31,7 @@ from nautobot.extras.models import (
31
31
  ExportTemplate,
32
32
  GitRepository,
33
33
  Job,
34
+ JobQueue,
34
35
  JobResult,
35
36
  Role,
36
37
  Tag,
@@ -763,7 +764,9 @@ def refresh_git_jobs(repository_record, job_result, delete=False):
763
764
  if not job_class_path.startswith(f"{repository_record.slug}.jobs."):
764
765
  continue
765
766
  found_jobs = True
766
- job_model, created = refresh_job_model_from_job_class(Job, job_class)
767
+ job_model, created = refresh_job_model_from_job_class(
768
+ job_model_class=Job, job_class=job_class, job_queue_class=JobQueue
769
+ )
767
770
 
768
771
  if job_model is None:
769
772
  msg = "Failed to create Job record; check Nautobot logs for details"
@@ -20,6 +20,7 @@ from nautobot.core.factory import (
20
20
  from nautobot.core.templatetags.helpers import bettertitle
21
21
  from nautobot.extras.choices import (
22
22
  DynamicGroupTypeChoices,
23
+ JobQueueTypeChoices,
23
24
  JobResultStatusChoices,
24
25
  LogLevelChoices,
25
26
  MetadataTypeDataTypeChoices,
@@ -34,6 +35,7 @@ from nautobot.extras.models import (
34
35
  ExternalIntegration,
35
36
  Job,
36
37
  JobLogEntry,
38
+ JobQueue,
37
39
  JobResult,
38
40
  MetadataChoice,
39
41
  MetadataType,
@@ -140,6 +142,31 @@ class JobLogEntryFactory(BaseModelFactory):
140
142
  return faker.Faker().past_datetime(start_date=self.job_result.date_created, tzinfo=timezone.utc)
141
143
 
142
144
 
145
+ class JobQueueFactory(PrimaryModelFactory):
146
+ """JobQueue model Factory"""
147
+
148
+ class Meta:
149
+ model = JobQueue
150
+
151
+ class Params:
152
+ has_description = NautobotBoolIterator()
153
+ has_tenant = NautobotBoolIterator()
154
+
155
+ name = factory.LazyAttributeSequence(lambda o, n: f"{o.queue_type} Job Queue - {n}")
156
+ description = factory.Maybe("has_description", factory.Faker("text", max_nb_chars=CHARFIELD_MAX_LENGTH), "")
157
+ queue_type = factory.Iterator(JobQueueTypeChoices.CHOICES, getter=lambda choice: choice[0])
158
+ tenant = factory.Maybe("has_tenant", random_instance(Tenant))
159
+
160
+ @factory.post_generation
161
+ def jobs(self, create, extracted, **kwargs):
162
+ jobs = get_random_instances(Job)
163
+ self.jobs.set(jobs)
164
+ for job in jobs:
165
+ if not job.job_queues_override:
166
+ job.job_queues_override = True
167
+ job.validated_save()
168
+
169
+
143
170
  class JobResultFactory(BaseModelFactory):
144
171
  """JobResult model factory."""
145
172
 
@@ -23,6 +23,7 @@ from nautobot.core.filters import (
23
23
  from nautobot.core.utils.deprecation import class_deprecated_in_favor_of
24
24
  from nautobot.dcim.models import DeviceRedundancyGroup, DeviceType, Location, Platform
25
25
  from nautobot.extras.choices import (
26
+ JobQueueTypeChoices,
26
27
  JobResultStatusChoices,
27
28
  MetadataTypeDataTypeChoices,
28
29
  RelationshipTypeChoices,
@@ -73,6 +74,8 @@ from nautobot.extras.models import (
73
74
  JobButton,
74
75
  JobHook,
75
76
  JobLogEntry,
77
+ JobQueue,
78
+ JobQueueAssignment,
76
79
  JobResult,
77
80
  MetadataChoice,
78
81
  MetadataType,
@@ -133,6 +136,8 @@ __all__ = (
133
136
  "ImageAttachmentFilterSet",
134
137
  "JobFilterSet",
135
138
  "JobLogEntryFilterSet",
139
+ "JobQueueFilterSet",
140
+ "JobQueueAssignmentFilterSet",
136
141
  "JobResultFilterSet",
137
142
  "LocalContextFilterSet",
138
143
  "LocalContextModelFilterSetMixin",
@@ -906,6 +911,60 @@ class JobHookFilterSet(BaseFilterSet):
906
911
  ]
907
912
 
908
913
 
914
+ class JobQueueFilterSet(NautobotFilterSet, TenancyModelFilterSetMixin):
915
+ q = SearchFilter(
916
+ filter_predicates={
917
+ "name": "icontains",
918
+ "queue_type": "icontains",
919
+ "description": "icontains",
920
+ "tenant__name": "icontains",
921
+ },
922
+ )
923
+ queue_type = django_filters.MultipleChoiceFilter(choices=JobQueueTypeChoices, null_value=None)
924
+ jobs = NaturalKeyOrPKMultipleChoiceFilter(
925
+ queryset=Job.objects.all(),
926
+ label="Job (name or ID)",
927
+ )
928
+ has_jobs = RelatedMembershipBooleanFilter(
929
+ field_name="jobs",
930
+ label="Has jobs",
931
+ )
932
+
933
+ class Meta:
934
+ model = JobQueue
935
+ fields = [
936
+ "id",
937
+ "name",
938
+ "description",
939
+ "tags",
940
+ ]
941
+
942
+
943
+ class JobQueueAssignmentFilterSet(BaseFilterSet):
944
+ q = SearchFilter(
945
+ filter_predicates={
946
+ "job__name": "icontains",
947
+ "job__grouping": "icontains",
948
+ "job__description": "icontains",
949
+ "job_queue__name": "icontains",
950
+ "job_queue__description": "icontains",
951
+ "job_queue__queue_type": "icontains",
952
+ }
953
+ )
954
+ job = NaturalKeyOrPKMultipleChoiceFilter(
955
+ queryset=Job.objects.all(),
956
+ label="Job (name or ID)",
957
+ )
958
+ job_queue = NaturalKeyOrPKMultipleChoiceFilter(
959
+ queryset=JobQueue.objects.all(),
960
+ label="Job Queue (name or ID)",
961
+ )
962
+
963
+ class Meta:
964
+ model = JobQueueAssignment
965
+ fields = ["id"]
966
+
967
+
909
968
  class JobResultFilterSet(BaseFilterSet, CustomFieldModelFilterSetMixin):
910
969
  q = SearchFilter(
911
970
  filter_predicates={
@@ -9,6 +9,7 @@ from django.core.validators import MinValueValidator
9
9
  from django.db.models.fields import TextField
10
10
  from django.forms import inlineformset_factory, ModelMultipleChoiceField
11
11
  from django.urls.base import reverse
12
+ from django.utils.timezone import get_current_timezone_name
12
13
 
13
14
  from nautobot.core.constants import CHARFIELD_MAX_LENGTH
14
15
  from nautobot.core.forms import (
@@ -25,7 +26,6 @@ from nautobot.core.forms import (
25
26
  DateTimePicker,
26
27
  DynamicModelChoiceField,
27
28
  DynamicModelMultipleChoiceField,
28
- JSONArrayFormField,
29
29
  JSONField,
30
30
  LaxURLField,
31
31
  MultipleContentTypeField,
@@ -40,6 +40,7 @@ from nautobot.dcim.models import Device, DeviceRedundancyGroup, DeviceType, Loca
40
40
  from nautobot.extras.choices import (
41
41
  DynamicGroupTypeChoices,
42
42
  JobExecutionType,
43
+ JobQueueTypeChoices,
43
44
  JobResultStatusChoices,
44
45
  ObjectChangeActionChoices,
45
46
  RelationshipTypeChoices,
@@ -65,6 +66,7 @@ from nautobot.extras.models import (
65
66
  Job,
66
67
  JobButton,
67
68
  JobHook,
69
+ JobQueue,
68
70
  JobResult,
69
71
  MetadataChoice,
70
72
  MetadataType,
@@ -106,6 +108,7 @@ from .mixins import (
106
108
  CustomFieldModelFormMixin,
107
109
  NoteModelBulkEditFormMixin,
108
110
  NoteModelFormMixin,
111
+ TagsBulkEditFormMixin,
109
112
  )
110
113
 
111
114
  __all__ = (
@@ -149,6 +152,9 @@ __all__ = (
149
152
  "JobFilterForm",
150
153
  "JobHookForm",
151
154
  "JobHookFilterForm",
155
+ "JobQueueBulkEditForm",
156
+ "JobQueueFilterForm",
157
+ "JobQueueForm",
152
158
  "JobScheduleForm",
153
159
  "JobResultFilterForm",
154
160
  "LocalContextFilterForm",
@@ -945,28 +951,19 @@ class JobForm(BootstrapMixin, forms.Form):
945
951
  controlled by the job definition. See `nautobot.extras.jobs.BaseJob.as_form`
946
952
  """
947
953
 
948
- _profile = forms.BooleanField(
949
- required=False,
950
- initial=False,
951
- label="Profile job execution",
952
- help_text="Profiles the job execution using cProfile and outputs a report to /tmp/",
954
+
955
+ class JobEditForm(NautobotModelForm):
956
+ job_queues = DynamicModelMultipleChoiceField(
957
+ label="Job Queues",
958
+ queryset=JobQueue.objects.all(),
953
959
  )
954
- _task_queue = forms.ChoiceField(
960
+ default_job_queue = DynamicModelChoiceField(
961
+ label="Default Job Queue",
962
+ queryset=JobQueue.objects.all(),
963
+ help_text="The default job queue to route this job to",
955
964
  required=False,
956
- help_text="The task queue to route this job to",
957
- label="Task queue",
958
965
  )
959
966
 
960
- def __init__(self, *args, **kwargs):
961
- super().__init__(*args, **kwargs)
962
-
963
- # Move special fields to the end of the form
964
- for field in ["_task_queue", "_profile"]:
965
- value = self.fields.pop(field)
966
- self.fields[field] = value
967
-
968
-
969
- class JobEditForm(NautobotModelForm):
970
967
  class Meta:
971
968
  model = Job
972
969
  fields = [
@@ -989,8 +986,10 @@ class JobEditForm(NautobotModelForm):
989
986
  "time_limit",
990
987
  "has_sensitive_variables_override",
991
988
  "has_sensitive_variables",
992
- "task_queues_override",
993
- "task_queues",
989
+ "job_queues_override",
990
+ "job_queues",
991
+ "default_job_queue_override",
992
+ "default_job_queue",
994
993
  "tags",
995
994
  ]
996
995
 
@@ -1006,8 +1005,28 @@ class JobEditForm(NautobotModelForm):
1006
1005
  for field_name in JOB_OVERRIDABLE_FIELDS:
1007
1006
  if not cleaned_data.get(f"{field_name}_override", False):
1008
1007
  cleaned_data[field_name] = getattr(job_class, field_name)
1008
+ # Get default Job Queue first
1009
+ if not cleaned_data.get("default_job_queue_override", False):
1010
+ meta_task_queues = getattr(job_class, "task_queues", []) or [settings.CELERY_TASK_DEFAULT_QUEUE]
1011
+ cleaned_data["default_job_queue"], _ = JobQueue.objects.get_or_create(
1012
+ name=meta_task_queues[0], defaults={"queue_type": JobQueueTypeChoices.TYPE_CELERY}
1013
+ )
1014
+ default_job_queue = cleaned_data["default_job_queue"]
1015
+ # Include the default Job Queue in the Job Queues selection
1016
+ if not cleaned_data.get("job_queues_override", False):
1017
+ names = getattr(job_class, "task_queues", []) or [settings.CELERY_TASK_DEFAULT_QUEUE]
1018
+ else:
1019
+ names = list(cleaned_data["job_queues"].values_list("name", flat=True))
1020
+ names += [default_job_queue]
1021
+ cleaned_data["job_queues"] = JobQueue.objects.filter(name__in=names)
1022
+
1009
1023
  return cleaned_data
1010
1024
 
1025
+ def save(self, *args, **kwargs):
1026
+ instance = super().save(*args, **kwargs)
1027
+ instance.job_queues.set(self.cleaned_data["job_queues"])
1028
+ return instance
1029
+
1011
1030
 
1012
1031
  class JobBulkEditForm(NautobotBulkEditForm):
1013
1032
  """Bulk edit form for `Job` objects."""
@@ -1058,10 +1077,17 @@ class JobBulkEditForm(NautobotBulkEditForm):
1058
1077
  help_text="Maximum runtime in seconds before the job will be forcibly terminated."
1059
1078
  "<br>Set to 0 to use Nautobot system default",
1060
1079
  )
1061
- task_queues = JSONArrayFormField(
1062
- base_field=forms.CharField(max_length=CHARFIELD_MAX_LENGTH),
1063
- help_text="Comma separated list of task queues that this job can run on. A blank list will use the default queue",
1080
+ job_queues = DynamicModelMultipleChoiceField(
1081
+ label="Job Queues",
1082
+ queryset=JobQueue.objects.all(),
1083
+ required=False,
1084
+ help_text="Job Queue instances that this job can run on",
1085
+ )
1086
+ default_job_queue = DynamicModelChoiceField(
1087
+ label="Default Job Queue",
1088
+ queryset=JobQueue.objects.all(),
1064
1089
  required=False,
1090
+ help_text="Default Job Queue the job runs on if no Job Queue is specified",
1065
1091
  )
1066
1092
  # Flags to indicate whether the above properties are inherited from the source code or overridden by the database
1067
1093
  # Text field overrides
@@ -1081,9 +1107,13 @@ class JobBulkEditForm(NautobotBulkEditForm):
1081
1107
  required=False,
1082
1108
  help_text="If checked, time limits will be reverted to the default values defined in each Job's source code",
1083
1109
  )
1084
- clear_task_queues_override = forms.BooleanField(
1110
+ clear_job_queues_override = forms.BooleanField(
1085
1111
  required=False,
1086
- help_text="If checked, task queue overrides will be reverted to the default values defined in each Job's source code",
1112
+ help_text="If checked, the selected job queues will be reverted to the default values defined in each Job's source code",
1113
+ )
1114
+ clear_default_job_queue_override = forms.BooleanField(
1115
+ required=False,
1116
+ help_text="If checked, the default job queue will be reverted to the first value of task_queues defined in each Job's source code",
1087
1117
  )
1088
1118
  # Boolean overrides
1089
1119
  clear_approval_required_override = forms.BooleanField(
@@ -1201,6 +1231,64 @@ class JobHookFilterForm(BootstrapMixin, forms.Form):
1201
1231
  type_delete = forms.NullBooleanField(required=False, widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES))
1202
1232
 
1203
1233
 
1234
+ class JobQueueBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm):
1235
+ pk = forms.ModelMultipleChoiceField(
1236
+ queryset=JobQueue.objects.all(),
1237
+ widget=forms.MultipleHiddenInput(),
1238
+ )
1239
+ queue_type = forms.ChoiceField(
1240
+ choices=JobQueueTypeChoices,
1241
+ help_text="The job can either run immediately, once in the future, or on a recurring schedule.",
1242
+ label="Type",
1243
+ required=False,
1244
+ )
1245
+ tenant = DynamicModelChoiceField(
1246
+ queryset=Tenant.objects.all(),
1247
+ required=False,
1248
+ )
1249
+ description = forms.CharField(required=False, max_length=CHARFIELD_MAX_LENGTH)
1250
+
1251
+ class Meta:
1252
+ model = JobQueue
1253
+ nullable_fields = [
1254
+ "secrets_group",
1255
+ "description",
1256
+ "tenant",
1257
+ ]
1258
+
1259
+
1260
+ class JobQueueFilterForm(NautobotFilterForm):
1261
+ model = JobQueue
1262
+ q = forms.CharField(required=False, label="Search")
1263
+ name = forms.CharField(required=False)
1264
+ jobs = DynamicModelMultipleChoiceField(queryset=Job.objects.all(), required=False)
1265
+ queue_type = forms.MultipleChoiceField(
1266
+ choices=JobQueueTypeChoices,
1267
+ required=False,
1268
+ widget=StaticSelect2Multiple(),
1269
+ )
1270
+ tenant = DynamicModelMultipleChoiceField(queryset=Tenant.objects.all(), to_field_name="name", required=False)
1271
+ tags = TagFilterField(model)
1272
+
1273
+
1274
+ class JobQueueForm(NautobotModelForm):
1275
+ name = forms.CharField(required=True, max_length=CHARFIELD_MAX_LENGTH)
1276
+ queue_type = forms.ChoiceField(
1277
+ choices=JobQueueTypeChoices,
1278
+ label="Queue Type",
1279
+ )
1280
+ tenant = DynamicModelChoiceField(
1281
+ queryset=Tenant.objects.all(),
1282
+ required=False,
1283
+ )
1284
+ description = forms.CharField(required=False, max_length=CHARFIELD_MAX_LENGTH)
1285
+ tags = DynamicModelMultipleChoiceField(queryset=Tag.objects.all(), required=False)
1286
+
1287
+ class Meta:
1288
+ model = JobQueue
1289
+ fields = ("name", "queue_type", "description", "tenant", "tags")
1290
+
1291
+
1204
1292
  class JobScheduleForm(BootstrapMixin, forms.Form):
1205
1293
  """
1206
1294
  This form is rendered alongside the JobForm but deals specifically with the fields needed to either
@@ -1223,7 +1311,6 @@ class JobScheduleForm(BootstrapMixin, forms.Form):
1223
1311
  required=False,
1224
1312
  label="Starting date and time",
1225
1313
  widget=DateTimePicker(),
1226
- help_text=f"The scheduled time is relative to the Nautobot configured timezone: {settings.TIME_ZONE}.",
1227
1314
  )
1228
1315
  _recurrence_custom_time = forms.CharField(
1229
1316
  required=False,
@@ -1260,6 +1347,16 @@ class JobScheduleForm(BootstrapMixin, forms.Form):
1260
1347
  except Exception as e:
1261
1348
  raise ValidationError({"_recurrence_custom_time": e})
1262
1349
 
1350
+ def __init__(self, *args, **kwargs):
1351
+ super().__init__(*args, **kwargs)
1352
+ # setting the help_text for `_schedule_start_time` here instead of in the field definition
1353
+ # because Django needs to be fully initialized before we can accurately retrieve the current timezone.
1354
+ self.fields[
1355
+ "_schedule_start_time"
1356
+ ].help_text = (
1357
+ f"The scheduled time is relative to the Nautobot configured timezone: {get_current_timezone_name()}."
1358
+ )
1359
+
1263
1360
 
1264
1361
  class JobResultFilterForm(BootstrapMixin, forms.Form):
1265
1362
  model = JobResult
@@ -1429,7 +1526,7 @@ class MetadataTypeFilterForm(NautobotFilterForm):
1429
1526
  tags = TagFilterField(model)
1430
1527
 
1431
1528
 
1432
- class MetadataTypeBulkEditForm(NautobotBulkEditForm):
1529
+ class MetadataTypeBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm):
1433
1530
  pk = forms.ModelMultipleChoiceField(queryset=MetadataType.objects.all(), widget=forms.MultipleHiddenInput)
1434
1531
  description = forms.CharField(required=False, max_length=CHARFIELD_MAX_LENGTH)
1435
1532
 
@@ -1682,8 +1779,6 @@ class RoleBulkEditForm(NautobotBulkEditForm):
1682
1779
 
1683
1780
  pk = forms.ModelMultipleChoiceField(queryset=Role.objects.all(), widget=forms.MultipleHiddenInput)
1684
1781
  color = forms.CharField(max_length=6, required=False, widget=ColorSelect())
1685
- description = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False)
1686
- weight = forms.IntegerField(required=False)
1687
1782
  content_types = MultipleContentTypeField(
1688
1783
  queryset=RoleModelsQuery().as_queryset(), required=False, label="Content Type(s)"
1689
1784
  )
@@ -837,21 +837,13 @@ class StatusModelFilterFormMixin(forms.Form):
837
837
  self.order_fields(self.field_order) # Reorder fields again
838
838
 
839
839
 
840
- class TagsBulkEditFormMixin(BulkEditForm):
840
+ class TagsBulkEditFormMixin(forms.Form):
841
841
  def __init__(self, *args, **kwargs):
842
842
  super().__init__(*args, **kwargs)
843
843
 
844
844
  # Add add/remove tags fields
845
- self.fields["add_tags"] = DynamicModelMultipleChoiceField(
846
- queryset=Tag.objects.all(),
847
- query_params={"content_types": self.model._meta.label_lower},
848
- required=False,
849
- )
850
- self.fields["remove_tags"] = DynamicModelMultipleChoiceField(
851
- queryset=Tag.objects.all(),
852
- query_params={"content_types": self.model._meta.label_lower},
853
- required=False,
854
- )
845
+ self.fields["add_tags"] = DynamicModelMultipleChoiceField(queryset=Tag.objects.all(), required=False)
846
+ self.fields["remove_tags"] = DynamicModelMultipleChoiceField(queryset=Tag.objects.all(), required=False)
855
847
 
856
848
 
857
849
  # 2.2 TODO: Names below are only for backward compatibility with Nautobot 1.3 and earlier. Remove in 2.2
@@ -1,11 +1,15 @@
1
+ import graphene
2
+
1
3
  from nautobot.core.graphql.types import OptimizedNautobotObjectType
2
4
  from nautobot.extras.filters import (
3
5
  ContactAssociationFilterSet,
4
6
  DynamicGroupFilterSet,
7
+ JobFilterSet,
8
+ ScheduledJobFilterSet,
5
9
  StatusFilterSet,
6
10
  TagFilterSet,
7
11
  )
8
- from nautobot.extras.models import ContactAssociation, DynamicGroup, Status, Tag
12
+ from nautobot.extras.models import ContactAssociation, DynamicGroup, Job, ScheduledJob, Status, Tag
9
13
 
10
14
 
11
15
  class ContactAssociationType(OptimizedNautobotObjectType):
@@ -24,6 +28,26 @@ class DynamicGroupType(OptimizedNautobotObjectType):
24
28
  filterset_class = DynamicGroupFilterSet
25
29
 
26
30
 
31
+ class JobType(OptimizedNautobotObjectType):
32
+ """Graphql Type Object for Job model."""
33
+
34
+ class Meta:
35
+ model = Job
36
+ filterset_class = JobFilterSet
37
+
38
+ task_queues = graphene.List(graphene.String)
39
+
40
+
41
+ class ScheduledJobType(OptimizedNautobotObjectType):
42
+ """Graphql Type Object for Job model."""
43
+
44
+ class Meta:
45
+ model = ScheduledJob
46
+ filterset_class = ScheduledJobFilterSet
47
+
48
+ queue = graphene.String
49
+
50
+
27
51
  class StatusType(OptimizedNautobotObjectType):
28
52
  """Graphql Type object for `Status` model."""
29
53
 
@@ -8,15 +8,15 @@ from django.contrib.auth.models import Group
8
8
  logger = logging.getLogger(__name__)
9
9
 
10
10
 
11
- CLAIMS_GROUP_NAME = getattr(settings, "SSO_CLAIMS_GROUP", "groups")
11
+ CLAIMS_GROUP_NAME = getattr(settings, "NAUTOBOT_SSO_CLAIMS_GROUP", "groups")
12
12
  """ Which claim to look at in the OAuth2/OIDC response
13
13
 
14
14
  For Okta you can look at `Okta -> Authorization Servers -> Claims`. And a reasonable
15
15
  default is "groups". For Azure a reasonable default is "roles".
16
16
  """
17
17
 
18
- SUPERUSER_GROUPS = getattr(settings, "SSO_SUPERUSER_GROUPS", [])
19
- STAFF_GROUPS = getattr(settings, "SSO_STAFF_GROUPS", [])
18
+ SUPERUSER_GROUPS = getattr(settings, "NAUTOBOT_SSO_SUPERUSER_GROUPS", [])
19
+ STAFF_GROUPS = getattr(settings, "NAUTOBOT_SSO_STAFF_GROUPS", [])
20
20
 
21
21
 
22
22
  def group_sync(uid, user=None, response=None, *args, **kwargs):
@@ -160,4 +160,5 @@ class RedisBackend(RedisHealthCheck):
160
160
  elif client_class == "django_redis.client.DefaultClient":
161
161
  self.check_redis(redis_url=location, **options.get("CONNECTION_POOL_KWARGS", {}))
162
162
  else:
163
- self.add_error(ServiceUnavailable(f"{client_class} is an unsupported CLIENT_CLASS!"))
163
+ if self.redis_url is None:
164
+ self.add_error(ServiceUnavailable(f"{client_class} is an unsupported CLIENT_CLASS!"))