nautobot 2.2.9__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 (697) 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 +95 -13
  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/schema.py +26 -4
  61. nautobot/core/jobs/__init__.py +16 -2
  62. nautobot/core/jobs/cleanup.py +100 -0
  63. nautobot/core/jobs/groups.py +38 -0
  64. nautobot/core/management/commands/generate_test_data.py +116 -3
  65. nautobot/core/models/__init__.py +34 -9
  66. nautobot/core/models/generics.py +19 -3
  67. nautobot/core/models/name_color_content_types.py +7 -28
  68. nautobot/core/models/querysets.py +4 -3
  69. nautobot/core/models/tree_queries.py +1 -1
  70. nautobot/core/models/utils.py +21 -5
  71. nautobot/core/settings.py +2 -17
  72. nautobot/core/settings.yaml +34 -13
  73. nautobot/core/settings_funcs.py +103 -0
  74. nautobot/core/tables.py +130 -56
  75. nautobot/core/templates/admin/search_form.html +1 -1
  76. nautobot/core/templates/buttons/add.html +11 -3
  77. nautobot/core/templates/buttons/consolidated_bulk_action_buttons.html +13 -0
  78. nautobot/core/templates/buttons/consolidated_detail_view_action_buttons.html +13 -0
  79. nautobot/core/templates/buttons/export.html +101 -53
  80. nautobot/core/templates/buttons/job_import.html +11 -3
  81. nautobot/core/templates/generic/object_bulk_destroy.html +3 -1
  82. nautobot/core/templates/generic/object_bulk_update.html +3 -1
  83. nautobot/core/templates/generic/object_changelog.html +0 -9
  84. nautobot/core/templates/generic/object_list.html +156 -17
  85. nautobot/core/templates/generic/object_retrieve.html +80 -16
  86. nautobot/core/templates/inc/extras_features_edit_form_fields.html +8 -0
  87. nautobot/core/templates/inc/javascript.html +2 -0
  88. nautobot/core/templates/inc/media.html +2 -2
  89. nautobot/core/templates/inc/nav_menu.html +1 -0
  90. nautobot/core/templates/inc/paginator.html +7 -7
  91. nautobot/core/templates/inc/search_panel.html +2 -2
  92. nautobot/core/templates/inc/table.html +2 -2
  93. nautobot/core/templates/nautobot_config.py.j2 +13 -8
  94. nautobot/core/templates/utilities/templatetags/dynamic_group_assignment_modal.html +37 -0
  95. nautobot/core/templates/utilities/templatetags/filter_form_modal.html +2 -2
  96. nautobot/core/templates/utilities/templatetags/saved_view_modal.html +38 -0
  97. nautobot/core/templates/utilities/theme_preview.html +25 -8
  98. nautobot/core/templates/utilities/worker_status.html +152 -0
  99. nautobot/core/templatetags/buttons.py +335 -38
  100. nautobot/core/templatetags/form_helpers.py +1 -1
  101. nautobot/core/templatetags/helpers.py +181 -11
  102. nautobot/core/testing/api.py +5 -4
  103. nautobot/core/testing/filters.py +63 -14
  104. nautobot/core/testing/mixins.py +46 -0
  105. nautobot/core/testing/models.py +22 -0
  106. nautobot/core/testing/schema.py +4 -8
  107. nautobot/core/testing/views.py +31 -14
  108. nautobot/core/tests/integration/test_import_objects_ui.py +1 -0
  109. nautobot/core/tests/integration/test_swagger.py +1 -1
  110. nautobot/core/tests/nautobot_config.py +0 -1
  111. nautobot/core/tests/runner.py +2 -2
  112. nautobot/core/tests/test_api.py +1 -0
  113. nautobot/core/tests/test_authentication.py +7 -2
  114. nautobot/core/tests/test_filters.py +11 -9
  115. nautobot/core/tests/test_forms.py +9 -0
  116. nautobot/core/tests/test_graphql.py +27 -16
  117. nautobot/core/tests/test_jobs.py +122 -0
  118. nautobot/core/tests/test_tables.py +3 -1
  119. nautobot/core/tests/test_templatetags_helpers.py +12 -5
  120. nautobot/core/tests/test_utils.py +31 -20
  121. nautobot/core/tests/test_views.py +6 -6
  122. nautobot/core/urls.py +8 -3
  123. nautobot/core/utils/deprecation.py +29 -0
  124. nautobot/core/utils/filtering.py +12 -9
  125. nautobot/core/utils/lookup.py +37 -2
  126. nautobot/core/utils/requests.py +4 -1
  127. nautobot/core/views/__init__.py +137 -24
  128. nautobot/core/views/generic.py +119 -67
  129. nautobot/core/views/mixins.py +105 -36
  130. nautobot/core/views/paginator.py +9 -3
  131. nautobot/core/views/renderers.py +121 -56
  132. nautobot/core/views/utils.py +81 -1
  133. nautobot/dcim/__init__.py +0 -1
  134. nautobot/dcim/api/serializers.py +180 -44
  135. nautobot/dcim/api/urls.py +7 -3
  136. nautobot/dcim/api/views.py +53 -7
  137. nautobot/dcim/apps.py +3 -0
  138. nautobot/dcim/choices.py +25 -0
  139. nautobot/dcim/constants.py +7 -0
  140. nautobot/dcim/factory.py +252 -18
  141. nautobot/dcim/filters/__init__.py +373 -193
  142. nautobot/dcim/filters/mixins.py +274 -1
  143. nautobot/dcim/forms.py +834 -121
  144. nautobot/dcim/graphql/types.py +2 -2
  145. nautobot/dcim/homepage.py +1 -1
  146. nautobot/dcim/migrations/0059_add_role_field_to_interface_models.py +27 -0
  147. nautobot/dcim/migrations/0060_alter_cable_status_alter_consoleport__path_and_more.py +303 -0
  148. nautobot/dcim/migrations/0061_module_models.py +862 -0
  149. nautobot/dcim/migrations/0062_module_data_migration.py +25 -0
  150. nautobot/dcim/models/__init__.py +8 -0
  151. nautobot/dcim/models/cables.py +15 -0
  152. nautobot/dcim/models/device_component_templates.py +207 -53
  153. nautobot/dcim/models/device_components.py +275 -99
  154. nautobot/dcim/models/devices.py +468 -13
  155. nautobot/dcim/models/racks.py +0 -1
  156. nautobot/dcim/navigation.py +47 -0
  157. nautobot/dcim/signals.py +3 -3
  158. nautobot/dcim/tables/__init__.py +35 -23
  159. nautobot/dcim/tables/devices.py +229 -43
  160. nautobot/dcim/tables/devicetypes.py +65 -9
  161. nautobot/dcim/tables/racks.py +5 -1
  162. nautobot/dcim/tables/template_code.py +46 -26
  163. nautobot/dcim/templates/dcim/cable_connect.html +76 -3
  164. nautobot/dcim/templates/dcim/console_port_connection_list.html +7 -5
  165. nautobot/dcim/templates/dcim/device/base.html +14 -6
  166. nautobot/dcim/templates/dcim/device/consoleports.html +2 -3
  167. nautobot/dcim/templates/dcim/device/consoleserverports.html +2 -3
  168. nautobot/dcim/templates/dcim/device/devicebays.html +6 -7
  169. nautobot/dcim/templates/dcim/device/frontports.html +2 -3
  170. nautobot/dcim/templates/dcim/device/interfaces.html +2 -3
  171. nautobot/dcim/templates/dcim/device/inventory.html +2 -3
  172. nautobot/dcim/templates/dcim/device/modulebays.html +49 -0
  173. nautobot/dcim/templates/dcim/device/poweroutlets.html +2 -3
  174. nautobot/dcim/templates/dcim/device/powerports.html +2 -3
  175. nautobot/dcim/templates/dcim/device/rearports.html +2 -3
  176. nautobot/dcim/templates/dcim/device.html +45 -1
  177. nautobot/dcim/templates/dcim/device_component.html +13 -5
  178. nautobot/dcim/templates/dcim/device_list.html +2 -1
  179. nautobot/dcim/templates/dcim/devicetype.html +99 -98
  180. nautobot/dcim/templates/dcim/devicetype_list.html +8 -16
  181. nautobot/dcim/templates/dcim/inc/devicetype_component_table.html +1 -1
  182. nautobot/dcim/templates/dcim/inc/moduletype_component_table.html +39 -0
  183. nautobot/dcim/templates/dcim/interface.html +17 -2
  184. nautobot/dcim/templates/dcim/interface_connection_list.html +7 -5
  185. nautobot/dcim/templates/dcim/interface_edit.html +1 -0
  186. nautobot/dcim/templates/dcim/manufacturer.html +24 -0
  187. nautobot/dcim/templates/dcim/module/base.html +97 -0
  188. nautobot/dcim/templates/dcim/module_bulk_destroy.html +5 -0
  189. nautobot/dcim/templates/dcim/module_consoleports.html +53 -0
  190. nautobot/dcim/templates/dcim/module_consoleserverports.html +53 -0
  191. nautobot/dcim/templates/dcim/module_destroy.html +5 -0
  192. nautobot/dcim/templates/dcim/module_frontports.html +53 -0
  193. nautobot/dcim/templates/dcim/module_interfaces.html +57 -0
  194. nautobot/dcim/templates/dcim/module_list.html +20 -0
  195. nautobot/dcim/templates/dcim/module_modulebays.html +49 -0
  196. nautobot/dcim/templates/dcim/module_poweroutlets.html +53 -0
  197. nautobot/dcim/templates/dcim/module_powerports.html +53 -0
  198. nautobot/dcim/templates/dcim/module_rearports.html +53 -0
  199. nautobot/dcim/templates/dcim/module_retrieve.html +63 -0
  200. nautobot/dcim/templates/dcim/module_update.html +71 -0
  201. nautobot/dcim/templates/dcim/modulebay_bulk_destroy.html +5 -0
  202. nautobot/dcim/templates/dcim/modulebay_destroy.html +8 -0
  203. nautobot/dcim/templates/dcim/modulebay_retrieve.html +101 -0
  204. nautobot/dcim/templates/dcim/moduletype_list.html +11 -0
  205. nautobot/dcim/templates/dcim/moduletype_retrieve.html +159 -0
  206. nautobot/dcim/templates/dcim/power_port_connection_list.html +7 -5
  207. nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +65 -19
  208. nautobot/dcim/tests/integration/test_cable_connect_form.py +4 -4
  209. nautobot/dcim/tests/test_api.py +693 -208
  210. nautobot/dcim/tests/test_filters.py +843 -217
  211. nautobot/dcim/tests/test_models.py +1072 -8
  212. nautobot/dcim/tests/test_views.py +1510 -341
  213. nautobot/dcim/urls.py +17 -2
  214. nautobot/dcim/utils.py +2 -3
  215. nautobot/dcim/views.py +1106 -116
  216. nautobot/extras/__init__.py +0 -1
  217. nautobot/extras/api/serializers.py +115 -3
  218. nautobot/extras/api/urls.py +12 -0
  219. nautobot/extras/api/views.py +66 -0
  220. nautobot/extras/apps.py +2 -2
  221. nautobot/extras/choices.py +43 -0
  222. nautobot/extras/context_managers.py +13 -8
  223. nautobot/extras/datasources/git.py +2 -0
  224. nautobot/extras/factory.py +460 -9
  225. nautobot/extras/filters/__init__.py +174 -3
  226. nautobot/extras/filters/mixins.py +46 -43
  227. nautobot/extras/forms/base.py +24 -5
  228. nautobot/extras/forms/forms.py +227 -8
  229. nautobot/extras/forms/mixins.py +93 -0
  230. nautobot/extras/graphql/types.py +23 -10
  231. nautobot/extras/homepage.py +14 -1
  232. nautobot/extras/management/__init__.py +1 -0
  233. nautobot/extras/management/commands/refresh_dynamic_group_member_caches.py +1 -16
  234. nautobot/extras/migrations/0021_customfield_changelog_data.py +1 -0
  235. nautobot/extras/migrations/0109_dynamicgroup_group_type_dynamicgroup_tags_and_more.py +108 -0
  236. nautobot/extras/migrations/0110_alter_configcontext_cluster_groups_and_more.py +111 -0
  237. nautobot/extras/migrations/0111_metadata.py +162 -0
  238. nautobot/extras/migrations/0112_dynamic_group_group_type_data_migration.py +28 -0
  239. nautobot/extras/migrations/0113_saved_views.py +77 -0
  240. nautobot/extras/models/__init__.py +15 -1
  241. nautobot/extras/models/change_logging.py +3 -3
  242. nautobot/extras/models/contacts.py +4 -0
  243. nautobot/extras/models/customfields.py +18 -3
  244. nautobot/extras/models/groups.py +389 -225
  245. nautobot/extras/models/jobs.py +6 -3
  246. nautobot/extras/models/metadata.py +441 -0
  247. nautobot/extras/models/mixins.py +72 -62
  248. nautobot/extras/models/models.py +118 -9
  249. nautobot/extras/models/relationships.py +9 -2
  250. nautobot/extras/models/tags.py +13 -2
  251. nautobot/extras/navigation.py +57 -0
  252. nautobot/extras/plugins/__init__.py +3 -1
  253. nautobot/extras/querysets.py +30 -66
  254. nautobot/extras/signals.py +95 -100
  255. nautobot/extras/tables.py +165 -12
  256. nautobot/extras/templates/extras/dynamicgroup.html +44 -15
  257. nautobot/extras/templates/extras/dynamicgroup_edit.html +2 -0
  258. nautobot/extras/templates/extras/job.html +1 -1
  259. nautobot/extras/templates/extras/jobresult.html +61 -74
  260. nautobot/extras/templates/extras/metadatatype_create.html +89 -0
  261. nautobot/extras/templates/extras/metadatatype_retrieve.html +67 -0
  262. nautobot/extras/templates/extras/object_dynamicgroups.html +7 -0
  263. nautobot/extras/templates/extras/objectchange_list.html +0 -12
  264. nautobot/extras/templates/extras/plugins_list.html +1 -3
  265. nautobot/extras/templates/extras/role_retrieve.html +48 -0
  266. nautobot/extras/templates/extras/staticgroupassociation_retrieve.html +20 -0
  267. nautobot/extras/tests/integration/test_customfields.py +1 -0
  268. nautobot/extras/tests/test_api.py +509 -23
  269. nautobot/extras/tests/test_changelog.py +20 -9
  270. nautobot/extras/tests/test_context_managers.py +22 -15
  271. nautobot/extras/tests/test_datasources.py +13 -1
  272. nautobot/extras/tests/test_dynamicgroups.py +201 -171
  273. nautobot/extras/tests/test_filters.py +211 -12
  274. nautobot/extras/tests/test_jobs.py +6 -6
  275. nautobot/extras/tests/test_models.py +501 -4
  276. nautobot/extras/tests/test_relationships.py +1 -0
  277. nautobot/extras/tests/test_views.py +565 -8
  278. nautobot/extras/tests/test_webhooks.py +1 -1
  279. nautobot/extras/urls.py +5 -0
  280. nautobot/extras/utils.py +51 -11
  281. nautobot/extras/views.py +542 -76
  282. nautobot/ipam/__init__.py +0 -1
  283. nautobot/ipam/apps.py +1 -0
  284. nautobot/ipam/factory.py +17 -19
  285. nautobot/ipam/filters.py +13 -0
  286. nautobot/ipam/forms.py +8 -4
  287. nautobot/ipam/graphql/types.py +2 -2
  288. nautobot/ipam/migrations/0047_alter_ipaddress_role_alter_ipaddress_status_and_more.py +59 -0
  289. nautobot/ipam/models.py +11 -8
  290. nautobot/ipam/querysets.py +1 -1
  291. nautobot/ipam/signals.py +4 -2
  292. nautobot/ipam/tables.py +5 -0
  293. nautobot/ipam/templates/ipam/ipaddress_interfaces.html +1 -1
  294. nautobot/ipam/templates/ipam/ipaddress_vm_interfaces.html +1 -1
  295. nautobot/ipam/templates/ipam/prefix.html +1 -0
  296. nautobot/ipam/tests/test_api.py +37 -18
  297. nautobot/ipam/tests/test_filters.py +26 -2
  298. nautobot/ipam/tests/test_models.py +6 -0
  299. nautobot/ipam/tests/test_querysets.py +1 -1
  300. nautobot/ipam/tests/test_views.py +3 -2
  301. nautobot/ipam/urls.py +2 -2
  302. nautobot/ipam/views.py +18 -26
  303. nautobot/project-static/css/base.css +20 -0
  304. nautobot/project-static/css/dark.css +11 -0
  305. nautobot/project-static/docs/404.html +892 -88
  306. nautobot/project-static/docs/apps/index.html +892 -88
  307. nautobot/project-static/docs/apps/nautobot-apps.html +892 -88
  308. nautobot/project-static/docs/assets/_mkdocstrings.css +5 -0
  309. nautobot/project-static/docs/assets/stylesheets/main.3cba04c6.min.css +1 -0
  310. nautobot/project-static/docs/assets/stylesheets/main.3cba04c6.min.css.map +1 -0
  311. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +919 -120
  312. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +904 -101
  313. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +1618 -903
  314. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +935 -144
  315. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +977 -188
  316. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +901 -99
  317. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +897 -93
  318. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +991 -193
  319. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +974 -131
  320. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +1078 -272
  321. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +1242 -334
  322. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +1727 -875
  323. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +1164 -381
  324. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +2088 -1374
  325. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +2246 -1422
  326. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +912 -111
  327. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +963 -163
  328. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +1010 -223
  329. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +1913 -1277
  330. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +1846 -1102
  331. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +904 -101
  332. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +2331 -1699
  333. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +1802 -1024
  334. nautobot/project-static/docs/development/apps/api/configuration-view.html +892 -88
  335. nautobot/project-static/docs/development/apps/api/database-backend-config.html +892 -88
  336. nautobot/project-static/docs/development/apps/api/models/django-admin.html +892 -88
  337. nautobot/project-static/docs/development/apps/api/models/global-search.html +892 -88
  338. nautobot/project-static/docs/development/apps/api/models/graphql.html +892 -88
  339. nautobot/project-static/docs/development/apps/api/models/index.html +942 -90
  340. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +892 -88
  341. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +892 -88
  342. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +892 -88
  343. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +892 -88
  344. nautobot/project-static/docs/development/apps/api/platform-features/index.html +892 -88
  345. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +892 -88
  346. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +892 -88
  347. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +892 -88
  348. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +892 -88
  349. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +892 -88
  350. nautobot/project-static/docs/development/apps/api/prometheus.html +892 -88
  351. nautobot/project-static/docs/development/apps/api/setup.html +892 -88
  352. nautobot/project-static/docs/development/apps/api/testing.html +892 -88
  353. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +892 -88
  354. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +892 -88
  355. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +892 -88
  356. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +892 -88
  357. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +892 -88
  358. nautobot/project-static/docs/development/apps/api/views/base-template.html +892 -88
  359. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +892 -88
  360. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +892 -88
  361. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +892 -88
  362. nautobot/project-static/docs/development/apps/api/views/index.html +892 -88
  363. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +892 -88
  364. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +892 -88
  365. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +892 -88
  366. nautobot/project-static/docs/development/apps/api/views/notes.html +892 -88
  367. nautobot/project-static/docs/development/apps/api/views/rest-api.html +892 -88
  368. nautobot/project-static/docs/development/apps/api/views/urls.html +892 -88
  369. nautobot/project-static/docs/development/apps/index.html +892 -88
  370. nautobot/project-static/docs/development/apps/migration/code-updates.html +892 -88
  371. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +892 -88
  372. nautobot/project-static/docs/development/apps/migration/from-v1.html +892 -88
  373. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +892 -88
  374. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +892 -88
  375. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +892 -88
  376. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +892 -88
  377. nautobot/project-static/docs/development/apps/porting-from-netbox.html +892 -88
  378. nautobot/project-static/docs/development/core/application-registry.html +892 -88
  379. nautobot/project-static/docs/development/core/best-practices.html +893 -88
  380. nautobot/project-static/docs/development/core/bootstrap-ui.html +892 -88
  381. nautobot/project-static/docs/development/core/caching.html +892 -88
  382. nautobot/project-static/docs/development/core/controllers.html +892 -88
  383. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +892 -88
  384. nautobot/project-static/docs/development/core/generic-views.html +892 -88
  385. nautobot/project-static/docs/development/core/getting-started.html +892 -88
  386. nautobot/project-static/docs/development/core/homepage.html +892 -88
  387. nautobot/project-static/docs/development/core/index.html +892 -88
  388. nautobot/project-static/docs/development/core/model-checklist.html +901 -89
  389. nautobot/project-static/docs/development/core/model-features.html +892 -88
  390. nautobot/project-static/docs/development/core/natural-keys.html +892 -88
  391. nautobot/project-static/docs/development/core/navigation-menu.html +892 -88
  392. nautobot/project-static/docs/development/core/release-checklist.html +895 -91
  393. nautobot/project-static/docs/development/core/role-internals.html +892 -88
  394. nautobot/project-static/docs/development/core/settings.html +892 -88
  395. nautobot/project-static/docs/development/core/style-guide.html +893 -89
  396. nautobot/project-static/docs/development/core/templates.html +904 -89
  397. nautobot/project-static/docs/development/core/testing.html +892 -88
  398. nautobot/project-static/docs/development/core/user-preferences.html +892 -88
  399. nautobot/project-static/docs/development/index.html +892 -88
  400. nautobot/project-static/docs/development/jobs/index.html +893 -89
  401. nautobot/project-static/docs/development/jobs/migration/from-v1.html +892 -88
  402. nautobot/project-static/docs/index.html +892 -88
  403. nautobot/project-static/docs/media/models/cloud_aws_direct_connect_dark.png +0 -0
  404. nautobot/project-static/docs/media/models/cloud_aws_direct_connect_light.png +0 -0
  405. nautobot/project-static/docs/models/cloud/cloudaccount.html +15 -0
  406. nautobot/project-static/docs/models/cloud/cloudnetwork.html +15 -0
  407. nautobot/project-static/docs/models/cloud/cloudnetworkprefixassignment.html +15 -0
  408. nautobot/project-static/docs/models/cloud/cloudresourcetype.html +15 -0
  409. nautobot/project-static/docs/models/cloud/cloudservice.html +15 -0
  410. nautobot/project-static/docs/models/cloud/cloudservicenetworkassignment.html +15 -0
  411. nautobot/project-static/docs/models/dcim/module.html +15 -0
  412. nautobot/project-static/docs/models/dcim/modulebay.html +15 -0
  413. nautobot/project-static/docs/models/dcim/modulebaytemplate.html +15 -0
  414. nautobot/project-static/docs/models/dcim/moduletype.html +15 -0
  415. nautobot/project-static/docs/models/extras/metadatachoice.html +15 -0
  416. nautobot/project-static/docs/models/extras/metadatatype.html +15 -0
  417. nautobot/project-static/docs/models/extras/objectmetadata.html +15 -0
  418. nautobot/project-static/docs/models/extras/role.html +15 -0
  419. nautobot/project-static/docs/models/extras/savedview.html +15 -0
  420. nautobot/project-static/docs/models/extras/staticgroupassociation.html +15 -0
  421. nautobot/project-static/docs/models/extras/status.html +15 -0
  422. nautobot/project-static/docs/objects.inv +0 -0
  423. nautobot/project-static/docs/overview/application_stack.html +900 -89
  424. nautobot/project-static/docs/overview/design_philosophy.html +892 -88
  425. nautobot/project-static/docs/release-notes/index.html +1129 -92
  426. nautobot/project-static/docs/release-notes/version-1.0.html +892 -88
  427. nautobot/project-static/docs/release-notes/version-1.1.html +892 -88
  428. nautobot/project-static/docs/release-notes/version-1.2.html +892 -88
  429. nautobot/project-static/docs/release-notes/version-1.3.html +892 -88
  430. nautobot/project-static/docs/release-notes/version-1.4.html +892 -88
  431. nautobot/project-static/docs/release-notes/version-1.5.html +893 -89
  432. nautobot/project-static/docs/release-notes/version-1.6.html +893 -89
  433. nautobot/project-static/docs/release-notes/version-2.0.html +892 -88
  434. nautobot/project-static/docs/release-notes/version-2.1.html +892 -88
  435. nautobot/project-static/docs/release-notes/version-2.2.html +895 -91
  436. nautobot/project-static/docs/release-notes/version-2.3.html +9954 -0
  437. nautobot/project-static/docs/requirements.txt +5 -5
  438. nautobot/project-static/docs/search/search_index.json +1 -1
  439. nautobot/project-static/docs/sitemap.xml +331 -256
  440. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  441. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +892 -88
  442. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +892 -88
  443. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +892 -88
  444. nautobot/project-static/docs/user-guide/administration/configuration/index.html +892 -88
  445. nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +992 -174
  446. nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +892 -88
  447. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +892 -88
  448. nautobot/project-static/docs/user-guide/administration/guides/caching.html +892 -88
  449. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +896 -88
  450. nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +892 -88
  451. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +892 -88
  452. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +892 -88
  453. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +892 -88
  454. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +892 -88
  455. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +892 -88
  456. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +892 -88
  457. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +892 -88
  458. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +944 -153
  459. nautobot/project-static/docs/user-guide/administration/installation/index.html +901 -93
  460. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +934 -122
  461. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +954 -157
  462. nautobot/project-static/docs/user-guide/administration/installation/services.html +913 -112
  463. nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +908 -99
  464. nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +892 -88
  465. nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +892 -88
  466. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +892 -88
  467. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +892 -88
  468. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +893 -89
  469. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +892 -88
  470. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +892 -88
  471. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +892 -88
  472. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +892 -88
  473. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +892 -88
  474. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +892 -88
  475. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +892 -88
  476. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +892 -88
  477. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +892 -88
  478. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +892 -88
  479. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +892 -88
  480. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +893 -89
  481. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +892 -88
  482. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +896 -88
  483. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +895 -91
  484. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +8984 -0
  485. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +8828 -0
  486. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +8829 -0
  487. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +8828 -0
  488. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +8829 -0
  489. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +8833 -0
  490. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +8828 -0
  491. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +906 -102
  492. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +923 -105
  493. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +923 -105
  494. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +918 -100
  495. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +923 -105
  496. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +906 -102
  497. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +906 -102
  498. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +913 -105
  499. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +920 -116
  500. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +921 -117
  501. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +918 -114
  502. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +906 -102
  503. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +914 -105
  504. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +926 -108
  505. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +936 -118
  506. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +928 -106
  507. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +906 -102
  508. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +937 -119
  509. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +928 -110
  510. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +918 -114
  511. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +921 -117
  512. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +923 -115
  513. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +8828 -0
  514. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +8846 -0
  515. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +8843 -0
  516. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +8823 -0
  517. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +916 -112
  518. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +906 -102
  519. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +940 -83
  520. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +924 -106
  521. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +906 -102
  522. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +943 -86
  523. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +921 -103
  524. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +929 -125
  525. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +918 -114
  526. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +906 -102
  527. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +922 -104
  528. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +924 -106
  529. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +906 -102
  530. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +906 -102
  531. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +906 -102
  532. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +936 -88
  533. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +892 -88
  534. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +897 -89
  535. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +897 -89
  536. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +892 -88
  537. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +892 -88
  538. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +892 -88
  539. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +892 -88
  540. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +892 -88
  541. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +892 -88
  542. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +892 -88
  543. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +892 -88
  544. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +892 -88
  545. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +892 -88
  546. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +901 -96
  547. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +892 -88
  548. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +892 -88
  549. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +892 -88
  550. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +892 -88
  551. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +892 -88
  552. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +897 -89
  553. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +892 -88
  554. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +892 -88
  555. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +892 -88
  556. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +892 -88
  557. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +892 -88
  558. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +892 -88
  559. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +892 -88
  560. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +892 -88
  561. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +892 -88
  562. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +892 -88
  563. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +892 -88
  564. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +892 -88
  565. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +892 -88
  566. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/clear-view-button.png +0 -0
  567. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/cleared-view.png +0 -0
  568. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/config-table-columns-to-locations.png +0 -0
  569. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/configure-button.png +0 -0
  570. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/create-saved-view-success.png +0 -0
  571. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/current-saved-view-drop-down-menu.png +0 -0
  572. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/default-location-list-view.png +0 -0
  573. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/dropdown-button-after-new-saved-view.png +0 -0
  574. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/filter-application-to-locations.png +0 -0
  575. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/filter-button.png +0 -0
  576. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/global-default-location-list-view.png +0 -0
  577. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/location-list-view-with-saved-views.png +0 -0
  578. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/navigation-menu.png +0 -0
  579. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/save-as-new-view-drop-down.png +0 -0
  580. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/save-view-modal.png +0 -0
  581. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-buttons.png +0 -0
  582. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-success.png +0 -0
  583. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-view-unchecked.png +0 -0
  584. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-view.png +0 -0
  585. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-different-user.png +0 -0
  586. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-modal-unchecked.png +0 -0
  587. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/set-as-my-default-button.png +0 -0
  588. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/set-as-my-default-success.png +0 -0
  589. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/unsaved-saved-view.png +0 -0
  590. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/updated-saved-view.png +0 -0
  591. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +892 -88
  592. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +892 -88
  593. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +892 -88
  594. nautobot/project-static/docs/user-guide/index.html +892 -88
  595. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +892 -88
  596. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +892 -88
  597. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +892 -88
  598. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +892 -88
  599. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +1258 -785
  600. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +895 -91
  601. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +892 -88
  602. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +892 -88
  603. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +892 -88
  604. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +892 -88
  605. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +892 -88
  606. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +892 -88
  607. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +892 -88
  608. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +892 -88
  609. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +892 -88
  610. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +896 -88
  611. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +892 -88
  612. nautobot/project-static/docs/user-guide/platform-functionality/note.html +895 -91
  613. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +9061 -0
  614. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +895 -91
  615. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +892 -88
  616. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +892 -88
  617. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +892 -88
  618. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +892 -88
  619. nautobot/project-static/docs/user-guide/platform-functionality/role.html +895 -91
  620. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +9137 -0
  621. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +895 -91
  622. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +8933 -0
  623. nautobot/project-static/docs/user-guide/platform-functionality/status.html +892 -88
  624. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +892 -88
  625. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +950 -121
  626. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +892 -88
  627. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +892 -88
  628. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +892 -88
  629. nautobot/project-static/js/forms.js +71 -0
  630. nautobot/project-static/js/table_sorting_indicator.js +46 -0
  631. nautobot/project-static/js/tableconfig.js +6 -1
  632. nautobot/project-static/materialdesignicons-7.4.47/css/materialdesignicons.min.css +3 -0
  633. nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/fonts/materialdesignicons-webfont.eot +0 -0
  634. nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/fonts/materialdesignicons-webfont.ttf +0 -0
  635. nautobot/project-static/materialdesignicons-7.4.47/fonts/materialdesignicons-webfont.woff +0 -0
  636. nautobot/project-static/materialdesignicons-7.4.47/fonts/materialdesignicons-webfont.woff2 +0 -0
  637. nautobot/tenancy/__init__.py +0 -1
  638. nautobot/tenancy/apps.py +1 -0
  639. nautobot/tenancy/factory.py +3 -2
  640. nautobot/tenancy/filters/__init__.py +1 -0
  641. nautobot/tenancy/forms.py +1 -1
  642. nautobot/tenancy/templates/tenancy/tenant.html +24 -20
  643. nautobot/tenancy/views.py +11 -10
  644. nautobot/users/__init__.py +0 -1
  645. nautobot/users/api/serializers.py +1 -1
  646. nautobot/users/api/views.py +4 -2
  647. nautobot/users/apps.py +3 -2
  648. nautobot/users/factory.py +3 -3
  649. nautobot/users/migrations/0010_user_default_saved_views.py +20 -0
  650. nautobot/users/models.py +12 -0
  651. nautobot/users/tests/test_filters.py +6 -3
  652. nautobot/users/urls.py +8 -0
  653. nautobot/virtualization/__init__.py +0 -1
  654. nautobot/virtualization/apps.py +1 -0
  655. nautobot/virtualization/filters.py +6 -1
  656. nautobot/virtualization/forms.py +11 -3
  657. nautobot/virtualization/graphql/types.py +2 -2
  658. nautobot/virtualization/migrations/0029_add_role_field_to_interface_models.py +27 -0
  659. nautobot/virtualization/migrations/0030_alter_virtualmachine_local_config_context_data_owner_content_type_and_more.py +67 -0
  660. nautobot/virtualization/models.py +0 -2
  661. nautobot/virtualization/tables.py +10 -3
  662. nautobot/virtualization/templates/virtualization/virtualmachine.html +1 -1
  663. nautobot/virtualization/templates/virtualization/vminterface.html +7 -1
  664. nautobot/virtualization/templates/virtualization/vminterface_edit.html +1 -0
  665. nautobot/virtualization/tests/test_api.py +9 -4
  666. nautobot/virtualization/tests/test_filters.py +22 -0
  667. nautobot/virtualization/tests/test_models.py +7 -3
  668. nautobot/virtualization/tests/test_views.py +19 -3
  669. nautobot/virtualization/urls.py +2 -2
  670. nautobot/virtualization/views.py +10 -32
  671. {nautobot-2.2.9.dist-info → nautobot-2.3.0.dist-info}/METADATA +20 -18
  672. {nautobot-2.2.9.dist-info → nautobot-2.3.0.dist-info}/RECORD +677 -557
  673. nautobot/project-static/docs/assets/stylesheets/main.76a95c52.min.css +0 -1
  674. nautobot/project-static/docs/assets/stylesheets/main.76a95c52.min.css.map +0 -1
  675. nautobot/project-static/materialdesignicons-6.5.95/.github/ISSUE_TEMPLATE.md +0 -3
  676. nautobot/project-static/materialdesignicons-6.5.95/README.md +0 -25
  677. nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.css +0 -26654
  678. nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.css.map +0 -16
  679. nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.min.css +0 -3
  680. nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.min.css.map +0 -16
  681. nautobot/project-static/materialdesignicons-6.5.95/fonts/materialdesignicons-webfont.woff +0 -0
  682. nautobot/project-static/materialdesignicons-6.5.95/fonts/materialdesignicons-webfont.woff2 +0 -0
  683. nautobot/project-static/materialdesignicons-6.5.95/package.json +0 -28
  684. nautobot/project-static/materialdesignicons-6.5.95/preview.html +0 -717
  685. nautobot/project-static/materialdesignicons-6.5.95/scss/_animated.scss +0 -27
  686. nautobot/project-static/materialdesignicons-6.5.95/scss/_core.scss +0 -10
  687. nautobot/project-static/materialdesignicons-6.5.95/scss/_extras.scss +0 -65
  688. nautobot/project-static/materialdesignicons-6.5.95/scss/_functions.scss +0 -20
  689. nautobot/project-static/materialdesignicons-6.5.95/scss/_icons.scss +0 -10
  690. nautobot/project-static/materialdesignicons-6.5.95/scss/_path.scss +0 -10
  691. nautobot/project-static/materialdesignicons-6.5.95/scss/_variables.scss +0 -6606
  692. nautobot/project-static/materialdesignicons-6.5.95/scss/materialdesignicons.scss +0 -8
  693. /nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/LICENSE +0 -0
  694. {nautobot-2.2.9.dist-info → nautobot-2.3.0.dist-info}/LICENSE.txt +0 -0
  695. {nautobot-2.2.9.dist-info → nautobot-2.3.0.dist-info}/NOTICE +0 -0
  696. {nautobot-2.2.9.dist-info → nautobot-2.3.0.dist-info}/WHEEL +0 -0
  697. {nautobot-2.2.9.dist-info → nautobot-2.3.0.dist-info}/entry_points.txt +0 -0
@@ -1,9 +1,7 @@
1
1
  import contextlib
2
2
  import contextvars
3
- from datetime import timedelta
4
3
  import logging
5
4
  import os
6
- import secrets
7
5
  import shutil
8
6
  import traceback
9
7
 
@@ -23,7 +21,6 @@ import redis.exceptions
23
21
 
24
22
  from nautobot.core.celery import app, import_jobs
25
23
  from nautobot.core.models import BaseModel
26
- from nautobot.core.utils.config import get_settings_or_config
27
24
  from nautobot.core.utils.logging import sanitize
28
25
  from nautobot.extras.choices import JobResultStatusChoices, ObjectChangeActionChoices
29
26
  from nautobot.extras.constants import CHANGELOG_MAX_CHANGE_CONTEXT_DETAIL
@@ -35,6 +32,7 @@ from nautobot.extras.models import (
35
32
  DynamicGroupMembership,
36
33
  GitRepository,
37
34
  JobResult,
35
+ MetadataType,
38
36
  ObjectChange,
39
37
  Relationship,
40
38
  )
@@ -66,31 +64,47 @@ def get_user_if_authenticated(user, instance):
66
64
  return None
67
65
 
68
66
 
69
- @receiver(post_save)
70
- @receiver(m2m_changed)
71
- @receiver(post_delete)
67
+ @receiver(post_save, sender=ComputedField)
68
+ @receiver(post_save, sender=CustomField)
69
+ @receiver(post_save, sender=CustomField.content_types.through)
70
+ @receiver(post_save, sender=MetadataType)
71
+ @receiver(post_save, sender=MetadataType.content_types.through)
72
+ @receiver(m2m_changed, sender=ComputedField)
73
+ @receiver(m2m_changed, sender=CustomField)
74
+ @receiver(m2m_changed, sender=CustomField.content_types.through)
75
+ @receiver(m2m_changed, sender=MetadataType)
76
+ @receiver(m2m_changed, sender=MetadataType.content_types.through)
77
+ @receiver(post_delete, sender=ComputedField)
78
+ @receiver(post_delete, sender=CustomField)
79
+ @receiver(post_delete, sender=CustomField.content_types.through)
80
+ @receiver(post_delete, sender=MetadataType)
81
+ @receiver(post_delete, sender=MetadataType.content_types.through)
72
82
  def invalidate_models_cache(sender, **kwargs):
73
- """Invalidate the related-models cache for ComputedFields, CustomFields and Relationships."""
83
+ """Invalidate the related-models cache for ComputedFields and CustomFields."""
74
84
  if sender is CustomField.content_types.through:
75
85
  manager = CustomField.objects
76
- elif sender in (ComputedField, CustomField, Relationship):
77
- manager = sender.objects
86
+ elif sender is MetadataType.content_types.through:
87
+ manager = MetadataType.objects
78
88
  else:
79
- return
89
+ manager = sender.objects
90
+
91
+ with contextlib.suppress(redis.exceptions.ConnectionError):
92
+ # TODO: *maybe* target more narrowly, e.g. only clear the cache for specific related content-types?
93
+ cache.delete_pattern(f"{manager.get_for_model.cache_key_prefix}.*")
80
94
 
81
- cached_methods = (
82
- "get_for_model",
83
- "get_for_model_source",
84
- "get_for_model_destination",
85
- )
86
95
 
87
- for method_name in cached_methods:
88
- if hasattr(manager, method_name):
89
- method = getattr(manager, method_name)
90
- if hasattr(method, "cache_key_prefix"):
91
- with contextlib.suppress(redis.exceptions.ConnectionError):
92
- # TODO: *maybe* target more narrowly, e.g. only clear the cache for specific related content-types?
93
- cache.delete_pattern(f"{method.cache_key_prefix}.*")
96
+ @receiver(post_save, sender=Relationship)
97
+ @receiver(m2m_changed, sender=Relationship)
98
+ @receiver(post_delete, sender=Relationship)
99
+ def invalidate_relationship_models_cache(sender, **kwargs):
100
+ """Invalidate the related-models caches for Relationships."""
101
+ for method in (
102
+ Relationship.objects.get_for_model_source,
103
+ Relationship.objects.get_for_model_destination,
104
+ ):
105
+ with contextlib.suppress(redis.exceptions.ConnectionError):
106
+ # TODO: *maybe* target more narrowly, e.g. only clear the cache for specific related content-types?
107
+ cache.delete_pattern(f"{method.cache_key_prefix}.*")
94
108
 
95
109
 
96
110
  @receiver(post_save)
@@ -131,7 +145,11 @@ def _handle_changed_object(sender, instance, raw=False, **kwargs):
131
145
 
132
146
  # Generate a unique identifier for this change to stash in the change context
133
147
  # This is used for deferred change logging and for looking up related changes without querying the database
134
- unique_object_change_id = f"{changed_object_type.pk}__{changed_object_id}__{user.pk}"
148
+ unique_object_change_id = None
149
+ if user is not None:
150
+ unique_object_change_id = f"{changed_object_type.pk}__{changed_object_id}__{user.pk}"
151
+ else:
152
+ unique_object_change_id = f"{changed_object_type.pk}__{changed_object_id}"
135
153
 
136
154
  # If a change already exists for this change_id, user, and object, update it instead of creating a new one.
137
155
  # If the object was deleted then recreated with the same pk (don't do this), change the action to update.
@@ -146,12 +164,13 @@ def _handle_changed_object(sender, instance, raw=False, **kwargs):
146
164
  # Skip the database check when deferring object changes
147
165
  if not change_context.defer_object_changes and related_changes.exists():
148
166
  objectchange = instance.to_objectchange(action)
149
- most_recent_change = related_changes.order_by("-time").first()
150
- if most_recent_change.action == ObjectChangeActionChoices.ACTION_DELETE:
151
- most_recent_change.action = ObjectChangeActionChoices.ACTION_UPDATE
152
- most_recent_change.object_data = objectchange.object_data
153
- most_recent_change.object_data_v2 = objectchange.object_data_v2
154
- most_recent_change.save()
167
+ if objectchange is not None:
168
+ most_recent_change = related_changes.order_by("-time").first()
169
+ if most_recent_change.action == ObjectChangeActionChoices.ACTION_DELETE:
170
+ most_recent_change.action = ObjectChangeActionChoices.ACTION_UPDATE
171
+ most_recent_change.object_data = objectchange.object_data
172
+ most_recent_change.object_data_v2 = objectchange.object_data_v2
173
+ most_recent_change.save()
155
174
 
156
175
  else:
157
176
  change_context.deferred_object_changes[unique_object_change_id] = [
@@ -159,11 +178,14 @@ def _handle_changed_object(sender, instance, raw=False, **kwargs):
159
178
  ]
160
179
  if not change_context.defer_object_changes:
161
180
  objectchange = instance.to_objectchange(action)
162
- objectchange.user = user
163
- objectchange.request_id = change_context.change_id
164
- objectchange.change_context = change_context.context
165
- objectchange.change_context_detail = change_context.context_detail[:CHANGELOG_MAX_CHANGE_CONTEXT_DETAIL]
166
- objectchange.save()
181
+ if objectchange is not None:
182
+ objectchange.user = user
183
+ objectchange.request_id = change_context.change_id
184
+ objectchange.change_context = change_context.context
185
+ objectchange.change_context_detail = change_context.context_detail[
186
+ :CHANGELOG_MAX_CHANGE_CONTEXT_DETAIL
187
+ ]
188
+ objectchange.save()
167
189
 
168
190
  # restore field cache
169
191
  instance._state.fields_cache = original_cache
@@ -174,12 +196,6 @@ def _handle_changed_object(sender, instance, raw=False, **kwargs):
174
196
  elif action == ObjectChangeActionChoices.ACTION_UPDATE:
175
197
  model_updates.labels(instance._meta.model_name).inc()
176
198
 
177
- # Housekeeping: 0.1% chance of clearing out expired ObjectChanges
178
- changelog_retention = get_settings_or_config("CHANGELOG_RETENTION")
179
- if changelog_retention and secrets.randbelow(1000) == 0:
180
- cutoff = timezone.now() - timedelta(days=changelog_retention)
181
- ObjectChange.objects.filter(time__lt=cutoff).delete()
182
-
183
199
 
184
200
  @receiver(pre_delete)
185
201
  def _handle_deleted_object(sender, instance, **kwargs):
@@ -236,13 +252,14 @@ def _handle_deleted_object(sender, instance, **kwargs):
236
252
  # Skip the database check when deferring object changes
237
253
  if not change_context.defer_object_changes and related_changes.exists():
238
254
  objectchange = instance.to_objectchange(ObjectChangeActionChoices.ACTION_DELETE)
239
- most_recent_change = related_changes.order_by("-time").first()
240
- if most_recent_change.action != ObjectChangeActionChoices.ACTION_CREATE:
241
- most_recent_change.action = ObjectChangeActionChoices.ACTION_DELETE
242
- most_recent_change.object_data = objectchange.object_data
243
- most_recent_change.object_data_v2 = objectchange.object_data_v2
244
- most_recent_change.save()
245
- save_new_objectchange = False
255
+ if objectchange is not None:
256
+ most_recent_change = related_changes.order_by("-time").first()
257
+ if most_recent_change.action != ObjectChangeActionChoices.ACTION_CREATE:
258
+ most_recent_change.action = ObjectChangeActionChoices.ACTION_DELETE
259
+ most_recent_change.object_data = objectchange.object_data
260
+ most_recent_change.object_data_v2 = objectchange.object_data_v2
261
+ most_recent_change.save()
262
+ save_new_objectchange = False
246
263
 
247
264
  if save_new_objectchange:
248
265
  change_context.deferred_object_changes.setdefault(unique_object_change_id, []).append(
@@ -250,16 +267,20 @@ def _handle_deleted_object(sender, instance, **kwargs):
250
267
  "action": ObjectChangeActionChoices.ACTION_DELETE,
251
268
  "instance": instance,
252
269
  "user": user,
253
- "changed_object_id": instance.pk,
270
+ "changed_object_id": changed_object_id,
271
+ "changed_object_type": changed_object_type,
254
272
  }
255
273
  )
256
274
  if not change_context.defer_object_changes:
257
275
  objectchange = instance.to_objectchange(ObjectChangeActionChoices.ACTION_DELETE)
258
- objectchange.user = user
259
- objectchange.request_id = change_context.change_id
260
- objectchange.change_context = change_context.context
261
- objectchange.change_context_detail = change_context.context_detail[:CHANGELOG_MAX_CHANGE_CONTEXT_DETAIL]
262
- objectchange.save()
276
+ if objectchange is not None:
277
+ objectchange.user = user
278
+ objectchange.request_id = change_context.change_id
279
+ objectchange.change_context = change_context.context
280
+ objectchange.change_context_detail = change_context.context_detail[
281
+ :CHANGELOG_MAX_CHANGE_CONTEXT_DETAIL
282
+ ]
283
+ objectchange.save()
263
284
 
264
285
  # restore field cache
265
286
  instance._state.fields_cache = original_cache
@@ -400,60 +421,18 @@ m2m_changed.connect(dynamic_group_children_changed, sender=DynamicGroup.children
400
421
  pre_save.connect(dynamic_group_membership_created, sender=DynamicGroupMembership)
401
422
 
402
423
 
403
- def dynamic_group_eligible_groups_changed(sender, instance, **kwargs):
404
- """
405
- When a DynamicGroup is created or deleted, refresh the cache of eligible groups for the associated ContentType.
406
-
407
- Can't change content_type_id on an existing instance, so no need to check for that.
408
- """
409
-
410
- if get_settings_or_config("DYNAMIC_GROUPS_MEMBER_CACHE_TIMEOUT") == 0:
411
- # Caching is disabled, so there's nothing to do
412
- return
413
-
414
- if kwargs.get("created", None) is False:
415
- # We do not care about updates
416
- # "created" is not a kwarg for post_delete signals, so is unset or None
417
- # "created" is a kwarg for post_save signals, but you cannot change content types of existing groups
418
- # therefor we can ignore cache updates on DynamicGroups updates
419
- return
420
-
421
- content_type = instance.content_type
422
- cache_key = f"nautobot.{content_type.app_label}.{content_type.model}._get_eligible_dynamic_groups"
423
- cache.set(
424
- cache_key,
425
- DynamicGroup.objects.filter(content_type_id=instance.content_type_id),
426
- get_settings_or_config("DYNAMIC_GROUPS_MEMBER_CACHE_TIMEOUT"),
427
- )
428
-
429
-
430
- post_save.connect(dynamic_group_eligible_groups_changed, sender=DynamicGroup)
431
- post_delete.connect(dynamic_group_eligible_groups_changed, sender=DynamicGroup)
432
-
433
-
434
424
  def dynamic_group_update_cached_members(sender, instance, **kwargs):
435
425
  """
436
- When a DynamicGroup or DynamicGroupMembership is updated, update the cache of members.
426
+ When a DynamicGroup or DynamicGroupMembership is updated, update the cache of members for it and any parent groups.
437
427
  """
438
-
439
- if get_settings_or_config("DYNAMIC_GROUPS_MEMBER_CACHE_TIMEOUT") == 0:
440
- # Caching is disabled, so there's nothing to do
441
- return
442
-
443
428
  if isinstance(instance, DynamicGroupMembership):
444
- group = instance.group
429
+ group = instance.parent_group
445
430
  else:
446
431
  group = instance
447
432
 
448
- def _update_cache_and_parents(this_instance):
449
- this_instance.update_cached_members()
450
-
451
- # Since a change a group or group of groups does not affect it's children, we only need to go up the tree
452
- # A group of groups does not use the cache of it's children due to the complexity of the set operations
453
- for ancestor in list(this_instance.parents.all()):
454
- _update_cache_and_parents(ancestor)
455
-
456
- _update_cache_and_parents(group)
433
+ group.update_cached_members()
434
+ for ancestor in group.get_ancestors():
435
+ ancestor.update_cached_members()
457
436
 
458
437
 
459
438
  post_save.connect(dynamic_group_update_cached_members, sender=DynamicGroup)
@@ -507,3 +486,19 @@ def refresh_job_models(sender, *, apps, **kwargs):
507
486
  )
508
487
  job_model.installed = False
509
488
  job_model.save()
489
+
490
+
491
+ #
492
+ # Metadata
493
+ #
494
+
495
+
496
+ def handle_mdt_removed_obj_types(instance, action, pk_set, **kwargs): # pylint: disable=useless-return
497
+ """Handle the cleanup of old Metadata when a MetadataType is removed from one or more ContentTypes."""
498
+ if action != "post_remove":
499
+ return
500
+ # Existing content types have been removed from the MetadataType, delete their data.
501
+ # TODO delete Metadata records with object_type in pk_set and metadata_type == instance
502
+
503
+
504
+ m2m_changed.connect(handle_mdt_removed_obj_types, sender=MetadataType.content_types.through)
nautobot/extras/tables.py CHANGED
@@ -1,5 +1,5 @@
1
1
  from django.conf import settings
2
- from django.utils.html import format_html
2
+ from django.utils.html import format_html, format_html_join
3
3
  import django_tables2 as tables
4
4
  from django_tables2.utils import Accessor
5
5
  from jsonschema.exceptions import ValidationError as JSONSchemaValidationError
@@ -15,8 +15,10 @@ from nautobot.core.tables import (
15
15
  TagColumn,
16
16
  ToggleColumn,
17
17
  )
18
- from nautobot.core.templatetags.helpers import render_boolean, render_markdown
18
+ from nautobot.core.templatetags.helpers import render_boolean, render_json, render_markdown
19
+ from nautobot.tenancy.tables import TenantColumn
19
20
 
21
+ from .choices import MetadataTypeDataTypeChoices
20
22
  from .models import (
21
23
  ComputedField,
22
24
  ConfigContext,
@@ -36,14 +38,18 @@ from .models import (
36
38
  JobHook,
37
39
  JobLogEntry,
38
40
  JobResult,
41
+ MetadataType,
39
42
  Note,
40
43
  ObjectChange,
44
+ ObjectMetadata,
41
45
  Relationship,
42
46
  RelationshipAssociation,
43
47
  Role,
48
+ SavedView,
44
49
  ScheduledJob,
45
50
  Secret,
46
51
  SecretsGroup,
52
+ StaticGroupAssociation,
47
53
  Status,
48
54
  Tag,
49
55
  TaggedItem,
@@ -52,6 +58,11 @@ from .models import (
52
58
  )
53
59
  from .registry import registry
54
60
 
61
+ ASSIGNED_OBJECT = """
62
+ {% load helpers %}
63
+ {{ record.assigned_object|hyperlinked_object }}
64
+ """
65
+
55
66
  CONTACT_OR_TEAM_ICON = """
56
67
  {% if record.contact %}
57
68
  <i class="mdi mdi-account" title="Contact"></i>
@@ -76,11 +87,8 @@ EMAIL = """
76
87
  """
77
88
 
78
89
  TAGGED_ITEM = """
79
- {% if value.get_absolute_url %}
80
- <a href="{{ value.get_absolute_url }}">{{ value }}</a>
81
- {% else %}
82
- {{ value }}
83
- {% endif %}
90
+ {% load helpers %}
91
+ {{ value|hyperlinked_object }}
84
92
  """
85
93
 
86
94
  GITREPOSITORY_PROVIDES = """
@@ -114,6 +122,17 @@ OBJECTCHANGE_REQUEST_ID = """
114
122
  <a href="{% url 'extras:objectchange_list' %}?request_id={{ value }}">{{ value }}</a>
115
123
  """
116
124
 
125
+ MEMBERS_COUNT = """
126
+ {% load helpers %}
127
+ {% with urlname=record.model|validated_viewname:"list" %}
128
+ {% if urlname %}
129
+ <a href="{% url urlname %}?dynamic_groups={{ record.name }}">{{ record.members_count }}</a>
130
+ {% else %}
131
+ {{ record.members_count }}
132
+ {% endif %}
133
+ {% endwith %}
134
+ """
135
+
117
136
  # TODO: Webhook content_types in table order_by
118
137
  WEBHOOK_CONTENT_TYPES = """
119
138
  {{ value.all|join:", "|truncatewords:15 }}
@@ -328,11 +347,24 @@ class DynamicGroupTable(BaseTable):
328
347
  pk = ToggleColumn()
329
348
  name = tables.Column(linkify=True)
330
349
  members = tables.Column(accessor="count", verbose_name="Group Members", orderable=False)
350
+ tenant = TenantColumn()
351
+ tags = TagColumn(url_name="extras:dynamicgroup_list")
331
352
  actions = ButtonsColumn(DynamicGroup)
332
353
 
333
354
  class Meta(BaseTable.Meta): # pylint: disable=too-few-public-methods
334
355
  model = DynamicGroup
335
356
  fields = (
357
+ "pk",
358
+ "name",
359
+ "description",
360
+ "content_type",
361
+ "group_type",
362
+ "members",
363
+ "tenant",
364
+ "tags",
365
+ "actions",
366
+ )
367
+ default_columns = (
336
368
  "pk",
337
369
  "name",
338
370
  "description",
@@ -353,7 +385,7 @@ class DynamicGroupMembershipTable(DynamicGroupTable):
353
385
  """Hybrid table for displaying info for both group and membership."""
354
386
 
355
387
  description = tables.Column(accessor="group.description")
356
- actions = ButtonsColumn(DynamicGroup, pk_field="pk", buttons=("edit",))
388
+ members = tables.Column(accessor="group.count", verbose_name="Group Members", orderable=False)
357
389
 
358
390
  class Meta(BaseTable.Meta):
359
391
  model = DynamicGroupMembership
@@ -364,9 +396,8 @@ class DynamicGroupMembershipTable(DynamicGroupTable):
364
396
  "weight",
365
397
  "members",
366
398
  "description",
367
- "actions",
368
399
  )
369
- exclude = ("content_type",)
400
+ exclude = ("content_type", "actions", "group_type")
370
401
 
371
402
 
372
403
  DESCENDANTS_LINK = """
@@ -439,6 +470,51 @@ class NestedDynamicGroupAncestorsTable(DynamicGroupTable):
439
470
  exclude = ["content_type"]
440
471
 
441
472
 
473
+ class SavedViewTable(BaseTable):
474
+ name = tables.Column(linkify=True)
475
+ actions = ButtonsColumn(SavedView)
476
+ is_global_default = BooleanColumn()
477
+ is_shared = BooleanColumn()
478
+
479
+ class Meta(BaseTable.Meta):
480
+ model = SavedView
481
+ fields = (
482
+ "name",
483
+ "owner",
484
+ "view",
485
+ "config",
486
+ "is_global_default",
487
+ "is_shared",
488
+ "actions",
489
+ )
490
+ default_columns = (
491
+ "name",
492
+ "owner",
493
+ "view",
494
+ "is_global_default",
495
+ "actions",
496
+ )
497
+
498
+ def render_config(self, record):
499
+ if record.config:
500
+ return render_json(record.config, pretty_print=True)
501
+ return self.default
502
+
503
+
504
+ class StaticGroupAssociationTable(BaseTable):
505
+ """Table for list view of `StaticGroupAssociation` objects."""
506
+
507
+ pk = ToggleColumn()
508
+ dynamic_group = tables.Column(linkify=True)
509
+ associated_object = tables.Column(linkify=True, verbose_name="Associated Object")
510
+ actions = ButtonsColumn(StaticGroupAssociation, buttons=["changelog", "delete"])
511
+
512
+ class Meta(BaseTable.Meta):
513
+ model = StaticGroupAssociation
514
+ fields = ["pk", "dynamic_group", "associated_object", "actions"]
515
+ default_columns = ["pk", "dynamic_group", "associated_object", "actions"]
516
+
517
+
442
518
  class ExportTemplateTable(BaseTable):
443
519
  pk = ToggleColumn()
444
520
  name = tables.Column(linkify=True)
@@ -589,7 +665,7 @@ class GraphQLQueryTable(BaseTable):
589
665
 
590
666
 
591
667
  def log_object_link(value, record):
592
- return record.absolute_url
668
+ return record.absolute_url or None
593
669
 
594
670
 
595
671
  def log_entry_color_css(record):
@@ -861,6 +937,83 @@ class JobButtonTable(BaseTable):
861
937
  )
862
938
 
863
939
 
940
+ #
941
+ # Metadata
942
+ #
943
+
944
+
945
+ class MetadataTypeTable(BaseTable):
946
+ pk = ToggleColumn()
947
+ name = tables.Column(linkify=True)
948
+ content_types = ContentTypesColumn(truncate_words=15)
949
+ actions = ButtonsColumn(MetadataType)
950
+
951
+ class Meta(BaseTable.Meta):
952
+ model = MetadataType
953
+ fields = (
954
+ "pk",
955
+ "name",
956
+ "description",
957
+ "content_types",
958
+ "data_type",
959
+ "actions",
960
+ )
961
+ default_columns = (
962
+ "pk",
963
+ "name",
964
+ "content_types",
965
+ "data_type",
966
+ "actions",
967
+ )
968
+
969
+
970
+ class ObjectMetadataTable(BaseTable):
971
+ pk = ToggleColumn()
972
+ metadata_type = tables.Column(linkify=True)
973
+ assigned_object = tables.TemplateColumn(
974
+ template_code=ASSIGNED_OBJECT, verbose_name="Assigned object", orderable=False
975
+ )
976
+ # This is needed so that render_value method below does not skip itself
977
+ # when metadata_type.data_type is TYPE_CONTACT_TEAM and we need it to display either contact or team
978
+ value = tables.Column(empty_values=[])
979
+
980
+ class Meta(BaseTable.Meta):
981
+ model = ObjectMetadata
982
+ fields = (
983
+ "pk",
984
+ "assigned_object",
985
+ "metadata_type",
986
+ "scoped_fields",
987
+ "value",
988
+ )
989
+ default_columns = (
990
+ "pk",
991
+ "assigned_object",
992
+ "scoped_fields",
993
+ "value",
994
+ "metadata_type",
995
+ )
996
+
997
+ def render_scoped_fields(self, value):
998
+ if not value:
999
+ return "(all fields)"
1000
+ return format_html_join(", ", "<code>{}</code>", ([v] for v in sorted(value)))
1001
+
1002
+ def render_value(self, record):
1003
+ if record.value is not None and record.metadata_type.data_type == MetadataTypeDataTypeChoices.TYPE_JSON:
1004
+ return render_json(record.value, pretty_print=True)
1005
+ elif record.value is not None and record.metadata_type.data_type == MetadataTypeDataTypeChoices.TYPE_MARKDOWN:
1006
+ return render_markdown(record.value)
1007
+ elif record.value is not None and record.metadata_type.data_type == MetadataTypeDataTypeChoices.TYPE_BOOLEAN:
1008
+ return render_boolean(record.value)
1009
+ elif record.metadata_type.data_type == MetadataTypeDataTypeChoices.TYPE_CONTACT_TEAM:
1010
+ if record.contact:
1011
+ return format_html('<a href="{}">{}</a>', record.contact.get_absolute_url(), record.contact)
1012
+ else:
1013
+ return format_html('<a href="{}">{}</a>', record.team.get_absolute_url(), record.team)
1014
+ return record.value
1015
+
1016
+
864
1017
  #
865
1018
  # Notes
866
1019
  #
@@ -1072,7 +1225,7 @@ class StatusTable(BaseTable):
1072
1225
 
1073
1226
  class Meta(BaseTable.Meta):
1074
1227
  model = Status
1075
- fields = ["pk", "name", "color", "content_types", "description"]
1228
+ fields = ["pk", "name", "color", "content_types", "description", "actions"]
1076
1229
 
1077
1230
 
1078
1231
  class StatusTableMixin(BaseTable):
@@ -3,7 +3,7 @@
3
3
 
4
4
  {% block extra_nav_tabs %}
5
5
  <li role="presentation"{% if request.GET.tab == 'members' %} class="active"{% endif %}>
6
- <a href="{{ object.get_absolute_url }}#members" onclick="switch_tab(this.href, reload=true)" aria-controls="members" role="tab" data-toggle="tab">
6
+ <a href="{{ object.get_absolute_url }}#members" onclick="switch_tab(this.href, reload=false)" aria-controls="members" role="tab" data-toggle="tab">
7
7
  Members {% badge object.count %}
8
8
  </a>
9
9
  </li>
@@ -11,6 +11,15 @@
11
11
 
12
12
  {% block extra_tab_content %}
13
13
  <div id="members" role="tabpanel" class="tab-pane {% if not active_tab and not request.GET.tab or request.GET.tab == "members" %}active{% else %}fade{% endif %}">
14
+ {% if members_list_url %}
15
+ <div class="row">
16
+ <div class="col-md-12">
17
+ <div class="alert alert-success" role="alert">
18
+ You can bulk-add and bulk-remove members of this group from the <a href="{{ members_list_url }}">{{ members_verbose_name_plural|bettertitle }} list view</a>.
19
+ </div>
20
+ </div>
21
+ </div>
22
+ {% endif %}
14
23
  <div class="row">
15
24
  <div class="col-md-12">
16
25
  {% include 'utilities/obj_table.html' with table=members_table table_template='panel_table.html' heading='Dynamic Group members' %}
@@ -37,31 +46,49 @@
37
46
  <td>Content Type</td>
38
47
  <td><span>{{ object.content_type }}</span></td>
39
48
  </tr>
49
+ <tr>
50
+ <td>Group Type</td>
51
+ <td><span>{{ object.get_group_type_display }}</span></td>
52
+ </tr>
53
+ <tr>
54
+ <td>Tenant</td>
55
+ <td>
56
+ {% if object.tenant and object.tenant.tenant_group %}
57
+ {{ object.tenant.tenant_group|hyperlinked_object }} /
58
+ {% endif %}
59
+ {{ object.tenant|hyperlinked_object }}
60
+ </td>
61
+ </tr>
40
62
  </table>
41
63
  </div>
42
64
  {% endblock content_left_page %}
43
65
 
44
66
  {% block content_right_page %}
45
- <div class="panel panel-default">
46
- <div class="panel-heading">
47
- <strong>Filter</strong>
48
- </div>
49
- <div class="panel-body">
50
- <pre>{{ object.filter | render_json }}</pre>
67
+ {% if object.group_type == "dynamic-filter" %}
68
+ <div class="panel panel-default">
69
+ <div class="panel-heading">
70
+ <strong>Filter</strong>
71
+ </div>
72
+ <div class="panel-body">
73
+ <pre>{{ object.filter | render_json }}</pre>
74
+ </div>
51
75
  </div>
52
- </div>
76
+ {% endif %}
53
77
  {% endblock content_right_page %}
54
78
 
55
79
  {% block content_full_width_page %}
80
+ {% if object.group_type != "static" %}
56
81
  <div class="panel panel-default">
57
82
  <div class="panel-heading">
58
83
  <strong>Filter Query Logic</strong>
59
84
  </div>
60
85
  <div class="panel-body">
61
- <span class="help-block">
62
- This is a raw representation of the underlying filter that is derived
63
- by aggregating the filters from all descendant groups.
64
- </span>
86
+ {% if object.group_type == "dynamic-set" %}
87
+ <span class="help-block">
88
+ This is a raw representation of the underlying filter that is derived
89
+ by aggregating the filters from all descendant groups.
90
+ </span>
91
+ {% endif %}
65
92
  <pre>{{ raw_query }}</pre>
66
93
  </div>
67
94
  </div>
@@ -70,9 +97,11 @@
70
97
  <strong>Related Groups</strong>
71
98
  </div>
72
99
  <div class="panel-body">
73
- {% include 'utilities/obj_table.html' with table=descendants_table table_template='panel_table.html' heading='Descendants' disable_pagination=True %}
74
- {% include 'utilities/obj_table.html' with table=ancestors_table table_template='panel_table.html' heading='Ancestors' disable_pagination=True %}
100
+ {% if object.group_type == "dynamic-set" %}
101
+ {% include 'utilities/obj_table.html' with table=descendants_table table_template='panel_table.html' heading='Descendants' disable_pagination=True %}
102
+ {% endif %}
103
+ {% include 'utilities/obj_table.html' with table=ancestors_table table_template='panel_table.html' heading='Ancestors' disable_pagination=True %}
75
104
  </div>
76
105
  </div>
77
-
106
+ {% endif %}
78
107
  {% endblock content_full_width_page %}
@@ -25,6 +25,8 @@
25
25
  {% render_field form.name %}
26
26
  {% render_field form.description %}
27
27
  {% render_field form.content_type %}
28
+ {% render_field form.group_type %}
29
+ {% render_field form.tenant %}
28
30
  </div>
29
31
  </div>
30
32
  <div class="panel panel-default">