nautobot 2.3.15b1__py3-none-any.whl → 2.4.0__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 (785) hide show
  1. nautobot/__init__.py +15 -0
  2. nautobot/apps/__init__.py +1 -1
  3. nautobot/apps/api.py +8 -10
  4. nautobot/apps/change_logging.py +2 -2
  5. nautobot/apps/choices.py +4 -4
  6. nautobot/apps/config.py +32 -3
  7. nautobot/apps/events.py +19 -0
  8. nautobot/apps/exceptions.py +0 -2
  9. nautobot/apps/factory.py +2 -2
  10. nautobot/apps/filters.py +1 -1
  11. nautobot/apps/forms.py +20 -20
  12. nautobot/apps/graphql.py +2 -2
  13. nautobot/apps/jobs.py +8 -8
  14. nautobot/apps/models.py +19 -19
  15. nautobot/apps/tables.py +1 -1
  16. nautobot/apps/testing.py +10 -10
  17. nautobot/apps/ui.py +44 -9
  18. nautobot/apps/utils.py +7 -15
  19. nautobot/apps/views.py +8 -6
  20. nautobot/circuits/api/serializers.py +1 -0
  21. nautobot/circuits/api/views.py +4 -8
  22. nautobot/circuits/navigation.py +0 -57
  23. nautobot/circuits/templates/circuits/circuit_create.html +1 -7
  24. nautobot/circuits/templates/circuits/circuit_retrieve.html +0 -71
  25. nautobot/circuits/templates/circuits/inc/circuit_termination.html +6 -64
  26. nautobot/circuits/templates/circuits/inc/circuit_termination_cable_fragment.html +40 -0
  27. nautobot/circuits/templates/circuits/inc/circuit_termination_header_extra_content.html +26 -0
  28. nautobot/circuits/templates/circuits/provider_retrieve.html +0 -76
  29. nautobot/circuits/tests/integration/test_relationships.py +33 -24
  30. nautobot/circuits/tests/test_filters.py +4 -8
  31. nautobot/circuits/views.py +143 -26
  32. nautobot/cloud/api/views.py +6 -10
  33. nautobot/cloud/factory.py +4 -1
  34. nautobot/cloud/models.py +1 -1
  35. nautobot/cloud/tests/test_filters.py +5 -4
  36. nautobot/cloud/views.py +0 -16
  37. nautobot/core/api/constants.py +11 -0
  38. nautobot/core/api/fields.py +5 -5
  39. nautobot/core/api/filter_backends.py +3 -9
  40. nautobot/core/api/metadata.py +28 -256
  41. nautobot/core/api/pagination.py +3 -2
  42. nautobot/core/api/renderers.py +3 -0
  43. nautobot/core/api/schema.py +13 -2
  44. nautobot/core/api/serializers.py +54 -268
  45. nautobot/core/api/urls.py +3 -4
  46. nautobot/core/api/utils.py +0 -62
  47. nautobot/core/api/views.py +102 -159
  48. nautobot/core/apps/__init__.py +22 -575
  49. nautobot/core/celery/__init__.py +13 -0
  50. nautobot/core/celery/schedulers.py +48 -3
  51. nautobot/core/choices.py +2 -2
  52. nautobot/core/cli/__init__.py +8 -0
  53. nautobot/core/constants.py +7 -0
  54. nautobot/core/events/__init__.py +116 -0
  55. nautobot/core/events/base.py +27 -0
  56. nautobot/core/events/exceptions.py +10 -0
  57. nautobot/core/events/redis_broker.py +48 -0
  58. nautobot/core/events/syslog_broker.py +19 -0
  59. nautobot/core/exceptions.py +0 -6
  60. nautobot/core/filters.py +19 -16
  61. nautobot/core/forms/__init__.py +19 -19
  62. nautobot/core/forms/fields.py +62 -14
  63. nautobot/core/forms/forms.py +33 -2
  64. nautobot/core/forms/utils.py +2 -1
  65. nautobot/core/graphql/schema.py +3 -1
  66. nautobot/core/graphql/types.py +1 -1
  67. nautobot/core/jobs/__init__.py +28 -7
  68. nautobot/core/jobs/bulk_actions.py +248 -0
  69. nautobot/core/jobs/cleanup.py +2 -2
  70. nautobot/core/jobs/groups.py +1 -1
  71. nautobot/core/management/commands/generate_test_data.py +21 -0
  72. nautobot/core/management/commands/validate_models.py +1 -1
  73. nautobot/core/middleware.py +16 -0
  74. nautobot/core/models/__init__.py +1 -1
  75. nautobot/core/models/fields.py +11 -7
  76. nautobot/core/models/query_functions.py +2 -2
  77. nautobot/core/models/tree_queries.py +2 -2
  78. nautobot/core/settings.py +71 -4
  79. nautobot/core/settings.yaml +107 -0
  80. nautobot/core/tables.py +15 -51
  81. nautobot/core/tasks.py +1 -1
  82. nautobot/core/templates/about.html +67 -0
  83. nautobot/core/templates/components/button/default.html +7 -0
  84. nautobot/core/templates/components/button/dropdown.html +20 -0
  85. nautobot/core/templates/components/layout/one_over_two.html +19 -0
  86. nautobot/core/templates/components/layout/two_over_one.html +19 -0
  87. nautobot/core/templates/components/panel/body_content_data_table.html +27 -0
  88. nautobot/core/templates/components/panel/body_content_objects_table.html +4 -0
  89. nautobot/core/templates/components/panel/body_content_tags.html +6 -0
  90. nautobot/core/templates/components/panel/body_content_text.html +12 -0
  91. nautobot/core/templates/components/panel/body_wrapper_generic.html +3 -0
  92. nautobot/core/templates/components/panel/body_wrapper_key_value_table.html +3 -0
  93. nautobot/core/templates/components/panel/body_wrapper_table.html +3 -0
  94. nautobot/core/templates/components/panel/footer_contacts_table.html +20 -0
  95. nautobot/core/templates/components/panel/footer_content_table.html +14 -0
  96. nautobot/core/templates/components/panel/grouping_toggle.html +14 -0
  97. nautobot/core/templates/components/panel/header_extra_content_table.html +3 -0
  98. nautobot/core/templates/components/panel/panel.html +16 -0
  99. nautobot/core/templates/components/panel/stats_panel_body.html +8 -0
  100. nautobot/core/templates/components/tab/content_wrapper.html +3 -0
  101. nautobot/core/templates/components/tab/label_wrapper.html +5 -0
  102. nautobot/core/templates/components/tab/label_wrapper_distinct_view.html +3 -0
  103. nautobot/core/templates/generic/object_retrieve.html +28 -17
  104. nautobot/core/templates/inc/computed_fields/panel_data.html +4 -7
  105. nautobot/core/templates/inc/custom_fields/panel.html +2 -2
  106. nautobot/core/templates/inc/custom_fields/panel_data.html +4 -7
  107. nautobot/core/templates/inc/footer.html +1 -0
  108. nautobot/core/templates/inc/media.html +3 -0
  109. nautobot/core/templates/inc/nav_menu.html +2 -1
  110. nautobot/core/templates/inc/relationships_panel.html +1 -1
  111. nautobot/core/templates/inc/tenancy_form_panel.html +9 -0
  112. nautobot/core/templates/inc/tenant_table_row.html +11 -0
  113. nautobot/core/templates/nautobot_config.py.j2 +16 -0
  114. nautobot/core/templates/panel_table.html +12 -0
  115. nautobot/core/templates/utilities/render_jinja2.html +117 -0
  116. nautobot/core/templates/utilities/templatetags/tag.html +1 -1
  117. nautobot/core/templates/utilities/theme_preview.html +7 -0
  118. nautobot/core/templatetags/helpers.py +104 -6
  119. nautobot/core/templatetags/ui_framework.py +40 -0
  120. nautobot/core/testing/__init__.py +8 -8
  121. nautobot/core/testing/api.py +187 -137
  122. nautobot/core/testing/context.py +18 -0
  123. nautobot/core/testing/filters.py +44 -34
  124. nautobot/core/testing/forms.py +2 -0
  125. nautobot/core/testing/views.py +68 -146
  126. nautobot/core/tests/integration/test_app_home.py +0 -1
  127. nautobot/core/tests/integration/test_app_navbar.py +0 -1
  128. nautobot/core/tests/integration/test_filters.py +0 -2
  129. nautobot/core/tests/integration/test_home.py +0 -1
  130. nautobot/core/tests/integration/test_navbar.py +0 -1
  131. nautobot/core/tests/integration/test_view_authentication.py +2 -1
  132. nautobot/core/tests/nautobot_config.py +198 -0
  133. nautobot/core/tests/runner.py +3 -3
  134. nautobot/core/tests/test_api.py +154 -176
  135. nautobot/core/tests/test_events.py +214 -0
  136. nautobot/core/tests/test_forms.py +1 -0
  137. nautobot/core/tests/test_jinja_filters.py +1 -0
  138. nautobot/core/tests/test_jobs.py +387 -14
  139. nautobot/core/tests/test_navigations.py +7 -241
  140. nautobot/core/tests/test_settings_schema.py +7 -0
  141. nautobot/core/tests/test_tables.py +100 -0
  142. nautobot/core/tests/test_templatetags_helpers.py +16 -0
  143. nautobot/core/tests/test_ui.py +150 -0
  144. nautobot/core/tests/test_utils.py +55 -18
  145. nautobot/core/tests/test_views.py +153 -5
  146. nautobot/core/ui/__init__.py +0 -0
  147. nautobot/core/ui/base.py +11 -0
  148. nautobot/core/ui/choices.py +44 -0
  149. nautobot/core/ui/homepage.py +167 -0
  150. nautobot/core/ui/nav.py +280 -0
  151. nautobot/core/ui/object_detail.py +1855 -0
  152. nautobot/core/ui/utils.py +36 -0
  153. nautobot/core/urls.py +15 -0
  154. nautobot/core/utils/config.py +30 -3
  155. nautobot/core/utils/lookup.py +12 -2
  156. nautobot/core/utils/querysets.py +64 -0
  157. nautobot/core/utils/requests.py +24 -9
  158. nautobot/core/views/__init__.py +48 -1
  159. nautobot/core/views/generic.py +82 -177
  160. nautobot/core/views/mixins.py +98 -38
  161. nautobot/core/views/paginator.py +8 -5
  162. nautobot/core/views/renderers.py +9 -9
  163. nautobot/core/views/utils.py +11 -0
  164. nautobot/core/wsgi.py +3 -3
  165. nautobot/dcim/api/serializers.py +82 -189
  166. nautobot/dcim/api/urls.py +5 -0
  167. nautobot/dcim/api/views.py +57 -110
  168. nautobot/dcim/apps.py +1 -0
  169. nautobot/dcim/choices.py +28 -0
  170. nautobot/dcim/factory.py +58 -0
  171. nautobot/dcim/filters/__init__.py +204 -2
  172. nautobot/dcim/forms.py +221 -9
  173. nautobot/dcim/graphql/types.py +2 -2
  174. nautobot/dcim/migrations/0063_interfacevdcassignment_virtualdevicecontext_and_more.py +165 -0
  175. nautobot/dcim/migrations/0064_virtualdevicecontext_status_data_migration.py +28 -0
  176. nautobot/dcim/migrations/0065_controller_capabilities_and_more.py +29 -0
  177. nautobot/dcim/migrations/0066_controllermanageddevicegroup_radio_profiles_and_more.py +33 -0
  178. nautobot/dcim/migrations/0067_controllermanageddevicegroup_tenant.py +25 -0
  179. nautobot/dcim/models/__init__.py +5 -1
  180. nautobot/dcim/models/device_component_templates.py +2 -2
  181. nautobot/dcim/models/device_components.py +22 -20
  182. nautobot/dcim/models/devices.py +181 -3
  183. nautobot/dcim/models/locations.py +3 -3
  184. nautobot/dcim/models/power.py +6 -5
  185. nautobot/dcim/models/racks.py +6 -6
  186. nautobot/dcim/navigation.py +25 -224
  187. nautobot/dcim/signals.py +44 -0
  188. nautobot/dcim/tables/__init__.py +5 -3
  189. nautobot/dcim/tables/devices.py +103 -7
  190. nautobot/dcim/tables/devicetypes.py +2 -2
  191. nautobot/dcim/tables/racks.py +1 -1
  192. nautobot/dcim/templates/dcim/controller/base.html +10 -0
  193. nautobot/dcim/templates/dcim/controller_create.html +2 -7
  194. nautobot/dcim/templates/dcim/controller_retrieve.html +6 -10
  195. nautobot/dcim/templates/dcim/controller_wirelessnetworks.html +25 -0
  196. nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +68 -0
  197. nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +51 -0
  198. nautobot/dcim/templates/dcim/device/base.html +6 -42
  199. nautobot/dcim/templates/dcim/device/wireless.html +73 -0
  200. nautobot/dcim/templates/dcim/device.html +4 -10
  201. nautobot/dcim/templates/dcim/device_edit.html +36 -37
  202. nautobot/dcim/templates/dcim/interface.html +1 -0
  203. nautobot/dcim/templates/dcim/interface_edit.html +1 -0
  204. nautobot/dcim/templates/dcim/location.html +1 -9
  205. nautobot/dcim/templates/dcim/location_edit.html +1 -7
  206. nautobot/dcim/templates/dcim/locationtype.html +0 -107
  207. nautobot/dcim/templates/dcim/locationtype_retrieve.html +8 -0
  208. nautobot/dcim/templates/dcim/rack.html +1 -9
  209. nautobot/dcim/templates/dcim/rack_edit.html +1 -7
  210. nautobot/dcim/templates/dcim/rackreservation.html +1 -9
  211. nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +68 -0
  212. nautobot/dcim/templates/dcim/virtualdevicecontext_update.html +28 -0
  213. nautobot/dcim/tests/integration/test_controller.py +62 -0
  214. nautobot/dcim/tests/integration/test_controller_managed_device_group.py +71 -0
  215. nautobot/dcim/tests/test_api.py +188 -64
  216. nautobot/dcim/tests/test_filters.py +172 -76
  217. nautobot/dcim/tests/test_graphql.py +52 -0
  218. nautobot/dcim/tests/test_jobs.py +118 -0
  219. nautobot/dcim/tests/test_models.py +159 -5
  220. nautobot/dcim/tests/test_signals.py +1 -0
  221. nautobot/dcim/tests/test_views.py +118 -88
  222. nautobot/dcim/urls.py +72 -27
  223. nautobot/dcim/utils.py +2 -2
  224. nautobot/dcim/views.py +357 -62
  225. nautobot/extras/api/customfields.py +2 -2
  226. nautobot/extras/api/serializers.py +111 -87
  227. nautobot/extras/api/urls.py +4 -0
  228. nautobot/extras/api/views.py +93 -35
  229. nautobot/extras/choices.py +13 -0
  230. nautobot/extras/constants.py +2 -1
  231. nautobot/extras/context_managers.py +23 -6
  232. nautobot/extras/datasources/git.py +4 -1
  233. nautobot/extras/factory.py +27 -0
  234. nautobot/extras/filters/__init__.py +66 -5
  235. nautobot/extras/forms/base.py +2 -2
  236. nautobot/extras/forms/forms.py +262 -59
  237. nautobot/extras/forms/mixins.py +3 -3
  238. nautobot/extras/graphql/types.py +25 -1
  239. nautobot/extras/health_checks.py +1 -2
  240. nautobot/extras/jobs.py +114 -20
  241. nautobot/extras/management/__init__.py +1 -0
  242. nautobot/extras/management/commands/runjob.py +7 -79
  243. nautobot/extras/management/commands/runjob_with_job_result.py +46 -0
  244. nautobot/extras/management/utils.py +87 -0
  245. nautobot/extras/managers.py +3 -1
  246. nautobot/extras/migrations/0018_joblog_data_migration.py +7 -9
  247. nautobot/extras/migrations/0117_create_job_queue_model.py +129 -0
  248. nautobot/extras/migrations/0118_task_queue_to_job_queue_migration.py +78 -0
  249. nautobot/extras/migrations/0119_remove_task_queues_from_job_and_queue_from_scheduled_job.py +28 -0
  250. nautobot/extras/migrations/0120_job_is_singleton_job_is_singleton_override.py +22 -0
  251. nautobot/extras/migrations/0121_alter_team_contacts.py +17 -0
  252. nautobot/extras/models/__init__.py +5 -1
  253. nautobot/extras/models/change_logging.py +7 -3
  254. nautobot/extras/models/contacts.py +1 -1
  255. nautobot/extras/models/customfields.py +12 -11
  256. nautobot/extras/models/groups.py +11 -9
  257. nautobot/extras/models/jobs.py +237 -37
  258. nautobot/extras/models/models.py +2 -2
  259. nautobot/extras/models/relationships.py +69 -1
  260. nautobot/extras/models/secrets.py +5 -0
  261. nautobot/extras/navigation.py +20 -262
  262. nautobot/extras/plugins/__init__.py +54 -19
  263. nautobot/extras/plugins/marketplace_manifest.yml +455 -0
  264. nautobot/extras/plugins/tables.py +16 -14
  265. nautobot/extras/plugins/urls.py +1 -0
  266. nautobot/extras/plugins/views.py +104 -61
  267. nautobot/extras/registry.py +1 -1
  268. nautobot/extras/secrets/__init__.py +2 -2
  269. nautobot/extras/signals.py +39 -1
  270. nautobot/extras/tables.py +42 -6
  271. nautobot/extras/templates/extras/dynamicgroup.html +1 -9
  272. nautobot/extras/templates/extras/externalintegration_retrieve.html +0 -47
  273. nautobot/extras/templates/extras/inc/tags_panel.html +1 -5
  274. nautobot/extras/templates/extras/job_bulk_edit.html +2 -1
  275. nautobot/extras/templates/extras/job_detail.html +52 -6
  276. nautobot/extras/templates/extras/job_edit.html +6 -2
  277. nautobot/extras/templates/extras/job_list.html +2 -7
  278. nautobot/extras/templates/extras/jobqueue_retrieve.html +36 -0
  279. nautobot/extras/templates/extras/marketplace.html +296 -0
  280. nautobot/extras/templates/extras/plugin_detail.html +32 -15
  281. nautobot/extras/templates/extras/plugins_list.html +35 -1
  282. nautobot/extras/templates/extras/plugins_tiles.html +90 -0
  283. nautobot/extras/templates/extras/role_retrieve.html +16 -0
  284. nautobot/extras/templates/extras/secret.html +0 -65
  285. nautobot/extras/templates/extras/secret_check.js +16 -0
  286. nautobot/extras/templates/extras/secret_create.html +114 -0
  287. nautobot/extras/templates/extras/secret_edit.html +1 -114
  288. nautobot/extras/templates/extras/secretsgroup_edit.html +1 -1
  289. nautobot/extras/templates/extras/templatetags/plugin_object_detail_tabs.html +2 -0
  290. nautobot/extras/templatetags/job_buttons.py +5 -4
  291. nautobot/extras/templatetags/plugins.py +69 -6
  292. nautobot/extras/test_jobs/api_test_job.py +1 -1
  293. nautobot/extras/test_jobs/atomic_transaction.py +2 -2
  294. nautobot/extras/test_jobs/dry_run.py +1 -1
  295. nautobot/extras/test_jobs/fail.py +5 -5
  296. nautobot/extras/test_jobs/file_output.py +1 -1
  297. nautobot/extras/test_jobs/file_upload_fail.py +1 -1
  298. nautobot/extras/test_jobs/file_upload_pass.py +1 -1
  299. nautobot/extras/test_jobs/ipaddress_vars.py +3 -1
  300. nautobot/extras/test_jobs/jobs_module/jobs_submodule/jobs.py +1 -1
  301. nautobot/extras/test_jobs/location_with_custom_field.py +1 -1
  302. nautobot/extras/test_jobs/log_redaction.py +1 -1
  303. nautobot/extras/test_jobs/log_skip_db_logging.py +1 -1
  304. nautobot/extras/test_jobs/modify_db.py +1 -1
  305. nautobot/extras/test_jobs/object_var_optional.py +1 -1
  306. nautobot/extras/test_jobs/object_var_required.py +1 -1
  307. nautobot/extras/test_jobs/object_vars.py +1 -1
  308. nautobot/extras/test_jobs/pass.py +3 -3
  309. nautobot/extras/test_jobs/profiling.py +1 -1
  310. nautobot/extras/test_jobs/relative_import.py +3 -3
  311. nautobot/extras/test_jobs/singleton.py +16 -0
  312. nautobot/extras/test_jobs/soft_time_limit_greater_than_time_limit.py +1 -1
  313. nautobot/extras/test_jobs/task_queues.py +1 -1
  314. nautobot/extras/tests/integration/test_plugin_banner.py +0 -2
  315. nautobot/extras/tests/test_api.py +157 -55
  316. nautobot/extras/tests/test_context_managers.py +4 -1
  317. nautobot/extras/tests/test_customfields.py +1 -1
  318. nautobot/extras/tests/test_datasources.py +2 -1
  319. nautobot/extras/tests/test_dynamicgroups.py +1 -1
  320. nautobot/extras/tests/test_filters.py +219 -535
  321. nautobot/extras/tests/test_forms.py +20 -1
  322. nautobot/extras/tests/test_job_variables.py +73 -152
  323. nautobot/extras/tests/test_jobs.py +192 -62
  324. nautobot/extras/tests/test_models.py +71 -16
  325. nautobot/extras/tests/test_plugins.py +62 -9
  326. nautobot/extras/tests/test_relationships.py +124 -10
  327. nautobot/extras/tests/test_utils.py +23 -2
  328. nautobot/extras/tests/test_views.py +162 -161
  329. nautobot/extras/tests/test_webhooks.py +2 -1
  330. nautobot/extras/urls.py +2 -20
  331. nautobot/extras/utils.py +119 -4
  332. nautobot/extras/views.py +188 -141
  333. nautobot/extras/webhooks.py +5 -2
  334. nautobot/ipam/api/fields.py +3 -3
  335. nautobot/ipam/api/serializers.py +44 -137
  336. nautobot/ipam/api/views.py +68 -110
  337. nautobot/ipam/factory.py +1 -1
  338. nautobot/ipam/filters.py +3 -2
  339. nautobot/ipam/models.py +10 -12
  340. nautobot/ipam/navigation.py +0 -90
  341. nautobot/ipam/querysets.py +2 -2
  342. nautobot/ipam/tables.py +3 -1
  343. nautobot/ipam/templates/ipam/ipaddress.html +1 -9
  344. nautobot/ipam/templates/ipam/ipaddress_bulk_add.html +1 -7
  345. nautobot/ipam/templates/ipam/ipaddress_edit.html +1 -7
  346. nautobot/ipam/templates/ipam/prefix.html +1 -9
  347. nautobot/ipam/templates/ipam/prefix_edit.html +1 -7
  348. nautobot/ipam/templates/ipam/routetarget.html +0 -28
  349. nautobot/ipam/templates/ipam/vlan.html +1 -9
  350. nautobot/ipam/templates/ipam/vlan_edit.html +1 -7
  351. nautobot/ipam/templates/ipam/vrf.html +0 -47
  352. nautobot/ipam/templates/ipam/vrf_edit.html +1 -7
  353. nautobot/ipam/tests/test_api.py +19 -6
  354. nautobot/ipam/tests/test_filters.py +39 -119
  355. nautobot/ipam/tests/test_forms.py +49 -47
  356. nautobot/ipam/tests/test_migrations.py +30 -30
  357. nautobot/ipam/tests/test_models.py +56 -36
  358. nautobot/ipam/tests/test_querysets.py +14 -0
  359. nautobot/ipam/tests/test_views.py +3 -0
  360. nautobot/ipam/urls.py +3 -69
  361. nautobot/ipam/utils/__init__.py +16 -10
  362. nautobot/ipam/views.py +91 -162
  363. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.css.map +1 -1
  364. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.min.css.map +1 -1
  365. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css +40 -2
  366. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css.map +1 -1
  367. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css +1 -1
  368. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css.map +1 -1
  369. nautobot/project-static/css/base.css +38 -3
  370. nautobot/project-static/docs/404.html +463 -19
  371. nautobot/project-static/docs/apps/index.html +463 -19
  372. nautobot/project-static/docs/apps/nautobot-apps.html +464 -21
  373. nautobot/project-static/docs/assets/_mkdocstrings.css +25 -1
  374. nautobot/project-static/docs/assets/extra.css +5 -1
  375. nautobot/project-static/docs/assets/javascripts/{bundle.83f73b43.min.js → bundle.88dd0f4e.min.js} +2 -2
  376. nautobot/project-static/docs/assets/javascripts/{bundle.83f73b43.min.js.map → bundle.88dd0f4e.min.js.map} +2 -2
  377. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +479 -25
  378. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +476 -22
  379. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +792 -291
  380. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +507 -33
  381. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +512 -36
  382. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +473 -22
  383. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +469 -20
  384. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +499 -35
  385. nautobot/project-static/docs/code-reference/nautobot/apps/events.html +9883 -0
  386. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +525 -77
  387. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +548 -53
  388. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +672 -96
  389. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +1033 -180
  390. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +526 -51
  391. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +876 -190
  392. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +957 -237
  393. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +477 -23
  394. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +488 -30
  395. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +663 -101
  396. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +949 -481
  397. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +6427 -1236
  398. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +476 -22
  399. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +879 -346
  400. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +830 -173
  401. nautobot/project-static/docs/development/apps/api/configuration-view.html +463 -19
  402. nautobot/project-static/docs/development/apps/api/database-backend-config.html +463 -19
  403. nautobot/project-static/docs/development/apps/api/models/django-admin.html +463 -19
  404. nautobot/project-static/docs/development/apps/api/models/global-search.html +463 -19
  405. nautobot/project-static/docs/development/apps/api/models/graphql.html +463 -19
  406. nautobot/project-static/docs/development/apps/api/models/index.html +463 -19
  407. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +463 -19
  408. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +463 -19
  409. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +463 -19
  410. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +463 -19
  411. nautobot/project-static/docs/development/apps/api/platform-features/index.html +463 -19
  412. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +463 -19
  413. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +463 -19
  414. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +463 -19
  415. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +463 -19
  416. nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +463 -19
  417. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +463 -19
  418. nautobot/project-static/docs/development/apps/api/prometheus.html +463 -19
  419. nautobot/project-static/docs/development/apps/api/setup.html +467 -155
  420. nautobot/project-static/docs/development/apps/api/testing.html +463 -19
  421. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +463 -19
  422. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +463 -19
  423. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +463 -19
  424. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +463 -19
  425. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +743 -130
  426. nautobot/project-static/docs/development/apps/api/views/base-template.html +463 -19
  427. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +463 -19
  428. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +463 -19
  429. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +463 -19
  430. nautobot/project-static/docs/development/apps/api/views/index.html +465 -20
  431. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +467 -19
  432. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +493 -19
  433. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +463 -19
  434. nautobot/project-static/docs/development/apps/api/views/notes.html +463 -19
  435. nautobot/project-static/docs/development/apps/api/views/rest-api.html +469 -21
  436. nautobot/project-static/docs/development/apps/api/views/urls.html +463 -19
  437. nautobot/project-static/docs/development/apps/index.html +463 -19
  438. nautobot/project-static/docs/development/apps/migration/code-updates.html +464 -52
  439. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +464 -20
  440. nautobot/project-static/docs/development/apps/migration/from-v1.html +463 -19
  441. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +463 -19
  442. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +463 -19
  443. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +463 -19
  444. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +466 -22
  445. nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +9261 -0
  446. nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +9375 -0
  447. nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +9671 -0
  448. nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +9559 -0
  449. nautobot/project-static/docs/development/apps/porting-from-netbox.html +466 -22
  450. nautobot/project-static/docs/development/core/application-registry.html +463 -19
  451. nautobot/project-static/docs/development/core/best-practices.html +463 -19
  452. nautobot/project-static/docs/development/core/bootstrap-ui.html +463 -19
  453. nautobot/project-static/docs/development/core/caching.html +463 -19
  454. nautobot/project-static/docs/development/core/controllers.html +465 -19
  455. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +491 -90
  456. nautobot/project-static/docs/development/core/generic-views.html +463 -19
  457. nautobot/project-static/docs/development/core/getting-started.html +541 -129
  458. nautobot/project-static/docs/development/core/homepage.html +474 -30
  459. nautobot/project-static/docs/development/core/index.html +463 -19
  460. nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +9754 -0
  461. nautobot/project-static/docs/development/core/model-checklist.html +473 -27
  462. nautobot/project-static/docs/development/core/model-features.html +463 -19
  463. nautobot/project-static/docs/development/core/natural-keys.html +463 -19
  464. nautobot/project-static/docs/development/core/navigation-menu.html +480 -26
  465. nautobot/project-static/docs/development/core/release-checklist.html +480 -48
  466. nautobot/project-static/docs/development/core/role-internals.html +463 -19
  467. nautobot/project-static/docs/development/core/settings.html +463 -19
  468. nautobot/project-static/docs/development/core/style-guide.html +466 -22
  469. nautobot/project-static/docs/development/core/templates.html +473 -22
  470. nautobot/project-static/docs/development/core/testing.html +463 -19
  471. nautobot/project-static/docs/development/core/ui-component-framework.html +11116 -0
  472. nautobot/project-static/docs/development/core/user-preferences.html +466 -22
  473. nautobot/project-static/docs/development/index.html +463 -19
  474. nautobot/project-static/docs/development/jobs/index.html +501 -21
  475. nautobot/project-static/docs/development/jobs/migration/from-v1.html +463 -19
  476. nautobot/project-static/docs/index.html +471 -38
  477. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_edit.png +0 -0
  478. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_edit_button.png +0 -0
  479. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_list_nav.png +0 -0
  480. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_list_view.png +0 -0
  481. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue.png +0 -0
  482. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue_add.png +0 -0
  483. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue_config.png +0 -0
  484. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_completed.png +0 -0
  485. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_nav.png +0 -0
  486. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_pending.png +0 -0
  487. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_run_form.png +0 -0
  488. nautobot/project-static/docs/media/development/core/kubernetes/k8s_nautobot_login.png +0 -0
  489. nautobot/project-static/docs/media/development/core/kubernetes/k8s_run_job.png +0 -0
  490. nautobot/project-static/docs/media/development/core/kubernetes/k8s_run_scheduled_job_form.png +0 -0
  491. nautobot/project-static/docs/media/development/core/kubernetes/k8s_scheduled_job_result.png +0 -0
  492. nautobot/project-static/docs/media/development/core/ui-component-framework/basic-panel-layout.png +0 -0
  493. nautobot/project-static/docs/media/development/core/ui-component-framework/button-example.png +0 -0
  494. nautobot/project-static/docs/media/development/core/ui-component-framework/buttons-example.png +0 -0
  495. nautobot/project-static/docs/media/development/core/ui-component-framework/cluster-type-before-after-example.png +0 -0
  496. nautobot/project-static/docs/media/development/core/ui-component-framework/dropdown-button-example.png +0 -0
  497. nautobot/project-static/docs/media/development/core/ui-component-framework/grouped-key-value-table-panel-example-1.png +0 -0
  498. nautobot/project-static/docs/media/development/core/ui-component-framework/grouped-key-value-table-panel-example-2.png +0 -0
  499. nautobot/project-static/docs/media/development/core/ui-component-framework/object-fields-panel-example.png +0 -0
  500. nautobot/project-static/docs/media/development/core/ui-component-framework/object-fields-panel-example_2.png +0 -0
  501. nautobot/project-static/docs/media/development/core/ui-component-framework/stats-panel-example-code.png +0 -0
  502. nautobot/project-static/docs/media/development/core/ui-component-framework/stats-panel-example.png +0 -0
  503. nautobot/project-static/docs/media/development/core/ui-component-framework/table-panels-family.png +0 -0
  504. nautobot/project-static/docs/media/development/core/ui-component-framework/text-panels-family.png +0 -0
  505. nautobot/project-static/docs/media/development/core/ui-component-framework/ui-framework-example.png +0 -0
  506. nautobot/project-static/docs/media/models/virtual_device_context_overview.drawio +73 -0
  507. nautobot/project-static/docs/media/models/virtual_device_context_overview.png +0 -0
  508. nautobot/project-static/docs/models/dcim/virtualdevicecontext.html +14 -0
  509. nautobot/project-static/docs/models/extras/jobqueue.html +14 -0
  510. nautobot/project-static/docs/models/wireless/radioprofile.html +14 -0
  511. nautobot/project-static/docs/models/wireless/supporteddatarate.html +14 -0
  512. nautobot/project-static/docs/models/wireless/wirelessnetwork.html +14 -0
  513. nautobot/project-static/docs/objects.inv +0 -0
  514. nautobot/project-static/docs/overview/application_stack.html +469 -23
  515. nautobot/project-static/docs/overview/design_philosophy.html +463 -19
  516. nautobot/project-static/docs/release-notes/index.html +485 -22
  517. nautobot/project-static/docs/release-notes/version-1.0.html +651 -208
  518. nautobot/project-static/docs/release-notes/version-1.1.html +648 -205
  519. nautobot/project-static/docs/release-notes/version-1.2.html +723 -280
  520. nautobot/project-static/docs/release-notes/version-1.3.html +749 -306
  521. nautobot/project-static/docs/release-notes/version-1.4.html +834 -392
  522. nautobot/project-static/docs/release-notes/version-1.5.html +1022 -581
  523. nautobot/project-static/docs/release-notes/version-1.6.html +942 -518
  524. nautobot/project-static/docs/release-notes/version-2.0.html +945 -504
  525. nautobot/project-static/docs/release-notes/version-2.1.html +780 -339
  526. nautobot/project-static/docs/release-notes/version-2.2.html +773 -332
  527. nautobot/project-static/docs/release-notes/version-2.3.html +1142 -448
  528. nautobot/project-static/docs/release-notes/version-2.4.html +10323 -0
  529. nautobot/project-static/docs/requirements.txt +2 -2
  530. nautobot/project-static/docs/search/search_index.json +1 -1
  531. nautobot/project-static/docs/sitemap.xml +342 -270
  532. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  533. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +463 -19
  534. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +463 -19
  535. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +463 -19
  536. nautobot/project-static/docs/user-guide/administration/configuration/index.html +475 -32
  537. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +463 -19
  538. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +894 -180
  539. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +463 -19
  540. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +463 -19
  541. nautobot/project-static/docs/user-guide/administration/guides/docker.html +476 -29
  542. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +463 -19
  543. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +463 -19
  544. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +463 -19
  545. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +463 -19
  546. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +463 -19
  547. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +465 -21
  548. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +463 -19
  549. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +463 -19
  550. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +463 -19
  551. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +483 -23
  552. nautobot/project-static/docs/user-guide/administration/installation/index.html +468 -20
  553. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +464 -20
  554. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +463 -19
  555. nautobot/project-static/docs/user-guide/administration/installation/services.html +463 -19
  556. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +463 -19
  557. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +484 -41
  558. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +477 -66
  559. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +477 -66
  560. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +463 -19
  561. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +463 -19
  562. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +463 -19
  563. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +463 -19
  564. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +463 -19
  565. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +466 -23
  566. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +463 -19
  567. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/tables/v2-code-nautobot-app-location.yaml +0 -16
  568. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +463 -19
  569. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +469 -21
  570. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +463 -19
  571. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +463 -19
  572. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +463 -19
  573. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +463 -19
  574. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +463 -19
  575. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +463 -19
  576. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +463 -19
  577. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +463 -19
  578. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +463 -19
  579. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +463 -19
  580. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +463 -19
  581. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +463 -19
  582. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +463 -19
  583. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +463 -19
  584. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +463 -19
  585. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +463 -19
  586. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +463 -19
  587. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +499 -20
  588. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +489 -22
  589. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +463 -19
  590. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +463 -19
  591. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +463 -19
  592. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +463 -19
  593. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +463 -19
  594. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +463 -19
  595. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +463 -19
  596. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +463 -19
  597. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +463 -19
  598. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +463 -19
  599. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +463 -19
  600. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +463 -19
  601. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +463 -19
  602. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +463 -19
  603. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +463 -19
  604. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +463 -19
  605. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +463 -19
  606. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +463 -19
  607. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +463 -19
  608. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +463 -19
  609. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +463 -19
  610. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +463 -19
  611. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +463 -19
  612. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +463 -19
  613. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +463 -19
  614. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +463 -19
  615. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +463 -19
  616. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +463 -19
  617. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +463 -19
  618. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +463 -19
  619. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +463 -19
  620. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +463 -19
  621. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +463 -19
  622. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +463 -19
  623. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +9375 -0
  624. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +470 -30
  625. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +463 -19
  626. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +463 -19
  627. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +463 -19
  628. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +463 -19
  629. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +463 -19
  630. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +463 -19
  631. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +463 -19
  632. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +463 -19
  633. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +463 -19
  634. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +463 -19
  635. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +463 -19
  636. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +463 -19
  637. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +466 -22
  638. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +463 -19
  639. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +463 -19
  640. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +463 -19
  641. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +463 -19
  642. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +463 -19
  643. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +463 -19
  644. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +466 -22
  645. nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +9313 -0
  646. nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +9217 -0
  647. nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +9211 -0
  648. nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +9277 -0
  649. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +463 -19
  650. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +463 -19
  651. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +463 -19
  652. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +463 -19
  653. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +463 -19
  654. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +463 -19
  655. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +463 -19
  656. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +463 -19
  657. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +463 -19
  658. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +463 -19
  659. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +463 -19
  660. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +468 -22
  661. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +463 -19
  662. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/central-mode.png +0 -0
  663. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/device-group-add.png +0 -0
  664. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/device-group-create-1.png +0 -0
  665. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/device-group-create-2.png +0 -0
  666. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/radio-profile-add.png +0 -0
  667. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/radio-profile-create.png +0 -0
  668. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/supported-data-rate-add.png +0 -0
  669. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/supported-data-rate-create.png +0 -0
  670. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-controller-add.png +0 -0
  671. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-controller-create-1.png +0 -0
  672. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-controller-create-2.png +0 -0
  673. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-network-add.png +0 -0
  674. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-network-create.png +0 -0
  675. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +463 -19
  676. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +463 -19
  677. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +466 -22
  678. nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +9444 -0
  679. nautobot/project-static/docs/user-guide/index.html +463 -19
  680. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +466 -22
  681. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +467 -23
  682. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +463 -19
  683. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +463 -19
  684. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +463 -19
  685. nautobot/project-static/docs/user-guide/platform-functionality/events.html +9617 -0
  686. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +466 -22
  687. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +463 -19
  688. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +463 -19
  689. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +463 -19
  690. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +463 -19
  691. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +463 -19
  692. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +472 -23
  693. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +466 -22
  694. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +466 -22
  695. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +463 -19
  696. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +9224 -0
  697. nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +9722 -0
  698. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +466 -22
  699. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +463 -19
  700. nautobot/project-static/docs/user-guide/platform-functionality/note.html +463 -19
  701. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +463 -19
  702. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +467 -23
  703. nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +9292 -0
  704. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +463 -19
  705. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +511 -40
  706. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +494 -23
  707. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +463 -19
  708. nautobot/project-static/docs/user-guide/platform-functionality/role.html +463 -19
  709. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +463 -19
  710. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +463 -19
  711. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +466 -22
  712. nautobot/project-static/docs/user-guide/platform-functionality/status.html +463 -19
  713. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +463 -19
  714. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +531 -56
  715. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +463 -19
  716. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +463 -19
  717. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +463 -19
  718. nautobot/project-static/img/jinja_logo.svg +97 -0
  719. nautobot/project-static/js/forms.js +6 -1
  720. nautobot/project-static/js/nav_menu.js +2 -1
  721. nautobot/tenancy/api/serializers.py +0 -2
  722. nautobot/tenancy/api/views.py +9 -13
  723. nautobot/tenancy/factory.py +1 -1
  724. nautobot/tenancy/navigation.py +0 -29
  725. nautobot/tenancy/templates/tenancy/tenant.html +4 -91
  726. nautobot/tenancy/tests/test_filters.py +29 -134
  727. nautobot/tenancy/views.py +35 -24
  728. nautobot/users/admin.py +3 -1
  729. nautobot/users/api/serializers.py +4 -4
  730. nautobot/users/api/views.py +3 -3
  731. nautobot/users/forms.py +19 -0
  732. nautobot/users/templates/users/preferences.html +22 -0
  733. nautobot/users/tests/test_filters.py +1 -19
  734. nautobot/users/tests/test_views.py +57 -0
  735. nautobot/users/utils.py +8 -0
  736. nautobot/users/views.py +48 -11
  737. nautobot/virtualization/api/serializers.py +4 -4
  738. nautobot/virtualization/api/views.py +5 -24
  739. nautobot/virtualization/filters.py +1 -2
  740. nautobot/virtualization/models.py +1 -1
  741. nautobot/virtualization/navigation.py +0 -48
  742. nautobot/virtualization/tables.py +2 -2
  743. nautobot/virtualization/templates/virtualization/cluster_edit.html +1 -7
  744. nautobot/virtualization/templates/virtualization/clustertype.html +0 -39
  745. nautobot/virtualization/templates/virtualization/virtualmachine.html +1 -9
  746. nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +2 -8
  747. nautobot/virtualization/tests/test_filters.py +57 -166
  748. nautobot/virtualization/views.py +18 -15
  749. nautobot/wireless/__init__.py +0 -0
  750. nautobot/wireless/api/__init__.py +0 -0
  751. nautobot/wireless/api/serializers.py +44 -0
  752. nautobot/wireless/api/urls.py +20 -0
  753. nautobot/wireless/api/views.py +34 -0
  754. nautobot/wireless/apps.py +8 -0
  755. nautobot/wireless/choices.py +345 -0
  756. nautobot/wireless/factory.py +138 -0
  757. nautobot/wireless/filters.py +167 -0
  758. nautobot/wireless/forms.py +283 -0
  759. nautobot/wireless/homepage.py +19 -0
  760. nautobot/wireless/migrations/0001_initial.py +223 -0
  761. nautobot/wireless/migrations/__init__.py +0 -0
  762. nautobot/wireless/models.py +207 -0
  763. nautobot/wireless/navigation.py +105 -0
  764. nautobot/wireless/tables.py +244 -0
  765. nautobot/wireless/templates/wireless/radioprofile_retrieve.html +81 -0
  766. nautobot/wireless/templates/wireless/supporteddatarate_retrieve.html +26 -0
  767. nautobot/wireless/templates/wireless/wirelessnetwork_create.html +88 -0
  768. nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +56 -0
  769. nautobot/wireless/tests/__init__.py +0 -0
  770. nautobot/wireless/tests/integration/__init__.py +0 -0
  771. nautobot/wireless/tests/integration/test_radio_profile.py +42 -0
  772. nautobot/wireless/tests/test_api.py +247 -0
  773. nautobot/wireless/tests/test_filters.py +82 -0
  774. nautobot/wireless/tests/test_models.py +22 -0
  775. nautobot/wireless/tests/test_views.py +378 -0
  776. nautobot/wireless/urls.py +13 -0
  777. nautobot/wireless/views.py +119 -0
  778. {nautobot-2.3.15b1.dist-info → nautobot-2.4.0.dist-info}/METADATA +11 -13
  779. {nautobot-2.3.15b1.dist-info → nautobot-2.4.0.dist-info}/RECORD +783 -613
  780. {nautobot-2.3.15b1.dist-info → nautobot-2.4.0.dist-info}/WHEEL +1 -1
  781. nautobot/core/fixtures/user-data.json +0 -59
  782. nautobot/core/utils/navigation.py +0 -54
  783. {nautobot-2.3.15b1.dist-info → nautobot-2.4.0.dist-info}/LICENSE.txt +0 -0
  784. {nautobot-2.3.15b1.dist-info → nautobot-2.4.0.dist-info}/NOTICE +0 -0
  785. {nautobot-2.3.15b1.dist-info → nautobot-2.4.0.dist-info}/entry_points.txt +0 -0
@@ -98,6 +98,7 @@ class Command(BaseCommand):
98
98
  RearPortTemplateFactory,
99
99
  SoftwareImageFileFactory,
100
100
  SoftwareVersionFactory,
101
+ VirtualDeviceContextFactory,
101
102
  )
102
103
  from nautobot.extras.choices import MetadataTypeDataTypeChoices
103
104
  from nautobot.extras.factory import (
@@ -105,6 +106,7 @@ class Command(BaseCommand):
105
106
  DynamicGroupFactory,
106
107
  ExternalIntegrationFactory,
107
108
  JobLogEntryFactory,
109
+ JobQueueFactory,
108
110
  JobResultFactory,
109
111
  MetadataChoiceFactory,
110
112
  MetadataTypeFactory,
@@ -131,6 +133,14 @@ class Command(BaseCommand):
131
133
  )
132
134
  from nautobot.tenancy.factory import TenantFactory, TenantGroupFactory
133
135
  from nautobot.users.factory import UserFactory
136
+ from nautobot.wireless.factory import (
137
+ ControllerManagedDeviceGroupWithMembersFactory,
138
+ RadioProfileFactory,
139
+ RadioProfilesWithMembersFactory,
140
+ SupportedDataRateFactory,
141
+ WirelessNetworkFactory,
142
+ WirelessNetworksWithMembersFactory,
143
+ )
134
144
  except ImportError as err:
135
145
  raise CommandError('Unable to load data factories. Is the "factory-boy" package installed?') from err
136
146
 
@@ -218,6 +228,7 @@ class Command(BaseCommand):
218
228
  _create_batch(ManufacturerFactory, 2, description="without Platforms or DeviceTypes") # Last 2 hard-coded
219
229
  _create_batch(DeviceRedundancyGroupFactory, 20)
220
230
  _create_batch(DeviceFactory, 20)
231
+ _create_batch(VirtualDeviceContextFactory, 30)
221
232
  _create_batch(ModuleFactory, 20)
222
233
  _create_batch(SoftwareVersionFactory, 5, description="without Devices")
223
234
  _create_batch(SoftwareImageFileFactory, 5, description="without DeviceTypes")
@@ -304,6 +315,15 @@ class Command(BaseCommand):
304
315
  _create_batch(ExternalIntegrationFactory, 20)
305
316
  _create_batch(ControllerFactory, 10, description="with Devices or DeviceRedundancyGroups")
306
317
  _create_batch(ControllerManagedDeviceGroupFactory, 5, description="without any Devices")
318
+ _create_batch(SupportedDataRateFactory, 20)
319
+ _create_batch(RadioProfileFactory, 20)
320
+ _create_batch(WirelessNetworkFactory, 20)
321
+ _create_batch(ControllerManagedDeviceGroupWithMembersFactory, 5, description="with members")
322
+ _create_batch(RadioProfilesWithMembersFactory, 5, description="with members")
323
+ _create_batch(WirelessNetworksWithMembersFactory, 5, description="with members")
324
+ # make sure we have some supported data rates that have null relationships to make filter tests happy
325
+ _create_batch(SupportedDataRateFactory, 10, description="without any associated objects")
326
+ _create_batch(JobQueueFactory, 10)
307
327
  # make sure we have some tenants that have null relationships to make filter tests happy
308
328
  _create_batch(TenantFactory, 10, description="without any associated objects")
309
329
  # TODO: nautobot.tenancy.tests.test_filters currently calls the following additional factories:
@@ -329,6 +349,7 @@ class Command(BaseCommand):
329
349
  )
330
350
  _create_batch(MetadataChoiceFactory, 100)
331
351
  _create_batch(ObjectChangeFactory, 100)
352
+ _create_batch(JobQueueFactory, 30)
332
353
  _create_batch(JobResultFactory, 20)
333
354
  _create_batch(JobLogEntryFactory, 100)
334
355
  _create_batch(ObjectMetadataFactory, 100)
@@ -63,7 +63,7 @@ class Command(BaseCommand):
63
63
  for model in models:
64
64
  model_name = f"{model._meta.app_label}.{model.__name__}"
65
65
  # Most swap out for user_model
66
- if model_name == "auth.User":
66
+ if model_name == "auth.User": # pylint: disable=hard-coded-auth-user
67
67
  model = get_user_model()
68
68
  # Skip models that aren't actually in the database
69
69
  if not model._meta.managed:
@@ -1,9 +1,12 @@
1
+ from zoneinfo import ZoneInfo
2
+
1
3
  from django.conf import settings
2
4
  from django.contrib.auth.middleware import RemoteUserMiddleware as RemoteUserMiddleware_
3
5
  from django.db import ProgrammingError
4
6
  from django.http import Http404
5
7
  from django.urls import resolve
6
8
  from django.urls.exceptions import Resolver404
9
+ from django.utils import timezone
7
10
  from django.utils.deprecation import MiddlewareMixin
8
11
 
9
12
  from nautobot.core.api.utils import is_api_request, rest_api_server_error
@@ -149,3 +152,16 @@ class ExceptionHandlingMiddleware:
149
152
  return server_error(request, template_name=custom_template)
150
153
 
151
154
  return None
155
+
156
+
157
+ class UserDefinedTimeZoneMiddleware:
158
+ def __init__(self, get_response):
159
+ self.get_response = get_response
160
+
161
+ def __call__(self, request):
162
+ if request.user.is_authenticated:
163
+ if tzname := request.user.get_config("timezone"):
164
+ timezone.activate(ZoneInfo(tzname))
165
+ else:
166
+ timezone.deactivate()
167
+ return self.get_response(request)
@@ -270,7 +270,7 @@ class BaseModel(models.Model):
270
270
 
271
271
  if not natural_key_field_names:
272
272
  raise AttributeError(
273
- f"Unable to identify an intrinsic natural-key definition for {cls.__name__}. "
273
+ f"Unable to identify an intrinsic natural-key definition for {cls.__name__}. " # pylint: disable=no-member
274
274
  "If there isn't at least one UniqueConstraint, unique_together, or field with unique=True, "
275
275
  "you probably need to explicitly declare the 'natural_key_field_names' for this model, "
276
276
  "or potentially override the default 'natural_key_field_lookups' implementation for this model."
@@ -280,6 +280,8 @@ class JSONArrayField(models.JSONField):
280
280
  """
281
281
  An ArrayField implementation backed JSON storage.
282
282
  Replicates ArrayField's base field validation.
283
+
284
+ Supports choices in the base field.
283
285
  """
284
286
 
285
287
  _default_hint = ("list", "[]")
@@ -375,13 +377,15 @@ class JSONArrayField(models.JSONField):
375
377
 
376
378
  def formfield(self, **kwargs):
377
379
  """Return a django.forms.Field instance for this field."""
378
- return super().formfield(
379
- **{
380
- "form_class": fields.JSONArrayFormField,
381
- "base_field": self.base_field.formfield(),
382
- **kwargs,
383
- }
384
- )
380
+ defaults = {
381
+ "form_class": fields.JSONArrayFormField,
382
+ "base_field": self.base_field.formfield(),
383
+ }
384
+ # If the base field has choices, pass them to the form field.
385
+ if self.base_field.choices:
386
+ defaults["choices"] = self.base_field.choices
387
+ defaults.update(**kwargs)
388
+ return super().formfield(**defaults)
385
389
 
386
390
 
387
391
  class LaxURLField(models.URLField):
@@ -69,7 +69,7 @@ class JSONSet(Func):
69
69
  }
70
70
  return c
71
71
 
72
- def as_sql(self, compiler, connection, function=None, **extra_context):
72
+ def as_sql(self, compiler, connection, function=None, **extra_context): # pylint:disable=arguments-differ
73
73
  """
74
74
  MySQL implementation based on https://github.com/django/django/pull/18489/files.
75
75
 
@@ -138,7 +138,7 @@ class JSONRemove(Func):
138
138
  self.path = path
139
139
  super().__init__(expression)
140
140
 
141
- def as_sql(self, compiler, connection, function=None, **extra_context):
141
+ def as_sql(self, compiler, connection, function=None, **extra_context): # pylint:disable=arguments-differ
142
142
  """
143
143
  MySQL implementation based on https://github.com/django/django/pull/18489/files.
144
144
 
@@ -114,12 +114,12 @@ class TreeModel(TreeNode):
114
114
  if self.parent_id is not None:
115
115
  parent_display_str = cache.get(cache_key.replace(str(self.id), str(self.parent_id)), "")
116
116
  if not parent_display_str:
117
- parent_display_str = self.parent.display
117
+ parent_display_str = self.parent.display # pylint: disable=no-member
118
118
  display_str = parent_display_str + " → "
119
119
  except self.DoesNotExist:
120
120
  # Expected to occur at times during bulk-delete operations
121
121
  pass
122
- display_str += self.name
122
+ display_str += self.name # pylint: disable=no-member # we checked with hasattr() above
123
123
  cache.set(cache_key, display_str, 5)
124
124
  return display_str
125
125
 
nautobot/core/settings.py CHANGED
@@ -1,3 +1,4 @@
1
+ import datetime
1
2
  import os
2
3
  import os.path
3
4
  import platform
@@ -10,7 +11,11 @@ import django.forms
10
11
  from django.utils.safestring import mark_safe
11
12
 
12
13
  from nautobot import __version__
13
- from nautobot.core.constants import CONFIG_SETTING_SEPARATOR as _CONFIG_SETTING_SEPARATOR
14
+ from nautobot.core.constants import (
15
+ CONFIG_SETTING_SEPARATOR as _CONFIG_SETTING_SEPARATOR,
16
+ MAX_PAGE_SIZE_DEFAULT as _MAX_PAGE_SIZE_DEFAULT,
17
+ PAGINATE_COUNT_DEFAULT as _PAGINATE_COUNT_DEFAULT,
18
+ )
14
19
  from nautobot.core.settings_funcs import ConstanceConfigItem, is_truthy, parse_redis_connection
15
20
 
16
21
  #
@@ -96,6 +101,9 @@ if "NAUTOBOT_DEPLOYMENT_ID" in os.environ and os.environ["NAUTOBOT_DEPLOYMENT_ID
96
101
  if "NAUTOBOT_DEVICE_NAME_AS_NATURAL_KEY" in os.environ and os.environ["NAUTOBOT_DEVICE_NAME_AS_NATURAL_KEY"] != "":
97
102
  DEVICE_NAME_AS_NATURAL_KEY = is_truthy(os.environ["NAUTOBOT_DEVICE_NAME_AS_NATURAL_KEY"])
98
103
 
104
+ # Event Brokers
105
+ EVENT_BROKERS = {}
106
+
99
107
  # Exclude potentially sensitive models from wildcard view exemption. These may still be exempted
100
108
  # by specifying the model individually in the EXEMPT_VIEW_PERMISSIONS configuration parameter.
101
109
  EXEMPT_EXCLUDE_MODELS = (
@@ -156,6 +164,16 @@ NAPALM_PASSWORD = os.getenv("NAUTOBOT_NAPALM_PASSWORD", "")
156
164
  NAPALM_TIMEOUT = int(os.getenv("NAUTOBOT_NAPALM_TIMEOUT", "30"))
157
165
  NAPALM_USERNAME = os.getenv("NAUTOBOT_NAPALM_USERNAME", "")
158
166
 
167
+ # Expiration date (YYYY-MM-DD) for an active Nautobot support contract with Network to Code.
168
+ # Displayed in the About page.
169
+ if (
170
+ "NAUTOBOT_NTC_SUPPORT_CONTRACT_EXPIRATION_DATE" in os.environ
171
+ and os.environ["NAUTOBOT_NTC_SUPPORT_CONTRACT_EXPIRATION_DATE"] != ""
172
+ ):
173
+ NTC_SUPPORT_CONTRACT_EXPIRATION_DATE = datetime.date.fromisoformat(
174
+ os.environ["NAUTOBOT_NTC_SUPPORT_CONTRACT_EXPIRATION_DATE"]
175
+ )
176
+
159
177
  # Default number of objects to display per page of the UI and REST API. Default is 50
160
178
  if "NAUTOBOT_PAGINATE_COUNT" in os.environ and os.environ["NAUTOBOT_PAGINATE_COUNT"] != "":
161
179
  PAGINATE_COUNT = int(os.environ["NAUTOBOT_PAGINATE_COUNT"])
@@ -173,6 +191,9 @@ PLUGINS_CONFIG = {}
173
191
  if "NAUTOBOT_PREFER_IPV4" in os.environ and os.environ["NAUTOBOT_PREFER_IPV4"] != "":
174
192
  PREFER_IPV4 = is_truthy(os.environ["NAUTOBOT_PREFER_IPV4"])
175
193
 
194
+ # Publish a simple "no-index" robots.txt for Nautobot?
195
+ PUBLISH_ROBOTS_TXT = is_truthy(os.getenv("NAUTOBOT_PUBLISH_ROBOTS_TXT", "True"))
196
+
176
197
  # Default height and width in pixels of a single rack unit in rendered rack elevations. Defaults are 22 and 220
177
198
  if (
178
199
  "NAUTOBOT_RACK_ELEVATION_DEFAULT_UNIT_HEIGHT" in os.environ
@@ -401,6 +422,11 @@ SPECTACULAR_SETTINGS = {
401
422
  # enum naming encountered a non-optimally resolvable collision for fields named "protocol".
402
423
  "InterfaceRedundancyGroupProtocolChoices": "nautobot.dcim.choices.InterfaceRedundancyGroupProtocolChoices",
403
424
  "ServiceProtocolChoices": "nautobot.ipam.choices.ServiceProtocolChoices",
425
+ # These choice enums need to be overridden because they get assigned to the `mode` field and
426
+ # result in this error:
427
+ # enum naming encountered a non-optimally resolvable collision for fields named "mode".
428
+ "InterfaceModeChoices": "nautobot.dcim.choices.InterfaceModeChoices",
429
+ "WirelessNetworkModeChoices": "nautobot.wireless.choices.WirelessNetworkModeChoices",
404
430
  },
405
431
  # Create separate schema components for PATCH requests (fields generally are not `required` on PATCH)
406
432
  "COMPONENT_SPLIT_PATCH": True,
@@ -550,6 +576,7 @@ INSTALLED_APPS = [
550
576
  "nautobot.tenancy",
551
577
  "nautobot.users",
552
578
  "nautobot.virtualization",
579
+ "nautobot.wireless",
553
580
  "drf_spectacular",
554
581
  "drf_spectacular_sidecar",
555
582
  "graphene_django",
@@ -580,6 +607,7 @@ MIDDLEWARE = [
580
607
  "nautobot.core.middleware.RemoteUserMiddleware",
581
608
  "nautobot.core.middleware.ExternalAuthMiddleware",
582
609
  "nautobot.core.middleware.ObjectChangeMiddleware",
610
+ "nautobot.core.middleware.UserDefinedTimeZoneMiddleware",
583
611
  "django_prometheus.middleware.PrometheusAfterMiddleware",
584
612
  ]
585
613
 
@@ -704,6 +732,13 @@ CONSTANCE_ADDITIONAL_FIELDS = {
704
732
  "required": False,
705
733
  },
706
734
  ],
735
+ "optional_date_field": [
736
+ "django.forms.DateField",
737
+ {
738
+ "widget": "nautobot.core.forms.widgets.DatePicker",
739
+ "required": False,
740
+ },
741
+ ],
707
742
  }
708
743
 
709
744
  CONSTANCE_CONFIG = {
@@ -758,13 +793,13 @@ CONSTANCE_CONFIG = {
758
793
  field_type=bool,
759
794
  ),
760
795
  "MAX_PAGE_SIZE": ConstanceConfigItem(
761
- default=1000,
796
+ default=_MAX_PAGE_SIZE_DEFAULT,
762
797
  help_text="Maximum number of objects that a user can list in one UI page or one API call.\n"
763
798
  "If set to 0, a user can retrieve an unlimited number of objects.",
764
799
  field_type=int,
765
800
  ),
766
801
  "PAGINATE_COUNT": ConstanceConfigItem(
767
- default=50,
802
+ default=_PAGINATE_COUNT_DEFAULT,
768
803
  help_text="Default number of objects to display per page when listing objects in the UI and/or REST API.",
769
804
  field_type=int,
770
805
  ),
@@ -789,6 +824,12 @@ CONSTANCE_CONFIG = {
789
824
  # Use custom field type defined above
790
825
  field_type="optional_json_field",
791
826
  ),
827
+ "NTC_SUPPORT_CONTRACT_EXPIRATION_DATE": ConstanceConfigItem(
828
+ default="",
829
+ help_text="Expiration date for an active Nautobot support contract with Network to Code. "
830
+ "This value is displayed in the About page to provide additional support information.",
831
+ field_type="optional_date_field",
832
+ ),
792
833
  "PREFER_IPV4": ConstanceConfigItem(
793
834
  default=False,
794
835
  help_text="Whether to prefer IPv4 primary addresses over IPv6 primary addresses for devices.",
@@ -842,7 +883,7 @@ CONSTANCE_CONFIG_FIELDSETS = {
842
883
  "RACK_ELEVATION_UNIT_TWO_DIGIT_FORMAT",
843
884
  ],
844
885
  "Release Checking": ["RELEASE_CHECK_URL", "RELEASE_CHECK_TIMEOUT"],
845
- "User Interface": ["SUPPORT_MESSAGE"],
886
+ "User Interface": ["SUPPORT_MESSAGE", "NTC_SUPPORT_CONTRACT_EXPIRATION_DATE"],
846
887
  "Debugging": ["ALLOW_REQUEST_PROFILING"],
847
888
  }
848
889
 
@@ -1110,3 +1151,29 @@ def silk_request_logging_intercept_logic(request):
1110
1151
 
1111
1152
 
1112
1153
  SILKY_INTERCEPT_FUNC = silk_request_logging_intercept_logic
1154
+
1155
+ #
1156
+ # Kubernetes settings variables
1157
+ #
1158
+
1159
+ # Host of the kubernetes pod created in the kubernetes cluster
1160
+ KUBERNETES_DEFAULT_SERVICE_ADDRESS = os.getenv("NAUTOBOT_KUBERNETES_DEFAULT_SERVICE_ADDRESS", "")
1161
+
1162
+ # A dictionary that stores the kubernetes pod manifest used to create a job pod in the kubernetes cluster
1163
+ KUBERNETES_JOB_MANIFEST = {}
1164
+
1165
+ # Name of the kubernetes pod created in the kubernetes cluster
1166
+ KUBERNETES_JOB_POD_NAME = os.getenv("NAUTOBOT_KUBERNETES_JOB_POD_NAME", "")
1167
+
1168
+ # Namespace of the kubernetes pod created in the kubernetes cluster
1169
+ KUBERNETES_JOB_POD_NAMESPACE = os.getenv("NAUTOBOT_KUBERNETES_JOB_POD_NAMESPACE", "")
1170
+
1171
+ # File path to the SSL CA CERT used for authentication to create the job and job pod
1172
+ KUBERNETES_SSL_CA_CERT_PATH = os.getenv(
1173
+ "NAUTOBOT_KUBERNETES_SSL_CA_CERT_PATH", "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
1174
+ )
1175
+
1176
+ # File path to the Bearer token used for authentication to create the job and job pod
1177
+ KUBERNETES_TOKEN_PATH = os.getenv(
1178
+ "NAUTOBOT_KUBERNETES_TOKEN_PATH", "/var/run/secrets/kubernetes.io/serviceaccount/token"
1179
+ )
@@ -6,6 +6,8 @@ definitions:
6
6
  type: "string"
7
7
  callable:
8
8
  type: "string"
9
+ date:
10
+ type: "string"
9
11
  regex:
10
12
  type: "string"
11
13
  relative_path:
@@ -766,6 +768,57 @@ properties:
766
768
  is_constance_config: true
767
769
  type: "boolean"
768
770
  version_added: "2.0.0"
771
+ EVENT_BROKERS:
772
+ default: {}
773
+ description: >-
774
+ A dictionary defining event brokers that handle event publishing in Nautobot.
775
+ Each broker specifies its import path, along with topics to include or exclude
776
+ when publishing events.
777
+ details: |-
778
+ Each broker consists of a name, the class it uses for publishing events, and the topics
779
+ it filters. Topics are the categories of events that a broker will publish or exclude
780
+ based on the provided filters.
781
+
782
+ Example:
783
+
784
+ ```python
785
+ EVENT_BROKERS = {
786
+ "SyslogEventBroker": {
787
+ "CLASS": "nautobot.core.events.SyslogEventBroker",
788
+ "TOPICS": {
789
+ "INCLUDE": ["nautobot.test.*"],
790
+ "EXCLUDE": ["*.no-publish*"],
791
+ },
792
+ },
793
+ }
794
+ ```
795
+
796
+ In this example:
797
+ - **SyslogEventBroker** is the broker name.
798
+ - **CLASS** specifies the path to the event broker's Python class.
799
+ - **INCLUDE** filters the events the broker will publish, such as all topics starting with "nautobot.test."
800
+ - **EXCLUDE** filters out specific topics like those with "no-publish" in the name.
801
+
802
+ !!! note
803
+ If **INCLUDE** is set to ["*"], all topics will be published unless excluded by **EXCLUDE**.
804
+ properties:
805
+ CLASS:
806
+ type: "string"
807
+ TOPICS:
808
+ type: "object"
809
+ properties:
810
+ INCLUDE:
811
+ type: "array"
812
+ description: >-
813
+ List of topics that the broker should publish events for.
814
+ If empty or set to ["*"], all topics will be included.
815
+ EXCLUDE:
816
+ type: "array"
817
+ description: >-
818
+ List of topics that the broker should exclude from publishing.
819
+ If empty, no topics are excluded.
820
+ type: "object"
821
+ version_added: "2.4.0"
769
822
  EXEMPT_VIEW_PERMISSIONS:
770
823
  default: []
771
824
  description: "A list of Nautobot models to exempt from the enforcement of view permissions."
@@ -1007,6 +1060,41 @@ properties:
1007
1060
  +/- 2.0.0
1008
1061
  This directory no longer requires an `__init__.py` file.
1009
1062
  environment_variable: "NAUTOBOT_JOBS_ROOT"
1063
+ KUBERNETES_DEFAULT_SERVICE_ADDRESS:
1064
+ default: ""
1065
+ description: "HTTP address of the Kubernetes cluster. e.g. https://kubernetes.default.svc"
1066
+ environment_variable: "NAUTOBOT_KUBERNETES_DEFAULT_SERVICE_ADDRESS"
1067
+ type: "string"
1068
+ version_added: "2.4.0"
1069
+ KUBERNETES_JOB_MANIFEST:
1070
+ default: {}
1071
+ description: "A dictionary that contains the pod manifest used to create a job pod in the kubernetes cluster."
1072
+ type: "object"
1073
+ version_added: "2.4.0"
1074
+ KUBERNETES_JOB_POD_NAME:
1075
+ default: ""
1076
+ description: "Name of the Kubernetes pod."
1077
+ environment_variable: "NAUTOBOT_KUBERNETES_JOB_POD_NAME"
1078
+ type: "string"
1079
+ version_added: "2.4.0"
1080
+ KUBERNETES_JOB_POD_NAMESPACE:
1081
+ default: ""
1082
+ description: "Name of the namespace that the Kubernetes pod is created in."
1083
+ environment_variable: "NAUTOBOT_KUBERNETES_JOB_POD_NAMESPACE"
1084
+ type: "string"
1085
+ version_added: "2.4.0"
1086
+ KUBERNETES_SSL_CA_CERT_PATH:
1087
+ default: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
1088
+ description: "File path to the SSL CA CERT used for authentication to create the job and job pod."
1089
+ environment_variable: "NAUTOBOT_KUBERNETES_SSL_CA_CERT_PATH"
1090
+ type: "string"
1091
+ version_added: "2.4.0"
1092
+ KUBERNETES_TOKEN_PATH:
1093
+ default: "/var/run/secrets/kubernetes.io/serviceaccount/token"
1094
+ description: "File path to the Bearer token used for authentication to create the job and job pod."
1095
+ environment_variable: "NAUTOBOT_KUBERNETES_TOKEN_PATH"
1096
+ type: "string"
1097
+ version_added: "2.4.0"
1010
1098
  LOCATION_NAME_AS_NATURAL_KEY:
1011
1099
  default: false
1012
1100
  description: >-
@@ -1405,6 +1493,17 @@ properties:
1405
1493
  is_constance_config: true
1406
1494
  type: "object"
1407
1495
  version_added: "1.6.0"
1496
+ NTC_SUPPORT_CONTRACT_EXPIRATION_DATE:
1497
+ "$ref": "#/definitions/date"
1498
+ default: ""
1499
+ description: >-
1500
+ Expiration date for an active Nautobot support contract with Network to Code.
1501
+ This value is displayed in the "About" page to provide additional support information.
1502
+ details: >-
1503
+ If specified as an environment variable, use ISO 8601 (`YYYY-MM-DD`) format.
1504
+ environment_variable: "NAUTOBOT_NTC_SUPPORT_CONTRACT_EXPIRATION_DATE"
1505
+ is_constance_config: true
1506
+ version_added: "2.4.0"
1408
1507
  PAGINATE_COUNT:
1409
1508
  default: 50
1410
1509
  description: >-
@@ -1473,6 +1572,14 @@ properties:
1473
1572
  environment_variable: "NAUTOBOT_PREFER_IPV4"
1474
1573
  is_constance_config: true
1475
1574
  type: "boolean"
1575
+ PUBLISH_ROBOTS_TXT:
1576
+ default: true
1577
+ description: >-
1578
+ Setting this to true causes Nautobot to publish a `robots.txt` that discourages indexing by web crawlers.
1579
+ Irrelevant if deployed behind a firewall.
1580
+ environment_variable: "NAUTOBOT_PUBLISH_ROBOTS_TXT"
1581
+ type: "boolean"
1582
+ version_added: "2.3.15"
1476
1583
  RACK_ELEVATION_DEFAULT_UNIT_HEIGHT:
1477
1584
  default: 22
1478
1585
  description: >-
nautobot/core/tables.py CHANGED
@@ -4,7 +4,6 @@ import logging
4
4
  from django.contrib.auth.models import AnonymousUser
5
5
  from django.contrib.contenttypes.fields import GenericForeignKey
6
6
  from django.core.exceptions import FieldDoesNotExist, FieldError
7
- from django.db import NotSupportedError
8
7
  from django.db.models import Prefetch
9
8
  from django.db.models.fields.related import ForeignKey, RelatedField
10
9
  from django.db.models.fields.reverse_related import ManyToOneRel
@@ -22,6 +21,7 @@ from tree_queries.models import TreeNode
22
21
  from nautobot.core.models.querysets import count_related
23
22
  from nautobot.core.templatetags import helpers
24
23
  from nautobot.core.utils.lookup import get_model_for_view_name, get_related_field_for_models, get_route_for_model
24
+ from nautobot.core.utils.querysets import maybe_prefetch_related, maybe_select_related
25
25
  from nautobot.extras import choices, models
26
26
 
27
27
  logger = logging.getLogger(__name__)
@@ -64,6 +64,9 @@ class BaseTable(django_tables2.Table):
64
64
  returns new data. Runs after all of the queryset auto-optimization performed by this class.
65
65
  Used for example in IPAM views to inject "fake" records for "available" Prefixes, IPAddresses, or VLANs.
66
66
  **kwargs (dict, optional): Passed through to django_tables2.Table
67
+ Warning:
68
+ Do not modify/set the `base_columns` attribute after BaseTable class is instantiated.
69
+ Do not modify/set the `base_columns` attribute after calling super().__init__() of BaseTable class.
67
70
  """
68
71
  # Add custom field columns
69
72
  model = self._meta.model
@@ -236,51 +239,10 @@ class BaseTable(django_tables2.Table):
236
239
  prefetch_fields.append("__".join(prefetch_path))
237
240
 
238
241
  if select_fields:
239
- # Django doesn't allow .select_related() on a QuerySet that had .values()/.values_list() applied, or
240
- # one that has had union()/intersection()/difference() applied.
241
- # We can detect and avoid these cases the same way that Django itself does.
242
- if queryset._fields is not None:
243
- logger.debug(
244
- "NOT applying select_related(%s) to %s QuerySet as it includes .values()/.values_list()",
245
- select_fields,
246
- model.__name__,
247
- )
248
- elif queryset.query.combinator:
249
- logger.debug(
250
- "NOT applying select_related(%s) to %s QuerySet as it is a combinator query",
251
- select_fields,
252
- model.__name__,
253
- )
254
- else:
255
- logger.debug("Applying .select_related(%s) to %s QuerySet", select_fields, model.__name__)
256
- # Belt and suspenders - we should have avoided any error cases above, but be safe anyway:
257
- try:
258
- queryset = queryset.select_related(*select_fields)
259
- except (TypeError, ValueError, NotSupportedError) as exc:
260
- logger.warning(
261
- "Unexpected error when trying to .select_related() on %s QuerySet: %s",
262
- model.__name__,
263
- exc,
264
- )
242
+ queryset = maybe_select_related(queryset, select_fields)
265
243
 
266
244
  if prefetch_fields:
267
- if queryset.query.combinator:
268
- logger.debug(
269
- "NOT applying prefetch_related(%s) to %s QuerySet as it is a combinator query",
270
- prefetch_fields,
271
- model.__name__,
272
- )
273
- else:
274
- logger.debug("Applying .prefetch_related(%s) to %s QuerySet", prefetch_fields, model.__name__)
275
- # Belt and suspenders - we should have avoided any error cases above, but be safe anyway:
276
- try:
277
- queryset = queryset.prefetch_related(*prefetch_fields)
278
- except (AttributeError, TypeError, ValueError, NotSupportedError) as exc:
279
- logger.warning(
280
- "Unexpected error when trying to .prefetch_related() on %s QuerySet: %s",
281
- model.__name__,
282
- exc,
283
- )
245
+ queryset = maybe_prefetch_related(queryset, prefetch_fields)
284
246
 
285
247
  if count_fields:
286
248
  for column_name, column_model, lookup_name, distinct in count_fields:
@@ -314,7 +276,9 @@ class BaseTable(django_tables2.Table):
314
276
  @property
315
277
  def configurable_columns(self):
316
278
  selected_columns = [
317
- (name, self.columns[name].verbose_name) for name in self.sequence if name not in ["pk", "actions"]
279
+ (name, column.verbose_name)
280
+ for name, column in self.columns.items()
281
+ if name in self.sequence and name not in ["pk", "actions"]
318
282
  ]
319
283
  available_columns = [
320
284
  (name, column.verbose_name)
@@ -325,7 +289,7 @@ class BaseTable(django_tables2.Table):
325
289
 
326
290
  @property
327
291
  def visible_columns(self):
328
- return [name for name in self.sequence if self.columns[name].visible and name not in self.exclude]
292
+ return [name for name, column in self.columns.items() if column.visible and name not in self.exclude]
329
293
 
330
294
  @property
331
295
  def order_by(self):
@@ -480,7 +444,7 @@ class ChoiceFieldColumn(django_tables2.Column):
480
444
  choices. The CSS class is derived by calling .get_FOO_class() on the row record.
481
445
  """
482
446
 
483
- def render(self, record, bound_column, value): # pylint: disable=arguments-differ
447
+ def render(self, *, record, bound_column, value): # pylint: disable=arguments-differ # tables2 varies its kwargs
484
448
  if value:
485
449
  name = bound_column.name
486
450
  css_class = getattr(record, f"get_{name}_class")()
@@ -582,7 +546,7 @@ class LinkedCountColumn(django_tables2.Column):
582
546
  self.model = get_model_for_view_name(self.viewname)
583
547
  super().__init__(*args, default=default, **kwargs)
584
548
 
585
- def render(self, bound_column, record, value): # pylint: disable=arguments-differ
549
+ def render(self, *, bound_column, record, value): # pylint: disable=arguments-differ # tables2 varies its kwargs
586
550
  related_record = None
587
551
  try:
588
552
  lookup = self.lookup or get_related_field_for_models(bound_column._table._meta.model, self.model).name
@@ -666,7 +630,7 @@ class ComputedFieldColumn(django_tables2.Column):
666
630
 
667
631
  super().__init__(*args, **kwargs)
668
632
 
669
- def render(self, record):
633
+ def render(self, *, record): # pylint: disable=arguments-differ # tables2 varies its kwargs
670
634
  return self.computedfield.render({"obj": record})
671
635
 
672
636
 
@@ -685,7 +649,7 @@ class CustomFieldColumn(django_tables2.Column):
685
649
 
686
650
  super().__init__(*args, **kwargs)
687
651
 
688
- def render(self, record, bound_column, value): # pylint: disable=arguments-differ
652
+ def render(self, *, record, bound_column, value): # pylint: disable=arguments-differ # tables2 varies its kwargs
689
653
  if self.customfield.type == choices.CustomFieldTypeChoices.TYPE_BOOLEAN:
690
654
  template = helpers.render_boolean(value)
691
655
  elif self.customfield.type == choices.CustomFieldTypeChoices.TYPE_MULTISELECT:
@@ -716,7 +680,7 @@ class RelationshipColumn(django_tables2.Column):
716
680
  kwargs.setdefault("accessor", Accessor("associations"))
717
681
  super().__init__(orderable=False, *args, **kwargs)
718
682
 
719
- def render(self, record, value): # pylint: disable=arguments-differ
683
+ def render(self, *, record, value): # pylint: disable=arguments-differ # tables2 varies its kwargs
720
684
  # Filter the relationship associations by the relationship instance.
721
685
  # Since associations accessor returns all the relationship associations regardless of the relationship.
722
686
  value = [v for v in value if v.relationship == self.relationship]
nautobot/core/tasks.py CHANGED
@@ -49,7 +49,7 @@ def get_releases(pre_releases=False):
49
49
  cache.set(
50
50
  "nautobot.core.releases.get_latest_release",
51
51
  max(releases),
52
- config.get_settings_or_config("RELEASE_CHECK_TIMEOUT"),
52
+ config.get_settings_or_config("RELEASE_CHECK_TIMEOUT", fallback=24 * 3600),
53
53
  )
54
54
 
55
55
  # Since this is a Celery task, we can't return Version objects as they are not JSON serializable.