nautobot 2.2.8__py3-none-any.whl → 2.3.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 (704) hide show
  1. nautobot/apps/forms.py +4 -0
  2. nautobot/apps/models.py +10 -1
  3. nautobot/circuits/__init__.py +0 -1
  4. nautobot/circuits/apps.py +1 -0
  5. nautobot/circuits/factory.py +15 -3
  6. nautobot/circuits/filters.py +13 -0
  7. nautobot/circuits/forms.py +13 -0
  8. nautobot/circuits/migrations/0021_alter_circuit_status_alter_circuittermination__path.py +32 -0
  9. nautobot/circuits/migrations/0022_circuittermination_cloud_network.py +25 -0
  10. nautobot/circuits/models.py +16 -3
  11. nautobot/circuits/tables.py +16 -2
  12. nautobot/circuits/templates/circuits/circuittermination_create.html +10 -2
  13. nautobot/circuits/templates/circuits/circuittermination_retrieve.html +6 -0
  14. nautobot/circuits/templates/circuits/inc/circuit_termination.html +6 -1
  15. nautobot/circuits/tests/test_api.py +7 -5
  16. nautobot/circuits/tests/test_filters.py +12 -5
  17. nautobot/circuits/tests/test_models.py +33 -2
  18. nautobot/circuits/views.py +2 -3
  19. nautobot/cloud/__init__.py +0 -0
  20. nautobot/cloud/api/__init__.py +0 -0
  21. nautobot/cloud/api/serializers.py +54 -0
  22. nautobot/cloud/api/urls.py +16 -0
  23. nautobot/cloud/api/views.py +48 -0
  24. nautobot/cloud/apps.py +13 -0
  25. nautobot/cloud/factory.py +113 -0
  26. nautobot/cloud/filters.py +187 -0
  27. nautobot/cloud/forms.py +339 -0
  28. nautobot/cloud/homepage.py +43 -0
  29. nautobot/cloud/migrations/0001_initial.py +304 -0
  30. nautobot/cloud/migrations/__init__.py +0 -0
  31. nautobot/cloud/models.py +246 -0
  32. nautobot/cloud/navigation.py +85 -0
  33. nautobot/cloud/tables.py +157 -0
  34. nautobot/cloud/templates/cloud/cloudaccount_retrieve.html +43 -0
  35. nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +122 -0
  36. nautobot/cloud/templates/cloud/cloudnetwork_update.html +33 -0
  37. nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +111 -0
  38. nautobot/cloud/templates/cloud/cloudservice_retrieve.html +69 -0
  39. nautobot/cloud/templates/cloud/cloudservice_update.html +25 -0
  40. nautobot/cloud/tests/__init__.py +0 -0
  41. nautobot/cloud/tests/test_api.py +248 -0
  42. nautobot/cloud/tests/test_filters.py +125 -0
  43. nautobot/cloud/tests/test_models.py +43 -0
  44. nautobot/cloud/tests/test_views.py +153 -0
  45. nautobot/cloud/urls.py +14 -0
  46. nautobot/cloud/views.py +181 -0
  47. nautobot/core/__init__.py +0 -3
  48. nautobot/core/api/metadata.py +1 -0
  49. nautobot/core/api/parsers.py +7 -1
  50. nautobot/core/api/urls.py +1 -0
  51. nautobot/core/api/utils.py +1 -0
  52. nautobot/core/api/views.py +4 -0
  53. nautobot/core/apps/__init__.py +6 -3
  54. nautobot/core/constants.py +8 -0
  55. nautobot/core/factory.py +32 -1
  56. nautobot/core/filters.py +110 -14
  57. nautobot/core/forms/fields.py +10 -4
  58. nautobot/core/forms/forms.py +11 -3
  59. nautobot/core/forms/widgets.py +18 -1
  60. nautobot/core/graphql/generators.py +2 -2
  61. nautobot/core/graphql/schema.py +28 -7
  62. nautobot/core/jobs/__init__.py +20 -3
  63. nautobot/core/jobs/cleanup.py +100 -0
  64. nautobot/core/jobs/groups.py +38 -0
  65. nautobot/core/management/commands/generate_test_data.py +116 -3
  66. nautobot/core/models/__init__.py +34 -9
  67. nautobot/core/models/generics.py +19 -3
  68. nautobot/core/models/name_color_content_types.py +7 -28
  69. nautobot/core/models/querysets.py +4 -3
  70. nautobot/core/models/tree_queries.py +1 -1
  71. nautobot/core/models/utils.py +21 -5
  72. nautobot/core/settings.py +15 -19
  73. nautobot/core/settings.yaml +48 -13
  74. nautobot/core/settings_funcs.py +103 -0
  75. nautobot/core/tables.py +130 -56
  76. nautobot/core/templates/admin/search_form.html +1 -1
  77. nautobot/core/templates/buttons/add.html +11 -3
  78. nautobot/core/templates/buttons/consolidated_bulk_action_buttons.html +13 -0
  79. nautobot/core/templates/buttons/consolidated_detail_view_action_buttons.html +13 -0
  80. nautobot/core/templates/buttons/export.html +101 -53
  81. nautobot/core/templates/buttons/job_import.html +11 -3
  82. nautobot/core/templates/generic/object_bulk_destroy.html +3 -1
  83. nautobot/core/templates/generic/object_bulk_update.html +3 -1
  84. nautobot/core/templates/generic/object_changelog.html +0 -9
  85. nautobot/core/templates/generic/object_list.html +156 -17
  86. nautobot/core/templates/generic/object_retrieve.html +80 -16
  87. nautobot/core/templates/inc/extras_features_edit_form_fields.html +8 -0
  88. nautobot/core/templates/inc/javascript.html +2 -0
  89. nautobot/core/templates/inc/media.html +2 -2
  90. nautobot/core/templates/inc/nav_menu.html +1 -0
  91. nautobot/core/templates/inc/paginator.html +7 -7
  92. nautobot/core/templates/inc/search_panel.html +2 -2
  93. nautobot/core/templates/inc/table.html +2 -2
  94. nautobot/core/templates/nautobot_config.py.j2 +28 -8
  95. nautobot/core/templates/utilities/templatetags/dynamic_group_assignment_modal.html +37 -0
  96. nautobot/core/templates/utilities/templatetags/filter_form_modal.html +2 -2
  97. nautobot/core/templates/utilities/templatetags/saved_view_modal.html +38 -0
  98. nautobot/core/templates/utilities/theme_preview.html +25 -8
  99. nautobot/core/templates/utilities/worker_status.html +152 -0
  100. nautobot/core/templatetags/buttons.py +335 -38
  101. nautobot/core/templatetags/form_helpers.py +1 -1
  102. nautobot/core/templatetags/helpers.py +181 -11
  103. nautobot/core/testing/api.py +5 -4
  104. nautobot/core/testing/filters.py +63 -14
  105. nautobot/core/testing/mixins.py +46 -0
  106. nautobot/core/testing/models.py +22 -0
  107. nautobot/core/testing/schema.py +4 -8
  108. nautobot/core/testing/views.py +31 -14
  109. nautobot/core/tests/integration/test_general_functionality.py +1 -1
  110. nautobot/core/tests/integration/test_import_objects_ui.py +1 -0
  111. nautobot/core/tests/integration/test_swagger.py +1 -1
  112. nautobot/core/tests/nautobot_config.py +0 -1
  113. nautobot/core/tests/runner.py +2 -2
  114. nautobot/core/tests/test_api.py +1 -0
  115. nautobot/core/tests/test_authentication.py +7 -2
  116. nautobot/core/tests/test_filters.py +11 -9
  117. nautobot/core/tests/test_forms.py +9 -0
  118. nautobot/core/tests/test_graphql.py +27 -16
  119. nautobot/core/tests/test_jobs.py +204 -2
  120. nautobot/core/tests/test_tables.py +3 -1
  121. nautobot/core/tests/test_templatetags_helpers.py +12 -5
  122. nautobot/core/tests/test_templatetags_netutils.py +3 -3
  123. nautobot/core/tests/test_utils.py +31 -20
  124. nautobot/core/tests/test_views.py +6 -6
  125. nautobot/core/urls.py +8 -3
  126. nautobot/core/utils/deprecation.py +29 -0
  127. nautobot/core/utils/filtering.py +12 -9
  128. nautobot/core/utils/lookup.py +37 -2
  129. nautobot/core/utils/requests.py +4 -1
  130. nautobot/core/views/__init__.py +137 -24
  131. nautobot/core/views/generic.py +119 -67
  132. nautobot/core/views/mixins.py +105 -36
  133. nautobot/core/views/paginator.py +9 -3
  134. nautobot/core/views/renderers.py +121 -56
  135. nautobot/core/views/utils.py +81 -1
  136. nautobot/dcim/__init__.py +0 -1
  137. nautobot/dcim/api/serializers.py +180 -44
  138. nautobot/dcim/api/urls.py +7 -3
  139. nautobot/dcim/api/views.py +53 -7
  140. nautobot/dcim/apps.py +3 -0
  141. nautobot/dcim/choices.py +25 -0
  142. nautobot/dcim/constants.py +7 -0
  143. nautobot/dcim/factory.py +252 -18
  144. nautobot/dcim/filters/__init__.py +373 -193
  145. nautobot/dcim/filters/mixins.py +274 -1
  146. nautobot/dcim/forms.py +834 -121
  147. nautobot/dcim/graphql/types.py +2 -2
  148. nautobot/dcim/homepage.py +1 -1
  149. nautobot/dcim/migrations/0059_add_role_field_to_interface_models.py +27 -0
  150. nautobot/dcim/migrations/0060_alter_cable_status_alter_consoleport__path_and_more.py +303 -0
  151. nautobot/dcim/migrations/0061_module_models.py +862 -0
  152. nautobot/dcim/migrations/0062_module_data_migration.py +25 -0
  153. nautobot/dcim/models/__init__.py +8 -0
  154. nautobot/dcim/models/cables.py +15 -0
  155. nautobot/dcim/models/device_component_templates.py +207 -53
  156. nautobot/dcim/models/device_components.py +282 -99
  157. nautobot/dcim/models/devices.py +472 -13
  158. nautobot/dcim/models/racks.py +0 -1
  159. nautobot/dcim/navigation.py +47 -0
  160. nautobot/dcim/signals.py +3 -3
  161. nautobot/dcim/tables/__init__.py +35 -23
  162. nautobot/dcim/tables/devices.py +248 -47
  163. nautobot/dcim/tables/devicetypes.py +65 -9
  164. nautobot/dcim/tables/racks.py +5 -1
  165. nautobot/dcim/tables/template_code.py +46 -26
  166. nautobot/dcim/templates/dcim/cable_connect.html +76 -3
  167. nautobot/dcim/templates/dcim/console_port_connection_list.html +7 -5
  168. nautobot/dcim/templates/dcim/device/base.html +14 -6
  169. nautobot/dcim/templates/dcim/device/consoleports.html +2 -3
  170. nautobot/dcim/templates/dcim/device/consoleserverports.html +2 -3
  171. nautobot/dcim/templates/dcim/device/devicebays.html +6 -7
  172. nautobot/dcim/templates/dcim/device/frontports.html +2 -3
  173. nautobot/dcim/templates/dcim/device/interfaces.html +2 -3
  174. nautobot/dcim/templates/dcim/device/inventory.html +2 -3
  175. nautobot/dcim/templates/dcim/device/modulebays.html +49 -0
  176. nautobot/dcim/templates/dcim/device/poweroutlets.html +2 -3
  177. nautobot/dcim/templates/dcim/device/powerports.html +2 -3
  178. nautobot/dcim/templates/dcim/device/rearports.html +2 -3
  179. nautobot/dcim/templates/dcim/device.html +45 -1
  180. nautobot/dcim/templates/dcim/device_component.html +13 -5
  181. nautobot/dcim/templates/dcim/device_list.html +2 -1
  182. nautobot/dcim/templates/dcim/deviceredundancygroup_retrieve.html +6 -0
  183. nautobot/dcim/templates/dcim/devicetype.html +99 -98
  184. nautobot/dcim/templates/dcim/devicetype_list.html +8 -16
  185. nautobot/dcim/templates/dcim/inc/devicetype_component_table.html +1 -1
  186. nautobot/dcim/templates/dcim/inc/moduletype_component_table.html +39 -0
  187. nautobot/dcim/templates/dcim/interface.html +17 -2
  188. nautobot/dcim/templates/dcim/interface_connection_list.html +7 -5
  189. nautobot/dcim/templates/dcim/interface_edit.html +1 -0
  190. nautobot/dcim/templates/dcim/manufacturer.html +24 -0
  191. nautobot/dcim/templates/dcim/module/base.html +97 -0
  192. nautobot/dcim/templates/dcim/module_bulk_destroy.html +5 -0
  193. nautobot/dcim/templates/dcim/module_consoleports.html +53 -0
  194. nautobot/dcim/templates/dcim/module_consoleserverports.html +53 -0
  195. nautobot/dcim/templates/dcim/module_destroy.html +5 -0
  196. nautobot/dcim/templates/dcim/module_frontports.html +53 -0
  197. nautobot/dcim/templates/dcim/module_interfaces.html +57 -0
  198. nautobot/dcim/templates/dcim/module_list.html +20 -0
  199. nautobot/dcim/templates/dcim/module_modulebays.html +49 -0
  200. nautobot/dcim/templates/dcim/module_poweroutlets.html +53 -0
  201. nautobot/dcim/templates/dcim/module_powerports.html +53 -0
  202. nautobot/dcim/templates/dcim/module_rearports.html +53 -0
  203. nautobot/dcim/templates/dcim/module_retrieve.html +63 -0
  204. nautobot/dcim/templates/dcim/module_update.html +71 -0
  205. nautobot/dcim/templates/dcim/modulebay_bulk_destroy.html +5 -0
  206. nautobot/dcim/templates/dcim/modulebay_destroy.html +8 -0
  207. nautobot/dcim/templates/dcim/modulebay_retrieve.html +101 -0
  208. nautobot/dcim/templates/dcim/moduletype_list.html +11 -0
  209. nautobot/dcim/templates/dcim/moduletype_retrieve.html +159 -0
  210. nautobot/dcim/templates/dcim/power_port_connection_list.html +7 -5
  211. nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +65 -19
  212. nautobot/dcim/tests/integration/test_cable_connect_form.py +4 -4
  213. nautobot/dcim/tests/test_api.py +693 -208
  214. nautobot/dcim/tests/test_filters.py +843 -217
  215. nautobot/dcim/tests/test_models.py +1103 -8
  216. nautobot/dcim/tests/test_views.py +1525 -343
  217. nautobot/dcim/urls.py +17 -2
  218. nautobot/dcim/utils.py +2 -3
  219. nautobot/dcim/views.py +1109 -113
  220. nautobot/extras/__init__.py +0 -1
  221. nautobot/extras/api/serializers.py +115 -3
  222. nautobot/extras/api/urls.py +12 -0
  223. nautobot/extras/api/views.py +73 -59
  224. nautobot/extras/apps.py +2 -2
  225. nautobot/extras/choices.py +43 -0
  226. nautobot/extras/context_managers.py +13 -8
  227. nautobot/extras/datasources/git.py +2 -0
  228. nautobot/extras/factory.py +460 -9
  229. nautobot/extras/filters/__init__.py +174 -3
  230. nautobot/extras/filters/mixins.py +46 -43
  231. nautobot/extras/forms/base.py +24 -5
  232. nautobot/extras/forms/forms.py +227 -8
  233. nautobot/extras/forms/mixins.py +93 -0
  234. nautobot/extras/graphql/types.py +23 -10
  235. nautobot/extras/homepage.py +26 -3
  236. nautobot/extras/jobs.py +2 -2
  237. nautobot/extras/management/__init__.py +1 -0
  238. nautobot/extras/management/commands/refresh_dynamic_group_member_caches.py +1 -16
  239. nautobot/extras/migrations/0021_customfield_changelog_data.py +1 -0
  240. nautobot/extras/migrations/0109_dynamicgroup_group_type_dynamicgroup_tags_and_more.py +108 -0
  241. nautobot/extras/migrations/0110_alter_configcontext_cluster_groups_and_more.py +111 -0
  242. nautobot/extras/migrations/0111_metadata.py +162 -0
  243. nautobot/extras/migrations/0112_dynamic_group_group_type_data_migration.py +28 -0
  244. nautobot/extras/migrations/0113_saved_views.py +77 -0
  245. nautobot/extras/models/__init__.py +15 -1
  246. nautobot/extras/models/change_logging.py +3 -3
  247. nautobot/extras/models/contacts.py +4 -0
  248. nautobot/extras/models/customfields.py +18 -3
  249. nautobot/extras/models/groups.py +389 -225
  250. nautobot/extras/models/jobs.py +87 -3
  251. nautobot/extras/models/metadata.py +441 -0
  252. nautobot/extras/models/mixins.py +72 -62
  253. nautobot/extras/models/models.py +118 -9
  254. nautobot/extras/models/relationships.py +9 -2
  255. nautobot/extras/models/tags.py +13 -2
  256. nautobot/extras/navigation.py +57 -0
  257. nautobot/extras/plugins/__init__.py +3 -1
  258. nautobot/extras/querysets.py +30 -66
  259. nautobot/extras/signals.py +109 -101
  260. nautobot/extras/tables.py +201 -17
  261. nautobot/extras/templates/extras/dynamicgroup.html +44 -15
  262. nautobot/extras/templates/extras/dynamicgroup_edit.html +2 -0
  263. nautobot/extras/templates/extras/job.html +1 -1
  264. nautobot/extras/templates/extras/job_detail.html +11 -0
  265. nautobot/extras/templates/extras/jobresult.html +61 -74
  266. nautobot/extras/templates/extras/metadatatype_create.html +89 -0
  267. nautobot/extras/templates/extras/metadatatype_retrieve.html +67 -0
  268. nautobot/extras/templates/extras/object_dynamicgroups.html +7 -0
  269. nautobot/extras/templates/extras/objectchange_list.html +0 -12
  270. nautobot/extras/templates/extras/plugins_list.html +1 -3
  271. nautobot/extras/templates/extras/role_retrieve.html +48 -0
  272. nautobot/extras/templates/extras/staticgroupassociation_retrieve.html +20 -0
  273. nautobot/extras/tests/integration/test_customfields.py +1 -0
  274. nautobot/extras/tests/test_api.py +509 -23
  275. nautobot/extras/tests/test_changelog.py +20 -9
  276. nautobot/extras/tests/test_context_managers.py +22 -15
  277. nautobot/extras/tests/test_datasources.py +13 -1
  278. nautobot/extras/tests/test_dynamicgroups.py +201 -171
  279. nautobot/extras/tests/test_filters.py +211 -12
  280. nautobot/extras/tests/test_jobs.py +6 -6
  281. nautobot/extras/tests/test_models.py +501 -4
  282. nautobot/extras/tests/test_relationships.py +1 -0
  283. nautobot/extras/tests/test_views.py +586 -8
  284. nautobot/extras/tests/test_webhooks.py +1 -1
  285. nautobot/extras/urls.py +5 -0
  286. nautobot/extras/utils.py +85 -16
  287. nautobot/extras/views.py +562 -122
  288. nautobot/ipam/__init__.py +0 -1
  289. nautobot/ipam/apps.py +1 -0
  290. nautobot/ipam/factory.py +17 -19
  291. nautobot/ipam/filters.py +13 -0
  292. nautobot/ipam/forms.py +8 -4
  293. nautobot/ipam/graphql/types.py +2 -2
  294. nautobot/ipam/migrations/0047_alter_ipaddress_role_alter_ipaddress_status_and_more.py +59 -0
  295. nautobot/ipam/models.py +20 -20
  296. nautobot/ipam/querysets.py +1 -1
  297. nautobot/ipam/signals.py +4 -2
  298. nautobot/ipam/tables.py +5 -0
  299. nautobot/ipam/templates/ipam/ipaddress_interfaces.html +1 -1
  300. nautobot/ipam/templates/ipam/ipaddress_vm_interfaces.html +1 -1
  301. nautobot/ipam/templates/ipam/prefix.html +1 -0
  302. nautobot/ipam/tests/test_api.py +37 -18
  303. nautobot/ipam/tests/test_filters.py +26 -2
  304. nautobot/ipam/tests/test_models.py +9 -2
  305. nautobot/ipam/tests/test_querysets.py +1 -1
  306. nautobot/ipam/tests/test_views.py +3 -2
  307. nautobot/ipam/urls.py +2 -2
  308. nautobot/ipam/views.py +20 -34
  309. nautobot/project-static/css/base.css +21 -0
  310. nautobot/project-static/css/dark.css +11 -0
  311. nautobot/project-static/docs/404.html +894 -90
  312. nautobot/project-static/docs/apps/index.html +894 -90
  313. nautobot/project-static/docs/apps/nautobot-apps.html +894 -90
  314. nautobot/project-static/docs/assets/_mkdocstrings.css +5 -0
  315. nautobot/project-static/docs/assets/stylesheets/main.3cba04c6.min.css +1 -0
  316. nautobot/project-static/docs/assets/stylesheets/main.3cba04c6.min.css.map +1 -0
  317. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +921 -122
  318. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +906 -103
  319. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +1620 -905
  320. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +937 -146
  321. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +979 -190
  322. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +903 -101
  323. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +899 -95
  324. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +993 -195
  325. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +976 -133
  326. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +1080 -274
  327. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +1244 -336
  328. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +1729 -877
  329. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +1166 -383
  330. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +2090 -1376
  331. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +2248 -1424
  332. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +914 -113
  333. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +965 -165
  334. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +1012 -225
  335. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +1915 -1279
  336. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +1848 -1104
  337. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +906 -103
  338. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +2335 -1701
  339. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +1804 -1026
  340. nautobot/project-static/docs/development/apps/api/configuration-view.html +894 -90
  341. nautobot/project-static/docs/development/apps/api/database-backend-config.html +894 -90
  342. nautobot/project-static/docs/development/apps/api/models/django-admin.html +894 -90
  343. nautobot/project-static/docs/development/apps/api/models/global-search.html +894 -90
  344. nautobot/project-static/docs/development/apps/api/models/graphql.html +894 -90
  345. nautobot/project-static/docs/development/apps/api/models/index.html +944 -92
  346. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +894 -90
  347. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +894 -90
  348. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +894 -90
  349. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +894 -90
  350. nautobot/project-static/docs/development/apps/api/platform-features/index.html +894 -90
  351. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +894 -90
  352. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +894 -90
  353. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +894 -90
  354. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +894 -90
  355. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +894 -90
  356. nautobot/project-static/docs/development/apps/api/prometheus.html +894 -90
  357. nautobot/project-static/docs/development/apps/api/setup.html +894 -90
  358. nautobot/project-static/docs/development/apps/api/testing.html +894 -90
  359. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +894 -90
  360. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +894 -90
  361. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +894 -90
  362. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +894 -90
  363. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +894 -90
  364. nautobot/project-static/docs/development/apps/api/views/base-template.html +894 -90
  365. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +894 -90
  366. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +894 -90
  367. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +894 -90
  368. nautobot/project-static/docs/development/apps/api/views/index.html +894 -90
  369. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +894 -90
  370. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +894 -90
  371. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +894 -90
  372. nautobot/project-static/docs/development/apps/api/views/notes.html +894 -90
  373. nautobot/project-static/docs/development/apps/api/views/rest-api.html +894 -90
  374. nautobot/project-static/docs/development/apps/api/views/urls.html +894 -90
  375. nautobot/project-static/docs/development/apps/index.html +894 -90
  376. nautobot/project-static/docs/development/apps/migration/code-updates.html +894 -90
  377. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +894 -90
  378. nautobot/project-static/docs/development/apps/migration/from-v1.html +894 -90
  379. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +894 -90
  380. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +894 -90
  381. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +894 -90
  382. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +894 -90
  383. nautobot/project-static/docs/development/apps/porting-from-netbox.html +894 -90
  384. nautobot/project-static/docs/development/core/application-registry.html +894 -90
  385. nautobot/project-static/docs/development/core/best-practices.html +895 -90
  386. nautobot/project-static/docs/development/core/bootstrap-ui.html +894 -90
  387. nautobot/project-static/docs/development/core/caching.html +894 -90
  388. nautobot/project-static/docs/development/core/controllers.html +894 -90
  389. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +894 -90
  390. nautobot/project-static/docs/development/core/generic-views.html +894 -90
  391. nautobot/project-static/docs/development/core/getting-started.html +894 -90
  392. nautobot/project-static/docs/development/core/homepage.html +894 -90
  393. nautobot/project-static/docs/development/core/index.html +905 -90
  394. nautobot/project-static/docs/development/core/model-checklist.html +903 -91
  395. nautobot/project-static/docs/development/core/model-features.html +894 -90
  396. nautobot/project-static/docs/development/core/natural-keys.html +894 -90
  397. nautobot/project-static/docs/development/core/navigation-menu.html +894 -90
  398. nautobot/project-static/docs/development/core/release-checklist.html +897 -93
  399. nautobot/project-static/docs/development/core/role-internals.html +894 -90
  400. nautobot/project-static/docs/development/core/settings.html +894 -90
  401. nautobot/project-static/docs/development/core/style-guide.html +895 -91
  402. nautobot/project-static/docs/development/core/templates.html +906 -91
  403. nautobot/project-static/docs/development/core/testing.html +894 -90
  404. nautobot/project-static/docs/development/core/user-preferences.html +894 -90
  405. nautobot/project-static/docs/development/index.html +894 -90
  406. nautobot/project-static/docs/development/jobs/index.html +1271 -453
  407. nautobot/project-static/docs/development/jobs/migration/from-v1.html +894 -90
  408. nautobot/project-static/docs/index.html +9032 -13
  409. nautobot/project-static/docs/media/models/cloud_aws_direct_connect_dark.png +0 -0
  410. nautobot/project-static/docs/media/models/cloud_aws_direct_connect_light.png +0 -0
  411. nautobot/project-static/docs/models/cloud/cloudaccount.html +15 -0
  412. nautobot/project-static/docs/models/cloud/cloudnetwork.html +15 -0
  413. nautobot/project-static/docs/models/cloud/cloudnetworkprefixassignment.html +15 -0
  414. nautobot/project-static/docs/models/cloud/cloudresourcetype.html +15 -0
  415. nautobot/project-static/docs/models/cloud/cloudservice.html +15 -0
  416. nautobot/project-static/docs/models/cloud/cloudservicenetworkassignment.html +15 -0
  417. nautobot/project-static/docs/models/dcim/module.html +15 -0
  418. nautobot/project-static/docs/models/dcim/modulebay.html +15 -0
  419. nautobot/project-static/docs/models/dcim/modulebaytemplate.html +15 -0
  420. nautobot/project-static/docs/models/dcim/moduletype.html +15 -0
  421. nautobot/project-static/docs/models/extras/metadatachoice.html +15 -0
  422. nautobot/project-static/docs/models/extras/metadatatype.html +15 -0
  423. nautobot/project-static/docs/models/extras/objectmetadata.html +15 -0
  424. nautobot/project-static/docs/models/extras/role.html +15 -0
  425. nautobot/project-static/docs/models/extras/savedview.html +15 -0
  426. nautobot/project-static/docs/models/extras/staticgroupassociation.html +15 -0
  427. nautobot/project-static/docs/models/extras/status.html +15 -0
  428. nautobot/project-static/docs/objects.inv +0 -0
  429. nautobot/project-static/docs/overview/application_stack.html +902 -91
  430. nautobot/project-static/docs/overview/design_philosophy.html +896 -92
  431. nautobot/project-static/docs/overview/index.html +13 -8228
  432. nautobot/project-static/docs/release-notes/index.html +1131 -94
  433. nautobot/project-static/docs/release-notes/version-1.0.html +894 -90
  434. nautobot/project-static/docs/release-notes/version-1.1.html +894 -90
  435. nautobot/project-static/docs/release-notes/version-1.2.html +894 -90
  436. nautobot/project-static/docs/release-notes/version-1.3.html +894 -90
  437. nautobot/project-static/docs/release-notes/version-1.4.html +894 -90
  438. nautobot/project-static/docs/release-notes/version-1.5.html +895 -91
  439. nautobot/project-static/docs/release-notes/version-1.6.html +895 -91
  440. nautobot/project-static/docs/release-notes/version-2.0.html +894 -90
  441. nautobot/project-static/docs/release-notes/version-2.1.html +894 -90
  442. nautobot/project-static/docs/release-notes/version-2.2.html +1137 -196
  443. nautobot/project-static/docs/release-notes/version-2.3.html +9954 -0
  444. nautobot/project-static/docs/requirements.txt +5 -5
  445. nautobot/project-static/docs/search/search_index.json +1 -1
  446. nautobot/project-static/docs/sitemap.xml +335 -260
  447. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  448. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +894 -90
  449. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +894 -90
  450. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +894 -90
  451. nautobot/project-static/docs/user-guide/administration/configuration/index.html +894 -90
  452. nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +1025 -175
  453. nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +894 -90
  454. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +894 -90
  455. nautobot/project-static/docs/user-guide/administration/guides/caching.html +894 -90
  456. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +902 -90
  457. nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +894 -90
  458. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +894 -90
  459. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +894 -90
  460. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +894 -90
  461. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +894 -90
  462. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +894 -90
  463. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +894 -90
  464. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +894 -90
  465. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +946 -155
  466. nautobot/project-static/docs/user-guide/administration/installation/index.html +903 -95
  467. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +936 -124
  468. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +956 -159
  469. nautobot/project-static/docs/user-guide/administration/installation/services.html +915 -114
  470. nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +910 -101
  471. nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +894 -90
  472. nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +894 -90
  473. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +894 -90
  474. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +894 -90
  475. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +977 -121
  476. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +894 -90
  477. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +894 -90
  478. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +894 -90
  479. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +894 -90
  480. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +894 -90
  481. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +894 -90
  482. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +894 -90
  483. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +894 -90
  484. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +894 -90
  485. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +894 -90
  486. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +894 -90
  487. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +895 -91
  488. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +894 -90
  489. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +898 -90
  490. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +897 -93
  491. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +8984 -0
  492. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +8828 -0
  493. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +8829 -0
  494. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +8828 -0
  495. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +8829 -0
  496. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +8833 -0
  497. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +8828 -0
  498. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +908 -104
  499. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +925 -107
  500. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +925 -107
  501. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +920 -102
  502. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +925 -107
  503. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +908 -104
  504. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +908 -104
  505. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +915 -107
  506. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +922 -118
  507. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +923 -119
  508. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +920 -116
  509. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +908 -104
  510. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +916 -107
  511. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +928 -110
  512. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +938 -120
  513. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +930 -108
  514. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +908 -104
  515. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +939 -121
  516. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +930 -112
  517. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +920 -116
  518. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +923 -119
  519. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +925 -117
  520. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +8828 -0
  521. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +8846 -0
  522. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +8843 -0
  523. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +8823 -0
  524. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +918 -114
  525. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +908 -104
  526. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +942 -85
  527. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +926 -108
  528. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +908 -104
  529. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +945 -88
  530. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +923 -105
  531. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +931 -127
  532. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +920 -116
  533. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +908 -104
  534. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +924 -106
  535. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +926 -108
  536. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +908 -104
  537. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +908 -104
  538. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +908 -104
  539. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +938 -90
  540. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +894 -90
  541. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +899 -91
  542. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +899 -91
  543. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +894 -90
  544. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +894 -90
  545. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +894 -90
  546. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +894 -90
  547. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +894 -90
  548. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +894 -90
  549. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +894 -90
  550. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +894 -90
  551. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +894 -90
  552. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +894 -90
  553. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +903 -98
  554. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +894 -90
  555. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +894 -90
  556. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +894 -90
  557. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +894 -90
  558. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +894 -90
  559. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +899 -91
  560. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +894 -90
  561. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +894 -90
  562. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +894 -90
  563. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +894 -90
  564. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +894 -90
  565. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +894 -90
  566. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +894 -90
  567. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +894 -90
  568. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +894 -90
  569. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +894 -90
  570. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +894 -90
  571. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +894 -90
  572. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +894 -90
  573. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/clear-view-button.png +0 -0
  574. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/cleared-view.png +0 -0
  575. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/config-table-columns-to-locations.png +0 -0
  576. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/configure-button.png +0 -0
  577. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/create-saved-view-success.png +0 -0
  578. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/current-saved-view-drop-down-menu.png +0 -0
  579. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/default-location-list-view.png +0 -0
  580. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/dropdown-button-after-new-saved-view.png +0 -0
  581. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/filter-application-to-locations.png +0 -0
  582. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/filter-button.png +0 -0
  583. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/global-default-location-list-view.png +0 -0
  584. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/location-list-view-with-saved-views.png +0 -0
  585. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/navigation-menu.png +0 -0
  586. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/save-as-new-view-drop-down.png +0 -0
  587. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/save-view-modal.png +0 -0
  588. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-buttons.png +0 -0
  589. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-success.png +0 -0
  590. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-view-unchecked.png +0 -0
  591. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-view.png +0 -0
  592. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-different-user.png +0 -0
  593. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-modal-unchecked.png +0 -0
  594. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/set-as-my-default-button.png +0 -0
  595. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/set-as-my-default-success.png +0 -0
  596. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/unsaved-saved-view.png +0 -0
  597. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/updated-saved-view.png +0 -0
  598. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +894 -90
  599. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +894 -90
  600. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +894 -90
  601. nautobot/project-static/docs/user-guide/index.html +894 -90
  602. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +894 -90
  603. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +894 -90
  604. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +894 -90
  605. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +894 -90
  606. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +1260 -787
  607. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +897 -93
  608. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +894 -90
  609. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +894 -90
  610. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +894 -90
  611. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +894 -90
  612. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +894 -90
  613. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +894 -90
  614. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +894 -90
  615. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +894 -90
  616. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +894 -90
  617. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +898 -90
  618. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +894 -90
  619. nautobot/project-static/docs/user-guide/platform-functionality/note.html +897 -93
  620. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +9061 -0
  621. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +897 -93
  622. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +894 -90
  623. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +894 -90
  624. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +894 -90
  625. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +894 -90
  626. nautobot/project-static/docs/user-guide/platform-functionality/role.html +897 -93
  627. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +9137 -0
  628. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +897 -93
  629. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +8933 -0
  630. nautobot/project-static/docs/user-guide/platform-functionality/status.html +894 -90
  631. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +894 -90
  632. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +952 -123
  633. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +894 -90
  634. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +894 -90
  635. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +894 -90
  636. nautobot/project-static/js/forms.js +71 -0
  637. nautobot/project-static/js/table_sorting_indicator.js +46 -0
  638. nautobot/project-static/js/tableconfig.js +6 -1
  639. nautobot/project-static/materialdesignicons-7.4.47/css/materialdesignicons.min.css +3 -0
  640. nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/fonts/materialdesignicons-webfont.eot +0 -0
  641. nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/fonts/materialdesignicons-webfont.ttf +0 -0
  642. nautobot/project-static/materialdesignicons-7.4.47/fonts/materialdesignicons-webfont.woff +0 -0
  643. nautobot/project-static/materialdesignicons-7.4.47/fonts/materialdesignicons-webfont.woff2 +0 -0
  644. nautobot/tenancy/__init__.py +0 -1
  645. nautobot/tenancy/apps.py +1 -0
  646. nautobot/tenancy/factory.py +3 -2
  647. nautobot/tenancy/filters/__init__.py +1 -0
  648. nautobot/tenancy/forms.py +1 -1
  649. nautobot/tenancy/templates/tenancy/tenant.html +24 -20
  650. nautobot/tenancy/views.py +11 -10
  651. nautobot/users/__init__.py +0 -1
  652. nautobot/users/api/serializers.py +1 -1
  653. nautobot/users/api/views.py +4 -2
  654. nautobot/users/apps.py +3 -2
  655. nautobot/users/factory.py +3 -3
  656. nautobot/users/migrations/0010_user_default_saved_views.py +20 -0
  657. nautobot/users/models.py +12 -0
  658. nautobot/users/tests/test_filters.py +6 -3
  659. nautobot/users/urls.py +8 -0
  660. nautobot/virtualization/__init__.py +0 -1
  661. nautobot/virtualization/apps.py +1 -0
  662. nautobot/virtualization/filters.py +6 -1
  663. nautobot/virtualization/forms.py +11 -3
  664. nautobot/virtualization/graphql/types.py +2 -2
  665. nautobot/virtualization/migrations/0029_add_role_field_to_interface_models.py +27 -0
  666. nautobot/virtualization/migrations/0030_alter_virtualmachine_local_config_context_data_owner_content_type_and_more.py +67 -0
  667. nautobot/virtualization/models.py +0 -2
  668. nautobot/virtualization/tables.py +12 -8
  669. nautobot/virtualization/templates/virtualization/virtualmachine.html +1 -1
  670. nautobot/virtualization/templates/virtualization/vminterface.html +7 -1
  671. nautobot/virtualization/templates/virtualization/vminterface_edit.html +1 -0
  672. nautobot/virtualization/tests/test_api.py +9 -4
  673. nautobot/virtualization/tests/test_filters.py +22 -0
  674. nautobot/virtualization/tests/test_models.py +7 -3
  675. nautobot/virtualization/tests/test_views.py +19 -3
  676. nautobot/virtualization/urls.py +2 -2
  677. nautobot/virtualization/views.py +10 -32
  678. {nautobot-2.2.8.dist-info → nautobot-2.3.0.dist-info}/METADATA +21 -19
  679. {nautobot-2.2.8.dist-info → nautobot-2.3.0.dist-info}/RECORD +684 -564
  680. nautobot/project-static/docs/assets/stylesheets/main.76a95c52.min.css +0 -1
  681. nautobot/project-static/docs/assets/stylesheets/main.76a95c52.min.css.map +0 -1
  682. nautobot/project-static/materialdesignicons-6.5.95/.github/ISSUE_TEMPLATE.md +0 -3
  683. nautobot/project-static/materialdesignicons-6.5.95/README.md +0 -25
  684. nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.css +0 -26654
  685. nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.css.map +0 -16
  686. nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.min.css +0 -3
  687. nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.min.css.map +0 -16
  688. nautobot/project-static/materialdesignicons-6.5.95/fonts/materialdesignicons-webfont.woff +0 -0
  689. nautobot/project-static/materialdesignicons-6.5.95/fonts/materialdesignicons-webfont.woff2 +0 -0
  690. nautobot/project-static/materialdesignicons-6.5.95/package.json +0 -28
  691. nautobot/project-static/materialdesignicons-6.5.95/preview.html +0 -717
  692. nautobot/project-static/materialdesignicons-6.5.95/scss/_animated.scss +0 -27
  693. nautobot/project-static/materialdesignicons-6.5.95/scss/_core.scss +0 -10
  694. nautobot/project-static/materialdesignicons-6.5.95/scss/_extras.scss +0 -65
  695. nautobot/project-static/materialdesignicons-6.5.95/scss/_functions.scss +0 -20
  696. nautobot/project-static/materialdesignicons-6.5.95/scss/_icons.scss +0 -10
  697. nautobot/project-static/materialdesignicons-6.5.95/scss/_path.scss +0 -10
  698. nautobot/project-static/materialdesignicons-6.5.95/scss/_variables.scss +0 -6606
  699. nautobot/project-static/materialdesignicons-6.5.95/scss/materialdesignicons.scss +0 -8
  700. /nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/LICENSE +0 -0
  701. {nautobot-2.2.8.dist-info → nautobot-2.3.0.dist-info}/LICENSE.txt +0 -0
  702. {nautobot-2.2.8.dist-info → nautobot-2.3.0.dist-info}/NOTICE +0 -0
  703. {nautobot-2.2.8.dist-info → nautobot-2.3.0.dist-info}/WHEEL +0 -0
  704. {nautobot-2.2.8.dist-info → nautobot-2.3.0.dist-info}/entry_points.txt +0 -0
@@ -269,7 +269,7 @@ class ViewTestCases:
269
269
  response = self.client.get(url)
270
270
  self.assertHttpStatus(response, 200)
271
271
  response_data = response.content.decode(response.charset)
272
- if type(obj) not in [extras_models.Contact, extras_models.Team]:
272
+ if getattr(obj, "is_contact_associable_model", False):
273
273
  self.assertInHTML(
274
274
  f'<a href="{obj.get_absolute_url()}#contacts" onclick="switch_tab(this.href)" aria-controls="contacts" role="tab" data-toggle="tab">Contacts</a>',
275
275
  response_data,
@@ -288,7 +288,7 @@ class ViewTestCases:
288
288
  response = self.client.get(url)
289
289
  self.assertHttpStatus(response, 200)
290
290
  response_data = response.content.decode(response.charset)
291
- if type(obj) not in [extras_models.Contact, extras_models.Team]:
291
+ if getattr(obj, "is_contact_associable_model", False):
292
292
  self.assertInHTML(
293
293
  f'<a href="{obj.get_absolute_url()}#contacts" onclick="switch_tab(this.href)" aria-controls="contacts" role="tab" data-toggle="tab">Contacts</a>',
294
294
  response_data,
@@ -467,10 +467,12 @@ class ViewTestCases:
467
467
  """
468
468
  Edit a single existing instance.
469
469
 
470
- :form_data: Data to be used when updating the first existing object.
470
+ :update_data: Data to be used when updating the first existing object, fall back to form_data if not provided.
471
+ :form_data: Fall back to this data if update_data is not provided, for backward compatibility.
471
472
  """
472
473
 
473
474
  form_data = {}
475
+ update_data = {}
474
476
 
475
477
  def test_edit_object_without_permission(self):
476
478
  instance = self._get_queryset().first()
@@ -480,9 +482,10 @@ class ViewTestCases:
480
482
  self.assertHttpStatus(self.client.get(self._get_url("edit", instance)), [403, 404])
481
483
 
482
484
  # Try POST without permission
485
+ update_data = self.update_data or self.form_data
483
486
  request = {
484
487
  "path": self._get_url("edit", instance),
485
- "data": utils.post_data(self.form_data),
488
+ "data": utils.post_data(update_data),
486
489
  }
487
490
  with utils.disable_warnings("django.request"):
488
491
  self.assertHttpStatus(self.client.post(**request), [403, 404])
@@ -501,17 +504,17 @@ class ViewTestCases:
501
504
  self.assertHttpStatus(self.client.get(self._get_url("edit", instance)), 200)
502
505
 
503
506
  # Try POST with model-level permission
507
+ update_data = self.update_data or self.form_data
504
508
  request = {
505
509
  "path": self._get_url("edit", instance),
506
- "data": utils.post_data(self.form_data),
510
+ "data": utils.post_data(update_data),
507
511
  }
508
512
  self.assertHttpStatus(self.client.post(**request), 302)
509
- self.assertInstanceEqual(self._get_queryset().get(pk=instance.pk), self.form_data)
513
+ self.assertInstanceEqual(self._get_queryset().get(pk=instance.pk), update_data)
510
514
 
511
515
  if hasattr(self.model, "to_objectchange"):
512
516
  # Verify ObjectChange creation
513
517
  objectchanges = lookup.get_changes_for_model(instance)
514
- self.assertEqual(len(objectchanges), 1)
515
518
  self.assertEqual(objectchanges[0].action, extras_choices.ObjectChangeActionChoices.ACTION_UPDATE)
516
519
  # Validate if detail view exists
517
520
  validate = URLValidator()
@@ -549,17 +552,18 @@ class ViewTestCases:
549
552
  self.assertHttpStatus(self.client.get(self._get_url("edit", instance2)), 404)
550
553
 
551
554
  # Try to edit a permitted object
555
+ update_data = self.update_data or self.form_data
552
556
  request = {
553
557
  "path": self._get_url("edit", instance1),
554
- "data": utils.post_data(self.form_data),
558
+ "data": utils.post_data(update_data),
555
559
  }
556
560
  self.assertHttpStatus(self.client.post(**request), 302)
557
- self.assertInstanceEqual(self._get_queryset().get(pk=instance1.pk), self.form_data)
561
+ self.assertInstanceEqual(self._get_queryset().get(pk=instance1.pk), update_data)
558
562
 
559
563
  # Try to edit a non-permitted object
560
564
  request = {
561
565
  "path": self._get_url("edit", instance2),
562
- "data": utils.post_data(self.form_data),
566
+ "data": utils.post_data(update_data),
563
567
  }
564
568
  self.assertHttpStatus(self.client.post(**request), 404)
565
569
 
@@ -637,7 +641,6 @@ class ViewTestCases:
637
641
  if hasattr(self.model, "to_objectchange"):
638
642
  # Verify ObjectChange creation
639
643
  objectchanges = lookup.get_changes_for_model(instance)
640
- self.assertEqual(len(objectchanges), 1)
641
644
  self.assertEqual(objectchanges[0].action, extras_choices.ObjectChangeActionChoices.ACTION_DELETE)
642
645
 
643
646
  if hasattr(self.model, "notes") and isinstance(instance.notes, extras_querysets.NotesQuerySet):
@@ -678,7 +681,6 @@ class ViewTestCases:
678
681
  if hasattr(self.model, "to_objectchange"):
679
682
  # Verify ObjectChange creation
680
683
  objectchanges = lookup.get_changes_for_model(instance)
681
- self.assertEqual(len(objectchanges), 1)
682
684
  self.assertEqual(objectchanges[0].action, extras_choices.ObjectChangeActionChoices.ACTION_DELETE)
683
685
 
684
686
  @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
@@ -790,6 +792,10 @@ class ViewTestCases:
790
792
  @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
791
793
  def test_list_objects_filtered(self):
792
794
  instance1, instance2 = self._get_queryset().all()[:2]
795
+ if hasattr(self.model, "name") and instance1.name == instance2.name:
796
+ instance2.name += "X"
797
+ instance2.save()
798
+
793
799
  response = self.client.get(f"{self._get_url('list')}?id={instance1.pk}")
794
800
  self.assertHttpStatus(response, 200)
795
801
  content = utils.extract_page_body(response.content.decode(response.charset))
@@ -815,6 +821,10 @@ class ViewTestCases:
815
821
  def test_list_objects_unknown_filter_no_strict_filtering(self):
816
822
  """Verify that without STRICT_FILTERING, an unknown filter is ignored."""
817
823
  instance1, instance2 = self._get_queryset().all()[:2]
824
+ if hasattr(self.model, "name") and instance1.name == instance2.name:
825
+ instance2.name += "X"
826
+ instance2.save()
827
+
818
828
  with self.assertLogs("nautobot.core.filters") as cm:
819
829
  response = self.client.get(f"{self._get_url('list')}?ice_cream_flavor=chocolate")
820
830
  filterset = self.get_filterset()
@@ -881,6 +891,9 @@ class ViewTestCases:
881
891
  @override_settings(EXEMPT_VIEW_PERMISSIONS=[])
882
892
  def test_list_objects_with_constrained_permission(self):
883
893
  instance1, instance2 = self._get_queryset().all()[:2]
894
+ if hasattr(self.model, "name") and instance1.name == instance2.name:
895
+ instance2.name += "X"
896
+ instance2.save()
884
897
 
885
898
  # Add object-level permission
886
899
  obj_perm = users_models.ObjectPermission(
@@ -1409,7 +1422,9 @@ class ViewTestCases:
1409
1422
  # Try POST with model-level permission
1410
1423
  self.assertHttpStatus(self.client.post(self._get_url("bulk_rename"), data), 302)
1411
1424
  for i, instance in enumerate(self._get_queryset().filter(pk__in=pk_list)):
1412
- self.assertEqual(instance.name, f"{objects[i].name}X")
1425
+ name = getattr(instance, "name")
1426
+ expected_name = getattr(objects[i], "name") + "X"
1427
+ self.assertEqual(name, expected_name)
1413
1428
 
1414
1429
  @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
1415
1430
  def test_bulk_rename_objects_with_constrained_permission(self):
@@ -1442,7 +1457,9 @@ class ViewTestCases:
1442
1457
  # Bulk rename permitted objects
1443
1458
  self.assertHttpStatus(self.client.post(self._get_url("bulk_rename"), data), 302)
1444
1459
  for i, instance in enumerate(self._get_queryset().filter(pk__in=pk_list)):
1445
- self.assertEqual(instance.name, f"{objects[i].name}X")
1460
+ name = getattr(instance, "name")
1461
+ expected_name = getattr(objects[i], "name") + "X"
1462
+ self.assertEqual(name, expected_name)
1446
1463
 
1447
1464
  class PrimaryObjectViewTestCase(
1448
1465
  GetObjectViewTestCase,
@@ -24,7 +24,7 @@ class StaticMediaFailureTestCase(SeleniumTestCase):
24
24
  reverse("graphql"),
25
25
  reverse("api_docs"),
26
26
  "/admin/",
27
- "/static/docs/overview/index.html",
27
+ "/static/docs/index.html",
28
28
  ]
29
29
  for url in test_urls:
30
30
  with self.subTest(test_url=url):
@@ -18,6 +18,7 @@ class ImportObjectsUITestCase(SeleniumTestCase):
18
18
  self.browser.visit(self.live_server_url)
19
19
  self.browser.links.find_by_partial_text("Organization").click()
20
20
  self.browser.links.find_by_partial_text("Locations").click()
21
+ self.browser.find_by_id("actions-dropdown").click()
21
22
  self.browser.find_by_id("import-button").click()
22
23
 
23
24
  # Make sure the table of fields for a Location import is populated via a few spot checks
@@ -20,7 +20,7 @@ class SwaggerUITestCase(SeleniumTestCase):
20
20
  """Check that the dcim.location API endpoints are rendered correctly."""
21
21
  self.browser.visit(self.live_server_url + reverse("api_docs"))
22
22
  # Wait for Swagger UI to load, look for the location-list endpoint in the UI and click on it to expand it.
23
- dcim_locations_list = self.browser.find_by_id("operations-dcim-dcim_locations_list", wait_time=20).first
23
+ dcim_locations_list = self.browser.find_by_id("operations-dcim-dcim_locations_list", wait_time=60).first
24
24
  dcim_locations_list.find_by_tag("button").first.click()
25
25
 
26
26
  # Look for the "Try it out" button and click it
@@ -58,5 +58,4 @@ METRICS_ENABLED = True
58
58
 
59
59
  METRICS_AUTHENTICATED = True
60
60
 
61
- DYNAMIC_GROUPS_MEMBER_CACHE_TIMEOUT = 0
62
61
  CONTENT_TYPE_CACHE_TIMEOUT = 0
@@ -13,9 +13,9 @@ from nautobot.core.celery import app, setup_nautobot_job_logging
13
13
  from nautobot.core.settings_funcs import parse_redis_connection
14
14
 
15
15
 
16
- def init_worker_with_unique_cache(counter):
16
+ def init_worker_with_unique_cache(*args, **kwargs):
17
17
  """Extend Django's default parallel unit test setup to also ensure distinct Redis caches."""
18
- _init_worker(counter) # call Django default to set _worker_id and set up parallel DB instances
18
+ _init_worker(*args, **kwargs) # call Django default to set _worker_id and set up parallel DB instances
19
19
  # _worker_id is now 1, 2, 3, 4, etc.
20
20
 
21
21
  from django.test.runner import _worker_id
@@ -992,6 +992,7 @@ class NewUIGetMenuAPIViewTestCase(testing.APITestCase):
992
992
  "Custom Links": "/extras/custom-links/",
993
993
  "Notes": "/extras/notes/",
994
994
  },
995
+ "Users": {"Saved Views": "/extras/saved-views/"},
995
996
  },
996
997
  }
997
998
 
@@ -4,6 +4,7 @@ from django.conf import settings
4
4
  from django.contrib.auth import get_user_model
5
5
  from django.contrib.auth.models import Group
6
6
  from django.contrib.contenttypes.models import ContentType
7
+ from django.db.models import Q
7
8
  from django.test.utils import override_settings
8
9
  from django.urls import reverse
9
10
  from netaddr import IPNetwork
@@ -573,10 +574,14 @@ class ObjectPermissionAPIViewTestCase(TestCase):
573
574
 
574
575
  # Check against 1st user's response
575
576
  self.assertEqual(response_user1.status_code, 200)
576
- self.assertEqual(response_user1.data["count"], 1)
577
+ self.assertEqual(
578
+ response_user1.data["count"], ObjectChange.objects.filter(Q(user=self.user) | Q(action="delete")).count()
579
+ )
577
580
  self.assertEqual(response_user1.data["results"][0]["user"]["id"], self.user.pk)
578
581
 
579
582
  # Check against 2nd user's response
580
583
  self.assertEqual(response_user2.status_code, 200)
581
- self.assertEqual(response_user2.data["count"], 1)
584
+ self.assertEqual(
585
+ response_user2.data["count"], ObjectChange.objects.filter(Q(user=obj_user2) | Q(action="delete")).count()
586
+ )
582
587
  self.assertEqual(response_user2.data["results"][0]["user"]["id"], obj_user2.pk)
@@ -142,6 +142,7 @@ class TreeNodeMultipleChoiceFilterTest(TestCase):
142
142
  self.child_location_2ab,
143
143
  self.child_location_same_name_2,
144
144
  ],
145
+ ordered=False,
145
146
  )
146
147
 
147
148
  def test_filter_null(self):
@@ -212,6 +213,7 @@ class TreeNodeMultipleChoiceFilterTest(TestCase):
212
213
  self.child_location_2ab,
213
214
  self.child_location_same_name_2,
214
215
  ],
216
+ ordered=False,
215
217
  )
216
218
 
217
219
  def test_filter_combined_name_exclude(self):
@@ -1304,14 +1306,14 @@ class SearchFilterTest(TestCase, testing.NautobotTestCaseMixin):
1304
1306
  parent=self.parent_location_1,
1305
1307
  name="Test Child Location 1",
1306
1308
  location_type=self.lt,
1307
- asn=1234,
1309
+ asn=12345,
1308
1310
  status=status,
1309
1311
  )
1310
1312
  self.child_location_2 = dcim_models.Location.objects.create(
1311
1313
  parent=self.parent_location_2,
1312
1314
  name="Test Child Location 2",
1313
1315
  location_type=self.lt,
1314
- asn=12345,
1316
+ asn=123456,
1315
1317
  status=status,
1316
1318
  )
1317
1319
  self.child_location_3 = dcim_models.Location.objects.create(
@@ -1353,19 +1355,19 @@ class SearchFilterTest(TestCase, testing.NautobotTestCaseMixin):
1353
1355
 
1354
1356
  def test_default_exact(self):
1355
1357
  """Test a default search for an "exact" value."""
1356
- params = {"q": "1234"}
1358
+ params = {"q": "12345"}
1357
1359
  self.assertQuerysetEqualAndNotEmpty(
1358
- self.filterset_class(params, self.queryset).qs, self.queryset.filter(asn__exact="1234")
1360
+ self.filterset_class(params, self.queryset).qs, self.queryset.filter(asn__exact=12345)
1359
1361
  )
1360
1362
  asn = (
1361
- dcim_models.Location.objects.exclude(asn="1234")
1363
+ dcim_models.Location.objects.exclude(asn="12345")
1362
1364
  .exclude(asn__isnull=True)
1363
1365
  .values_list("asn", flat=True)
1364
1366
  .first()
1365
1367
  )
1366
1368
  params = {"q": str(asn)}
1367
1369
  self.assertQuerysetEqualAndNotEmpty(
1368
- self.filterset_class(params, self.queryset).qs, self.queryset.filter(asn__exact=str(asn))
1370
+ self.filterset_class(params, self.queryset).qs, self.queryset.filter(asn__exact=asn)
1369
1371
  )
1370
1372
 
1371
1373
  def test_default_id(self):
@@ -1389,9 +1391,9 @@ class SearchFilterTest(TestCase, testing.NautobotTestCaseMixin):
1389
1391
 
1390
1392
  q = filters.SearchFilter(filter_predicates={"asn": {"lookup_expr": "exact", "preprocessor": int}})
1391
1393
 
1392
- params = {"q": "1234"}
1394
+ params = {"q": "12345"}
1393
1395
  self.assertQuerysetEqualAndNotEmpty(
1394
- MyLocationFilterSet(params, self.queryset).qs, self.queryset.filter(asn__exact="1234")
1396
+ MyLocationFilterSet(params, self.queryset).qs, self.queryset.filter(asn__exact="12345")
1395
1397
  )
1396
1398
  params = {"q": "123"}
1397
1399
  # Both querysets are empty so we dont use assertQuerysetEqualAndNotEmpty here.
@@ -1403,7 +1405,7 @@ class SearchFilterTest(TestCase, testing.NautobotTestCaseMixin):
1403
1405
 
1404
1406
  q = filters.SearchFilter(filter_predicates={"asn": {"lookup_expr": "exact", "preprocessor": dict}})
1405
1407
 
1406
- params = {"q": "1234"}
1408
+ params = {"q": "12345"}
1407
1409
  # Both querysets are empty so we dont use assertQuerysetEqualAndNotEmpty here.
1408
1410
  self.assertEqual(self.get_filterset_count(params, MyLocationFilterSet2), 0)
1409
1411
 
@@ -637,11 +637,14 @@ class DynamicFilterFormTest(TestCase):
637
637
  form._get_lookup_field_choices(),
638
638
  [
639
639
  ("color", "Color"),
640
+ ("contacts", "Contacts (name or ID)"),
640
641
  ("content_types", "Content type(s)"),
641
642
  ("created", "Created"),
643
+ ("dynamic_groups", "Dynamic groups (name or ID)"),
642
644
  ("id", "Id"),
643
645
  ("last_updated", "Last updated"),
644
646
  ("name", "Name"),
647
+ ("teams", "Teams (name or ID)"),
645
648
  ],
646
649
  )
647
650
  self.assertEqual(
@@ -655,9 +658,11 @@ class DynamicFilterFormTest(TestCase):
655
658
  ("contact_email", "Contact E-mail"),
656
659
  ("contact_name", "Contact name"),
657
660
  ("contact_phone", "Contact phone"),
661
+ ("contacts", "Contacts (name or ID)"),
658
662
  ("created", "Created"),
659
663
  ("description", "Description"),
660
664
  ("devices", "Devices (name or ID)"),
665
+ ("dynamic_groups", "Dynamic groups (name or ID)"),
661
666
  ("cf_example_app_auto_custom_field", "Example App Automatically Added Custom Field"),
662
667
  ("facility", "Facility"),
663
668
  ("has_vlan_groups", "Has VLAN groups"),
@@ -687,6 +692,7 @@ class DynamicFilterFormTest(TestCase):
687
692
  ("status", "Status (name or ID)"),
688
693
  ("vlans", "Tagged VLANs (VID or ID)"),
689
694
  ("tags", "Tags"),
695
+ ("teams", "Teams (name or ID)"),
690
696
  ("tenant_id", 'Tenant (ID) (deprecated, use "tenant" filter instead)'),
691
697
  ("tenant", "Tenant (name or ID)"),
692
698
  ("tenant_group", "Tenant Group (name or ID)"),
@@ -723,11 +729,14 @@ class DynamicFilterFormTest(TestCase):
723
729
  [
724
730
  (None, "---------"),
725
731
  ("color", "Color"),
732
+ ("contacts", "Contacts (name or ID)"),
726
733
  ("content_types", "Content type(s)"),
727
734
  ("created", "Created"),
735
+ ("dynamic_groups", "Dynamic groups (name or ID)"),
728
736
  ("id", "Id"),
729
737
  ("last_updated", "Last updated"),
730
738
  ("name", "Name"),
739
+ ("teams", "Teams (name or ID)"),
731
740
  ],
732
741
  )
733
742
  self.assertEqual(
@@ -52,6 +52,8 @@ from nautobot.dcim.models import (
52
52
  InterfaceRedundancyGroupAssociation,
53
53
  Location,
54
54
  LocationType,
55
+ Manufacturer,
56
+ Module,
55
57
  PowerFeed,
56
58
  PowerOutlet,
57
59
  PowerPanel,
@@ -93,15 +95,13 @@ User = get_user_model()
93
95
 
94
96
 
95
97
  class GraphQLTestCaseBase(TestCase):
96
- @classmethod
97
- def setUpTestData(cls):
98
- # TODO: the below *shouldn't* be needed, but without it, when run with --parallel test flag,
99
- # these tests consistently fail with schema construction errors
100
- cls.SCHEMA = graphene_settings.SCHEMA # not a no-op; this causes the schema to be built
98
+ def setUp(self):
99
+ self.SCHEMA = graphene_settings.SCHEMA # not a no-op; this causes the schema to be built when first called
101
100
 
102
101
 
103
102
  class GraphQLTestCase(GraphQLTestCaseBase):
104
103
  def setUp(self):
104
+ super().setUp()
105
105
  self.user = create_test_user("graphql_testuser")
106
106
  GraphQLQuery.objects.create(name="GQL 1", query="{ query: locations {name} }")
107
107
  GraphQLQuery.objects.create(name="GQL 2", query="query ($name: [String!]) { locations(name:$name) {name} }")
@@ -178,7 +178,7 @@ class GraphQLTestCase(GraphQLTestCaseBase):
178
178
  for app_label, models in registry["model_features"]["graphql"].items():
179
179
  for model_name in models:
180
180
  model = apps.get_model(app_label=app_label, model_name=model_name)
181
- self.assertIsNotNone(graphene_django_registry.get_type_for_model(model))
181
+ self.assertIsNotNone(graphene_django_registry.get_type_for_model(model), model)
182
182
 
183
183
  @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
184
184
  def test_graphql_url_field(self):
@@ -238,6 +238,7 @@ class GraphQLGenerateSchemaTypeTestCase(GraphQLTestCaseBase):
238
238
 
239
239
  class GraphQLExtendSchemaType(GraphQLTestCaseBase):
240
240
  def setUp(self):
241
+ super().setUp()
241
242
  self.datas = (
242
243
  {"field_name": "my_text", "field_type": CustomFieldTypeChoices.TYPE_TEXT},
243
244
  {
@@ -329,6 +330,7 @@ class GraphQLExtendSchemaType(GraphQLTestCaseBase):
329
330
 
330
331
  class GraphQLExtendSchemaRelationship(GraphQLTestCaseBase):
331
332
  def setUp(self):
333
+ super().setUp()
332
334
  location_ct = ContentType.objects.get_for_model(Location)
333
335
  rack_ct = ContentType.objects.get_for_model(Rack)
334
336
  vlan_ct = ContentType.objects.get_for_model(VLAN)
@@ -455,6 +457,7 @@ class GraphQLExtendSchemaRelationship(GraphQLTestCaseBase):
455
457
 
456
458
  class GraphQLSearchParameters(GraphQLTestCaseBase):
457
459
  def setUp(self):
460
+ super().setUp()
458
461
  self.schema = generate_schema_type(app_name="dcim", model=Location)
459
462
 
460
463
  def test_search_parameters(self):
@@ -476,8 +479,6 @@ class GraphQLAPIPermissionTest(GraphQLTestCaseBase):
476
479
  @classmethod
477
480
  def setUpTestData(cls):
478
481
  """Initialize the Database with some datas and multiple users associated with different permissions."""
479
- super().setUpTestData()
480
-
481
482
  cls.groups = (
482
483
  Group.objects.create(name="Group 1"),
483
484
  Group.objects.create(name="Group 2"),
@@ -705,22 +706,23 @@ class GraphQLQueryTest(GraphQLTestCaseBase):
705
706
  @classmethod
706
707
  def setUpTestData(cls):
707
708
  """Initialize the Database with some datas."""
708
- super().setUpTestData()
709
709
  cls.user = User.objects.create(username="Super User", is_active=True, is_superuser=True)
710
710
 
711
- # Remove random IPAddress and Device fixtures for this custom test
711
+ # Remove random IPAddress, Module and Device fixtures for this custom test
712
712
  IPAddress.objects.all().delete()
713
713
  Controller.objects.filter(controller_device__isnull=False).delete()
714
714
  Device.objects.all().delete()
715
+ Module.objects.all().delete()
715
716
 
716
717
  # Initialize fake request that will be required to execute GraphQL query
717
718
  cls.request = RequestFactory().request(SERVER_NAME="WebRequestContext")
718
719
  cls.request.id = uuid.uuid4()
719
720
  cls.request.user = cls.user
720
721
 
721
- # Populate Data
722
- cls.device_type1 = DeviceType.objects.first()
723
- cls.device_type2 = DeviceType.objects.last()
722
+ # Populate Data - create new device types with no component templates
723
+ manufacturer = Manufacturer.objects.first()
724
+ cls.device_type1 = DeviceType.objects.create(manufacturer=manufacturer, model="test device_type1")
725
+ cls.device_type2 = DeviceType.objects.create(manufacturer=manufacturer, model="test device_type2")
724
726
  roles = Role.objects.get_for_model(Device)
725
727
  cls.device_role1 = roles[0]
726
728
  cls.device_role2 = roles[1]
@@ -863,6 +865,7 @@ class GraphQLQueryTest(GraphQLTestCaseBase):
863
865
  ]
864
866
 
865
867
  interface_status = Status.objects.get_for_model(Interface).first()
868
+ interface_role = Role.objects.get_for_model(Interface).first()
866
869
  cls.interface11 = Interface.objects.create(
867
870
  name="Int1",
868
871
  type=InterfaceTypeChoices.TYPE_VIRTUAL,
@@ -871,12 +874,14 @@ class GraphQLQueryTest(GraphQLTestCaseBase):
871
874
  mode=InterfaceModeChoices.MODE_ACCESS,
872
875
  untagged_vlan=cls.vlan1,
873
876
  status=interface_status,
877
+ role=interface_role,
874
878
  )
875
879
  cls.interface12 = Interface.objects.create(
876
880
  name="Int2",
877
881
  type=InterfaceTypeChoices.TYPE_VIRTUAL,
878
882
  device=cls.device1,
879
883
  status=interface_status,
884
+ role=interface_role,
880
885
  )
881
886
  cls.namespace = Namespace.objects.first()
882
887
  cls.intr_group_status = Status.objects.get_for_model(InterfaceRedundancyGroup).first()
@@ -958,6 +963,7 @@ class GraphQLQueryTest(GraphQLTestCaseBase):
958
963
  untagged_vlan=cls.vlan2,
959
964
  mode=InterfaceModeChoices.MODE_ACCESS,
960
965
  status=interface_status,
966
+ role=interface_role,
961
967
  )
962
968
  cls.interface22 = Interface.objects.create(
963
969
  name="Int2",
@@ -984,7 +990,11 @@ class GraphQLQueryTest(GraphQLTestCaseBase):
984
990
  )
985
991
 
986
992
  cls.interface31 = Interface.objects.create(
987
- name="Int1", type=InterfaceTypeChoices.TYPE_VIRTUAL, device=cls.device3, status=interface_status
993
+ name="Int1",
994
+ type=InterfaceTypeChoices.TYPE_VIRTUAL,
995
+ device=cls.device3,
996
+ status=interface_status,
997
+ role=interface_role,
988
998
  )
989
999
  cls.interface31 = Interface.objects.create(
990
1000
  name="Mgmt1",
@@ -993,6 +1003,7 @@ class GraphQLQueryTest(GraphQLTestCaseBase):
993
1003
  mgmt_only=True,
994
1004
  enabled=False,
995
1005
  status=interface_status,
1006
+ role=interface_role,
996
1007
  )
997
1008
 
998
1009
  cable_statuses = Status.objects.get_for_model(Cable)
@@ -2197,7 +2208,7 @@ query {
2197
2208
  self.assertIsNone(result.errors)
2198
2209
  self.assertIsInstance(result.data, dict, result)
2199
2210
  self.assertIsInstance(result.data["device_types"], list, result)
2200
- self.assertEqual(result.data["device_types"][0]["model"], self.device_type1.model, result)
2211
+ self.assertEqual(result.data["device_types"][0]["model"], DeviceType.objects.first().model, result)
2201
2212
 
2202
2213
  @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
2203
2214
  def test_query_interface_pagination(self):
@@ -2233,7 +2244,7 @@ query {
2233
2244
  self.assertEqual(interface_names, ["Int2", "Int1"])
2234
2245
 
2235
2246
  result_2 = self.execute_query(query_all)
2236
- self.assertEqual(len(result_2.data.get("interfaces", [])), 6)
2247
+ self.assertEqual(len(result_2.data.get("interfaces", [])), Interface.objects.count())
2237
2248
 
2238
2249
  @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
2239
2250
  def test_query_power_feeds_cable_peer(self):