nautobot 3.0.0a2__py3-none-any.whl → 3.0.0a3__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 (420) hide show
  1. nautobot/apps/choices.py +0 -2
  2. nautobot/apps/filters.py +7 -9
  3. nautobot/apps/models.py +2 -2
  4. nautobot/apps/ui.py +9 -1
  5. nautobot/circuits/filters.py +3 -2
  6. nautobot/circuits/navigation.py +3 -2
  7. nautobot/circuits/templates/circuits/circuit.html +1 -1
  8. nautobot/circuits/templates/circuits/circuit_create.html +3 -3
  9. nautobot/circuits/templates/circuits/circuittermination.html +1 -1
  10. nautobot/circuits/templates/circuits/circuittermination_create.html +9 -24
  11. nautobot/circuits/templates/circuits/circuittype.html +1 -1
  12. nautobot/circuits/templates/circuits/inc/circuit_termination_cable_fragment.html +6 -6
  13. nautobot/circuits/templates/circuits/inc/speed_widget.html +12 -12
  14. nautobot/circuits/templates/circuits/providernetwork.html +1 -1
  15. nautobot/circuits/tests/integration/test_circuit.py +10 -13
  16. nautobot/cloud/filters.py +1 -1
  17. nautobot/cloud/navigation.py +3 -2
  18. nautobot/core/api/schema.py +1 -1
  19. nautobot/core/api/serializers.py +6 -1
  20. nautobot/core/api/urls.py +1 -0
  21. nautobot/core/api/views.py +8 -0
  22. nautobot/core/apps/__init__.py +11 -10
  23. nautobot/core/celery/__init__.py +3 -5
  24. nautobot/core/checks.py +46 -0
  25. nautobot/core/cli/bootstrap_v3_to_v5.py +70 -1
  26. nautobot/core/cli/migrate_deprecated_templates.py +200 -0
  27. nautobot/core/constants.py +3 -0
  28. nautobot/core/context_processors.py +9 -1
  29. nautobot/core/forms/forms.py +1 -1
  30. nautobot/core/jobs/__init__.py +6 -3
  31. nautobot/core/jobs/groups.py +31 -1
  32. nautobot/core/management/commands/generate_test_data.py +28 -9
  33. nautobot/core/models/generics.py +9 -1
  34. nautobot/core/models/tree_queries.py +10 -5
  35. nautobot/core/settings.py +18 -12
  36. nautobot/core/settings.yaml +13 -7
  37. nautobot/core/signals.py +12 -1
  38. nautobot/core/tables.py +13 -6
  39. nautobot/core/templates/40x.html +1 -1
  40. nautobot/core/templates/500.html +2 -2
  41. nautobot/core/templates/admin/config/config.html +12 -12
  42. nautobot/core/templates/admin/index.html +3 -3
  43. nautobot/core/templates/buttons/export.html +1 -1
  44. nautobot/core/templates/components/button/dropdown.html +5 -3
  45. nautobot/core/templates/components/panel/body_wrapper_generic_table.html +1 -1
  46. nautobot/core/templates/components/panel/panel.html +3 -3
  47. nautobot/core/templates/components/tab/content_wrapper.html +2 -3
  48. nautobot/core/templates/components/tab/label_wrapper_distinct_view.html +1 -1
  49. nautobot/core/templates/echarts/echarts.html +1 -1
  50. nautobot/core/templates/generic/object_bulk_add_component.html +2 -1
  51. nautobot/core/templates/generic/object_bulk_create.html +4 -3
  52. nautobot/core/templates/generic/object_bulk_destroy.html +3 -3
  53. nautobot/core/templates/generic/object_bulk_remove.html +2 -2
  54. nautobot/core/templates/generic/object_bulk_update.html +5 -4
  55. nautobot/core/templates/generic/object_create.html +5 -4
  56. nautobot/core/templates/generic/object_import.html +2 -1
  57. nautobot/core/templates/generic/object_list.html +12 -4
  58. nautobot/core/templates/generic/object_notes.html +5 -3
  59. nautobot/core/templates/generic/object_retrieve.html +2 -3
  60. nautobot/core/templates/graphene/graphiql.html +7 -7
  61. nautobot/core/templates/home.html +1 -1
  62. nautobot/core/templates/import_success.html +2 -1
  63. nautobot/core/templates/inc/computed_fields/panel_data.html +1 -1
  64. nautobot/core/templates/inc/created_updated.html +7 -3
  65. nautobot/core/templates/inc/custom_fields/panel_data.html +1 -1
  66. nautobot/core/templates/inc/form_static_field.html +6 -0
  67. nautobot/core/templates/inc/header.html +1 -1
  68. nautobot/core/templates/inc/image_attachments.html +2 -1
  69. nautobot/core/templates/inc/nav_menu.html +2 -1
  70. nautobot/core/templates/inc/search_panel.html +4 -4
  71. nautobot/core/templates/login.html +4 -2
  72. nautobot/core/templates/nautobot_config.py.j2 +6 -5
  73. nautobot/core/templates/redoc_ui.html +7 -0
  74. nautobot/core/templates/search.html +1 -1
  75. nautobot/core/templates/swagger_ui.html +17 -3
  76. nautobot/core/templates/system_jobs/import_objects.html +1 -2
  77. nautobot/core/templates/utilities/confirmation_form.html +2 -2
  78. nautobot/core/templates/utilities/obj_table.html +10 -2
  79. nautobot/core/templates/utilities/render_field.html +7 -7
  80. nautobot/core/templates/utilities/render_jinja2.html +2 -2
  81. nautobot/core/templates/utilities/templatetags/filter_form_drawer.html +4 -4
  82. nautobot/core/templates/utilities/theme_preview.html +16 -3
  83. nautobot/core/templates/widgets/selectwithdisabled_option.html +3 -1
  84. nautobot/core/templatetags/helpers.py +52 -6
  85. nautobot/core/testing/api.py +68 -9
  86. nautobot/core/testing/filters.py +0 -23
  87. nautobot/core/testing/integration.py +23 -10
  88. nautobot/core/testing/mixins.py +2 -0
  89. nautobot/core/testing/views.py +4 -0
  90. nautobot/core/tests/integration/test_app_home.py +34 -30
  91. nautobot/core/tests/integration/test_app_navbar.py +3 -0
  92. nautobot/core/tests/nautobot_config_without_example_apps.py +4 -0
  93. nautobot/core/tests/runner.py +9 -1
  94. nautobot/core/tests/test_api.py +5 -3
  95. nautobot/core/tests/test_breadcrumbs.py +6 -7
  96. nautobot/core/tests/test_checks.py +28 -0
  97. nautobot/core/tests/test_cli.py +40 -0
  98. nautobot/core/tests/test_config.py +2 -1
  99. nautobot/core/tests/test_forms.py +55 -13
  100. nautobot/core/tests/test_jobs.py +75 -1
  101. nautobot/core/tests/test_nautobot_server.py +2 -0
  102. nautobot/core/tests/test_navigations.py +76 -1
  103. nautobot/core/tests/test_patch_social_django.py +42 -0
  104. nautobot/core/tests/test_tables.py +3 -1
  105. nautobot/core/tests/test_templatetags_helpers.py +53 -13
  106. nautobot/core/tests/test_templatetags_ui_framework.py +4 -4
  107. nautobot/core/tests/test_tree_queries.py +14 -1
  108. nautobot/core/tests/test_ui.py +1 -1
  109. nautobot/core/tests/test_utils.py +31 -4
  110. nautobot/core/tests/test_views.py +159 -31
  111. nautobot/core/ui/breadcrumbs.py +2 -12
  112. nautobot/core/ui/choices.py +142 -10
  113. nautobot/core/ui/constants.py +76 -12
  114. nautobot/core/ui/object_detail.py +92 -12
  115. nautobot/core/urls.py +12 -1
  116. nautobot/core/utils/cache.py +2 -1
  117. nautobot/core/utils/filtering.py +17 -17
  118. nautobot/core/utils/lookup.py +3 -8
  119. nautobot/core/utils/module_loading.py +21 -0
  120. nautobot/core/utils/patch_social_django.py +128 -0
  121. nautobot/core/views/__init__.py +38 -1
  122. nautobot/core/views/generic.py +3 -3
  123. nautobot/core/views/mixins.py +15 -3
  124. nautobot/core/views/renderers.py +2 -0
  125. nautobot/core/views/viewsets.py +2 -1
  126. nautobot/data_validation/apps.py +1 -5
  127. nautobot/data_validation/custom_validators.py +4 -4
  128. nautobot/data_validation/filters.py +1 -1
  129. nautobot/data_validation/forms.py +40 -0
  130. nautobot/data_validation/migrations/0001_initial.py +0 -7
  131. nautobot/data_validation/migrations/0002_data_migration_from_app.py +0 -12
  132. nautobot/data_validation/models.py +16 -7
  133. nautobot/data_validation/navigation.py +8 -1
  134. nautobot/data_validation/tables.py +12 -5
  135. nautobot/data_validation/templates/data_validation/datacompliance_tab.html +1 -0
  136. nautobot/data_validation/templates/data_validation/device_constraints.html +61 -0
  137. nautobot/data_validation/tests/__init__.py +2 -2
  138. nautobot/data_validation/tests/migrations/test_migrations.py +83 -3
  139. nautobot/data_validation/tests/test_data_compliance_rules.py +12 -7
  140. nautobot/data_validation/tests/test_filters.py +8 -6
  141. nautobot/data_validation/tests/test_models.py +15 -0
  142. nautobot/data_validation/tests/test_views.py +190 -32
  143. nautobot/data_validation/urls.py +2 -5
  144. nautobot/data_validation/views.py +73 -40
  145. nautobot/dcim/api/serializers.py +0 -13
  146. nautobot/dcim/apps.py +4 -0
  147. nautobot/dcim/choices.py +16 -0
  148. nautobot/dcim/custom_validators.py +84 -0
  149. nautobot/dcim/filter_mixins.py +353 -4
  150. nautobot/dcim/{filters/__init__.py → filters.py} +2 -35
  151. nautobot/dcim/forms.py +1 -1
  152. nautobot/dcim/migrations/0078_remove_device_location_tenant_name_uniqueness.py +16 -0
  153. nautobot/dcim/migrations/0079_device_name_data_migration.py +59 -0
  154. nautobot/dcim/models/device_components.py +81 -68
  155. nautobot/dcim/models/devices.py +13 -16
  156. nautobot/dcim/navigation.py +7 -6
  157. nautobot/dcim/tables/devices.py +3 -0
  158. nautobot/dcim/tables/template_code.py +14 -14
  159. nautobot/dcim/templates/dcim/cable.html +2 -61
  160. nautobot/dcim/templates/dcim/cable_connect.html +28 -112
  161. nautobot/dcim/templates/dcim/cable_edit.html +2 -5
  162. nautobot/dcim/templates/dcim/cable_retrieve.html +61 -0
  163. nautobot/dcim/templates/dcim/cable_trace.html +1 -3
  164. nautobot/dcim/templates/dcim/cable_update.html +5 -0
  165. nautobot/dcim/templates/dcim/consoleport.html +6 -5
  166. nautobot/dcim/templates/dcim/consoleserverport.html +6 -5
  167. nautobot/dcim/templates/dcim/device/config.html +2 -2
  168. nautobot/dcim/templates/dcim/device/consoleports.html +1 -1
  169. nautobot/dcim/templates/dcim/device/consoleserverports.html +1 -1
  170. nautobot/dcim/templates/dcim/device/devicebays.html +1 -1
  171. nautobot/dcim/templates/dcim/device/frontports.html +1 -1
  172. nautobot/dcim/templates/dcim/device/interfaces.html +1 -1
  173. nautobot/dcim/templates/dcim/device/inventory.html +1 -1
  174. nautobot/dcim/templates/dcim/device/lldp_neighbors.html +1 -1
  175. nautobot/dcim/templates/dcim/device/modulebays.html +1 -1
  176. nautobot/dcim/templates/dcim/device/poweroutlets.html +1 -1
  177. nautobot/dcim/templates/dcim/device/powerports.html +1 -1
  178. nautobot/dcim/templates/dcim/device/rearports.html +1 -1
  179. nautobot/dcim/templates/dcim/device/status.html +8 -8
  180. nautobot/dcim/templates/dcim/device/wireless.html +1 -1
  181. nautobot/dcim/templates/dcim/device.html +1 -1
  182. nautobot/dcim/templates/dcim/device_component_add.html +2 -2
  183. nautobot/dcim/templates/dcim/device_create.html +5 -3
  184. nautobot/dcim/templates/dcim/device_interface_delete.html +1 -1
  185. nautobot/dcim/templates/dcim/device_list.html +73 -10
  186. nautobot/dcim/templates/dcim/devicebay_populate.html +2 -2
  187. nautobot/dcim/templates/dcim/devicetype.html +1 -1
  188. nautobot/dcim/templates/dcim/devicetype_component_add.html +2 -2
  189. nautobot/dcim/templates/dcim/footer_convert_to_contact_or_team_record.html +14 -0
  190. nautobot/dcim/templates/dcim/frontport.html +9 -8
  191. nautobot/dcim/templates/dcim/inc/edit_form_softwareversion_js.html +2 -2
  192. nautobot/dcim/templates/dcim/interface.html +26 -6
  193. nautobot/dcim/templates/dcim/interface_bulk_delete.html +1 -1
  194. nautobot/dcim/templates/dcim/inventoryitem_add.html +3 -1
  195. nautobot/dcim/templates/dcim/inventoryitem_bulk_delete.html +1 -1
  196. nautobot/dcim/templates/dcim/inventoryitem_edit.html +3 -1
  197. nautobot/dcim/templates/dcim/location_retrieve.html +1 -242
  198. nautobot/dcim/templates/dcim/module/base.html +49 -9
  199. nautobot/dcim/templates/dcim/module_list.html +57 -8
  200. nautobot/dcim/templates/dcim/modulefamily_retrieve.html +1 -1
  201. nautobot/dcim/templates/dcim/moduletype_retrieve.html +49 -9
  202. nautobot/dcim/templates/dcim/platform_create.html +1 -1
  203. nautobot/dcim/templates/dcim/powerfeed.html +1 -1
  204. nautobot/dcim/templates/dcim/powerpanel.html +1 -1
  205. nautobot/dcim/templates/dcim/powerport.html +5 -4
  206. nautobot/dcim/templates/dcim/rack_elevation_list.html +16 -4
  207. nautobot/dcim/templates/dcim/rack_retrieve.html +33 -15
  208. nautobot/dcim/templates/dcim/rearport.html +7 -6
  209. nautobot/dcim/templates/dcim/virtualchassis.html +1 -1
  210. nautobot/dcim/templates/dcim/virtualchassis_add_member.html +16 -14
  211. nautobot/dcim/templates/dcim/virtualchassis_update.html +14 -6
  212. nautobot/dcim/tests/integration/test_controller.py +1 -0
  213. nautobot/dcim/tests/test_api.py +8 -0
  214. nautobot/dcim/tests/test_custom_validators.py +229 -0
  215. nautobot/dcim/tests/test_filters.py +12 -6
  216. nautobot/dcim/tests/test_models.py +63 -4
  217. nautobot/dcim/tests/test_views.py +63 -22
  218. nautobot/dcim/urls.py +64 -21
  219. nautobot/dcim/utils.py +3 -3
  220. nautobot/dcim/views.py +547 -273
  221. nautobot/extras/api/views.py +9 -1
  222. nautobot/extras/choices.py +2 -13
  223. nautobot/extras/{filters/mixins.py → filter_mixins.py} +1 -1
  224. nautobot/extras/{filters/customfields.py → filter_mixins_customfields.py} +42 -6
  225. nautobot/extras/{filters/__init__.py → filters.py} +14 -46
  226. nautobot/extras/forms/forms.py +5 -13
  227. nautobot/extras/forms/mixins.py +0 -41
  228. nautobot/extras/management/__init__.py +9 -0
  229. nautobot/extras/migrations/0127_approval_workflow_models.py +6 -6
  230. nautobot/extras/migrations/0129_jobresult_debug_log_count_jobresult_error_log_count_and_more.py +37 -0
  231. nautobot/extras/migrations/0130_jobresult_generate_log_entry_counts.py +42 -0
  232. nautobot/extras/models/__init__.py +1 -2
  233. nautobot/extras/models/approvals.py +22 -13
  234. nautobot/extras/models/contacts.py +2 -0
  235. nautobot/extras/models/groups.py +44 -5
  236. nautobot/extras/models/jobs.py +59 -1
  237. nautobot/extras/models/mixins.py +28 -0
  238. nautobot/extras/models/models.py +13 -0
  239. nautobot/extras/models/secrets.py +1 -0
  240. nautobot/extras/models/statuses.py +0 -15
  241. nautobot/extras/navigation.py +13 -9
  242. nautobot/extras/plugins/__init__.py +33 -55
  243. nautobot/extras/plugins/tables.py +3 -3
  244. nautobot/extras/plugins/urls.py +2 -21
  245. nautobot/extras/plugins/utils.py +1 -33
  246. nautobot/extras/plugins/views.py +0 -4
  247. nautobot/extras/signals.py +20 -19
  248. nautobot/extras/tables.py +52 -68
  249. nautobot/extras/templates/extras/approval_dashboard.html +7 -5
  250. nautobot/extras/templates/extras/approvalworkflowdefinition_update.html +4 -2
  251. nautobot/extras/templates/extras/approvalworkflowstage_retrieve.html +20 -12
  252. nautobot/extras/templates/extras/computedfield.html +1 -1
  253. nautobot/extras/templates/extras/configcontext.html +1 -1
  254. nautobot/extras/templates/extras/configcontextschema_validation.html +2 -2
  255. nautobot/extras/templates/extras/customfield.html +1 -1
  256. nautobot/extras/templates/extras/dynamicgroup_retrieve.html +11 -5
  257. nautobot/extras/templates/extras/dynamicgroup_update.html +1 -1
  258. nautobot/extras/templates/extras/gitrepository_result.html +0 -2
  259. nautobot/extras/templates/extras/graphqlquery_retrieve.html +1 -96
  260. nautobot/extras/templates/extras/inc/approval_buttons_column.html +20 -6
  261. nautobot/extras/templates/extras/inc/bulk_edit_overridable_field.html +8 -7
  262. nautobot/extras/templates/extras/inc/configcontext_format.html +10 -3
  263. nautobot/extras/templates/extras/inc/graphqlquery_execute.html +71 -0
  264. nautobot/extras/templates/extras/inc/job_tiles.html +15 -3
  265. nautobot/extras/templates/extras/inc/json_format.html +10 -3
  266. nautobot/extras/templates/extras/inc/overridable_field.html +13 -12
  267. nautobot/extras/templates/extras/job.html +29 -12
  268. nautobot/extras/templates/extras/job_bulk_edit.html +18 -0
  269. nautobot/extras/templates/extras/job_edit.html +52 -46
  270. nautobot/extras/templates/extras/job_list.html +29 -25
  271. nautobot/extras/templates/extras/marketplace.html +5 -9
  272. nautobot/extras/templates/extras/object_configcontext.html +1 -1
  273. nautobot/extras/templates/extras/object_dynamicgroups.html +2 -2
  274. nautobot/extras/templates/extras/objectchange_retrieve.html +19 -37
  275. nautobot/extras/templates/extras/plugin_detail.html +26 -21
  276. nautobot/extras/templates/extras/plugins_list.html +16 -26
  277. nautobot/extras/templates/extras/role_retrieve.html +64 -0
  278. nautobot/extras/templates/extras/scheduledjob.html +4 -2
  279. nautobot/extras/templates/extras/secretsgroup.html +1 -1
  280. nautobot/extras/templates/extras/tag.html +1 -1
  281. nautobot/extras/templatetags/custom_links.py +12 -12
  282. nautobot/extras/templatetags/job_buttons.py +14 -12
  283. nautobot/extras/test_jobs/invalid_import.py +9 -0
  284. nautobot/extras/test_jobs/log_counts_by_level.py +23 -0
  285. nautobot/extras/test_jobs/missing_import.py +11 -0
  286. nautobot/extras/tests/integration/test_configcontextschema.py +27 -26
  287. nautobot/extras/tests/integration/test_customfields.py +8 -7
  288. nautobot/extras/tests/integration/test_dynamicgroups.py +5 -1
  289. nautobot/extras/tests/integration/test_plugin_banner.py +3 -0
  290. nautobot/extras/tests/integration/test_plugins.py +18 -6
  291. nautobot/extras/tests/test_api.py +27 -18
  292. nautobot/extras/tests/test_approvals.py +38 -38
  293. nautobot/extras/tests/test_changelog.py +35 -3
  294. nautobot/extras/tests/test_customfields.py +22 -13
  295. nautobot/extras/tests/test_customfields_filters.py +479 -0
  296. nautobot/extras/tests/test_dynamicgroups.py +39 -1
  297. nautobot/extras/tests/test_filters.py +21 -19
  298. nautobot/extras/tests/test_forms.py +18 -21
  299. nautobot/extras/tests/test_jobs.py +25 -4
  300. nautobot/extras/tests/test_migrations.py +1 -0
  301. nautobot/extras/tests/test_models.py +13 -31
  302. nautobot/extras/tests/test_plugins.py +36 -10
  303. nautobot/extras/tests/test_views.py +31 -30
  304. nautobot/extras/views.py +81 -19
  305. nautobot/ipam/factory.py +7 -0
  306. nautobot/ipam/filter_mixins.py +38 -0
  307. nautobot/ipam/filters.py +27 -38
  308. nautobot/ipam/formfields.py +1 -1
  309. nautobot/ipam/forms.py +6 -3
  310. nautobot/ipam/migrations/0030_ipam__namespaces.py +13 -0
  311. nautobot/ipam/migrations/0031_ipam___data_migrations.py +4 -1
  312. nautobot/ipam/migrations/0054_namespace_tenant.py +25 -0
  313. nautobot/ipam/models.py +29 -2
  314. nautobot/ipam/navigation.py +3 -2
  315. nautobot/ipam/signals.py +71 -0
  316. nautobot/ipam/tables.py +13 -6
  317. nautobot/ipam/templates/ipam/inc/toggle_available.html +10 -10
  318. nautobot/ipam/templates/ipam/inc/vlangroup_header.html +1 -0
  319. nautobot/ipam/templates/ipam/ipaddress.html +14 -0
  320. nautobot/ipam/templates/ipam/ipaddress_merge.html +3 -3
  321. nautobot/ipam/templates/ipam/ipaddresstointerface_retrieve.html +1 -0
  322. nautobot/ipam/templates/ipam/namespace_update.html +15 -0
  323. nautobot/ipam/templates/ipam/prefix_delete.html +1 -1
  324. nautobot/ipam/templates/ipam/prefix_list.html +14 -13
  325. nautobot/ipam/templates/ipam/service.html +1 -1
  326. nautobot/ipam/templates/ipam/vlan.html +1 -1
  327. nautobot/ipam/templates/ipam/vlan_interfaces.html +1 -1
  328. nautobot/ipam/templates/ipam/vlan_vminterfaces.html +1 -1
  329. nautobot/ipam/tests/migration/test_migrations.py +89 -0
  330. nautobot/ipam/tests/test_api.py +13 -6
  331. nautobot/ipam/tests/test_filters.py +10 -0
  332. nautobot/ipam/tests/test_forms.py +1 -1
  333. nautobot/ipam/tests/test_models.py +43 -1
  334. nautobot/ipam/tests/test_tables.py +1 -2
  335. nautobot/ipam/tests/test_utils.py +1 -1
  336. nautobot/ipam/tests/test_views.py +13 -14
  337. nautobot/ipam/ui.py +0 -17
  338. nautobot/ipam/utils/migrations.py +16 -2
  339. nautobot/ipam/utils/testing.py +9 -3
  340. nautobot/ipam/views.py +46 -6
  341. nautobot/project-static/dist/css/nautobot.css +1 -1
  342. nautobot/project-static/dist/css/nautobot.css.map +1 -1
  343. nautobot/project-static/dist/js/nautobot.js +1 -1
  344. nautobot/project-static/dist/js/nautobot.js.map +1 -1
  345. nautobot/project-static/js/cabletrace.js +1 -1
  346. nautobot/project-static/js/interface_filtering.js +20 -16
  347. nautobot/project-static/nautobot-icons/battery-3.svg +3 -0
  348. nautobot/project-static/nautobot-icons/cloud.svg +1 -1
  349. nautobot/project-static/nautobot-icons/control-panel.svg +1 -1
  350. nautobot/project-static/nautobot-icons/device-lifecycle.svg +1 -1
  351. nautobot/project-static/nautobot-icons/elements.svg +1 -1
  352. nautobot/project-static/nautobot-icons/extensibility.svg +3 -0
  353. nautobot/project-static/nautobot-icons/hammer.svg +1 -1
  354. nautobot/project-static/nautobot-icons/organization.svg +3 -0
  355. nautobot/project-static/nautobot-icons/secrets.svg +1 -1
  356. nautobot/project-static/nautobot-icons/security.svg +3 -0
  357. nautobot/project-static/nautobot-icons/server.svg +1 -1
  358. nautobot/project-static/nautobot-icons/star-filled.svg +1 -1
  359. nautobot/project-static/nautobot-icons/star.svg +1 -1
  360. nautobot/tenancy/api/serializers.py +1 -0
  361. nautobot/tenancy/api/views.py +2 -1
  362. nautobot/tenancy/{filters/__init__.py → filters.py} +2 -10
  363. nautobot/tenancy/navigation.py +3 -1
  364. nautobot/tenancy/tests/test_filters.py +0 -2
  365. nautobot/tenancy/views.py +2 -1
  366. nautobot/ui/src/js/collapse.js +3 -3
  367. nautobot/ui/src/js/nautobot.js +16 -0
  368. nautobot/ui/src/scss/colors.scss +1 -1
  369. nautobot/ui/src/scss/nautobot.scss +61 -28
  370. nautobot/users/templates/users/profile.html +45 -12
  371. nautobot/users/templates/users/sessionkey_delete.html +1 -1
  372. nautobot/users/tests/test_api.py +4 -0
  373. nautobot/users/views.py +4 -2
  374. nautobot/virtualization/models.py +1 -68
  375. nautobot/virtualization/navigation.py +3 -2
  376. nautobot/virtualization/templates/virtualization/virtual_machine_vminterface_delete.html +1 -1
  377. nautobot/virtualization/templates/virtualization/virtualmachine.html +1 -1
  378. nautobot/virtualization/templates/virtualization/virtualmachine_list.html +2 -2
  379. nautobot/virtualization/templates/virtualization/virtualmachine_update.html +3 -1
  380. nautobot/virtualization/tests/test_api.py +3 -0
  381. nautobot/virtualization/tests/test_models.py +44 -4
  382. nautobot/vpn/__init__.py +0 -0
  383. nautobot/vpn/api/serializers.py +113 -0
  384. nautobot/vpn/api/urls.py +19 -0
  385. nautobot/vpn/api/views.py +70 -0
  386. nautobot/vpn/apps.py +8 -0
  387. nautobot/vpn/choices.py +171 -0
  388. nautobot/vpn/factory.py +209 -0
  389. nautobot/vpn/filters.py +233 -0
  390. nautobot/vpn/forms.py +486 -0
  391. nautobot/vpn/homepage.py +19 -0
  392. nautobot/vpn/migrations/0001_initial.py +541 -0
  393. nautobot/vpn/migrations/0002_populate_defaults.py +199 -0
  394. nautobot/vpn/migrations/__init__.py +0 -0
  395. nautobot/vpn/models.py +527 -0
  396. nautobot/vpn/navigation.py +98 -0
  397. nautobot/vpn/tables.py +380 -0
  398. nautobot/vpn/templates/vpn/vpnprofile.html +2 -0
  399. nautobot/vpn/templates/vpn/vpnprofile_create.html +150 -0
  400. nautobot/vpn/tests/__init__.py +0 -0
  401. nautobot/vpn/tests/test_api.py +341 -0
  402. nautobot/vpn/tests/test_filters.py +139 -0
  403. nautobot/vpn/tests/test_forms.py +294 -0
  404. nautobot/vpn/tests/test_models.py +97 -0
  405. nautobot/vpn/tests/test_views.py +281 -0
  406. nautobot/vpn/urls.py +16 -0
  407. nautobot/vpn/views.py +437 -0
  408. nautobot/wireless/navigation.py +3 -2
  409. nautobot/wireless/tests/integration/test_radio_profile.py +1 -5
  410. nautobot/wireless/tests/test_api.py +1 -1
  411. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/METADATA +14 -14
  412. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/RECORD +417 -366
  413. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/entry_points.txt +1 -0
  414. nautobot/data_validation/template_content.py +0 -42
  415. nautobot/dcim/filters/mixins.py +0 -354
  416. nautobot/ipam/templates/ipam/inc/prefix_header_extra_content_table.html +0 -4
  417. /nautobot/tenancy/{filters/mixins.py → filter_mixins.py} +0 -0
  418. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/LICENSE.txt +0 -0
  419. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/NOTICE +0 -0
  420. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/WHEEL +0 -0
nautobot/vpn/forms.py ADDED
@@ -0,0 +1,486 @@
1
+ """Forms for the vpn models."""
2
+
3
+ import logging
4
+
5
+ from django import forms
6
+
7
+ from nautobot.apps.forms import (
8
+ add_blank_choice,
9
+ APISelect,
10
+ BulkEditNullBooleanSelect,
11
+ DynamicModelChoiceField,
12
+ DynamicModelMultipleChoiceField,
13
+ JSONArrayFormField,
14
+ NautobotBulkEditForm,
15
+ NautobotFilterForm,
16
+ NautobotModelForm,
17
+ StaticSelect2,
18
+ TagFilterField,
19
+ TagsBulkEditFormMixin,
20
+ )
21
+ from nautobot.dcim.choices import InterfaceTypeChoices
22
+ from nautobot.dcim.models import Device, Interface
23
+ from nautobot.extras.models import DynamicGroup, SecretsGroup
24
+ from nautobot.ipam.models import IPAddress, Prefix
25
+ from nautobot.tenancy.forms import TenancyFilterForm, TenancyForm
26
+
27
+ from . import choices, models
28
+
29
+ logger = logging.getLogger(__name__)
30
+
31
+
32
+ class VPNProfileForm(NautobotModelForm, TenancyForm): # pylint: disable=too-many-ancestors
33
+ """Form for creating and updating VPNProfile."""
34
+
35
+ secrets_group = DynamicModelChoiceField(
36
+ queryset=SecretsGroup.objects.all(),
37
+ required=False,
38
+ label="Secrets Group",
39
+ help_text="Secrets Group for the VPN Profile.",
40
+ )
41
+
42
+ class Meta:
43
+ """Meta attributes."""
44
+
45
+ model = models.VPNProfile
46
+ fields = [
47
+ "name",
48
+ "description",
49
+ "keepalive_interval",
50
+ "keepalive_retries",
51
+ "keepalive_enabled",
52
+ "secrets_group",
53
+ "role",
54
+ "extra_options",
55
+ "nat_traversal",
56
+ "tenant_group",
57
+ "tenant",
58
+ "tags",
59
+ ]
60
+
61
+
62
+ class VPNProfileBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm): # pylint: disable=too-many-ancestors
63
+ """VPNProfile bulk edit form."""
64
+
65
+ pk = forms.ModelMultipleChoiceField(queryset=models.VPNProfile.objects.all(), widget=forms.MultipleHiddenInput)
66
+ description = forms.CharField(required=False, label="Description")
67
+ keepalive_interval = forms.IntegerField(
68
+ min_value=0,
69
+ required=False,
70
+ )
71
+ keepalive_retries = forms.IntegerField(
72
+ min_value=0,
73
+ required=False,
74
+ )
75
+ keepalive_enabled = forms.NullBooleanField(
76
+ required=False, widget=BulkEditNullBooleanSelect, label="Keepalive Enabled"
77
+ )
78
+ nat_traversal = forms.NullBooleanField(required=False, widget=BulkEditNullBooleanSelect, label="Nat Traversal")
79
+
80
+ class Meta:
81
+ """Meta attributes."""
82
+
83
+ model = models.VPNProfile
84
+ nullable_fields = [
85
+ "description",
86
+ "keepalive_interval",
87
+ "keepalive_retries",
88
+ ]
89
+
90
+
91
+ VPNProfilePh1FormSet = forms.inlineformset_factory(
92
+ parent_model=models.VPNProfile,
93
+ model=models.VPNProfilePhase1PolicyAssignment,
94
+ fields=("vpn_phase1_policy", "weight"),
95
+ extra=1,
96
+ widgets={
97
+ "vpn_phase1_policy": APISelect(api_url="/api/vpn/vpn-phase-1-policies/"),
98
+ "weight": forms.NumberInput(attrs={"class": "form-control"}),
99
+ },
100
+ )
101
+
102
+
103
+ VPNProfilePh2FormSet = forms.inlineformset_factory(
104
+ parent_model=models.VPNProfile,
105
+ model=models.VPNProfilePhase2PolicyAssignment,
106
+ fields=("vpn_phase2_policy", "weight"),
107
+ extra=1,
108
+ widgets={
109
+ "vpn_phase2_policy": APISelect(api_url="/api/vpn/vpn-phase-2-policies/"),
110
+ "weight": forms.NumberInput(attrs={"class": "form-control"}),
111
+ },
112
+ )
113
+
114
+
115
+ class VPNProfileFilterForm(NautobotFilterForm, TenancyFilterForm): # pylint: disable=too-many-ancestors
116
+ """Filter form for VPNProfile."""
117
+
118
+ model = models.VPNProfile
119
+ q = forms.CharField(required=False, label="Search")
120
+ tags = TagFilterField(model)
121
+
122
+
123
+ class VPNPhase1PolicyForm(NautobotModelForm, TenancyForm): # pylint: disable=too-many-ancestors
124
+ """Form for creating and updating VPNPhase1Policy."""
125
+
126
+ ike_version = forms.ChoiceField(
127
+ required=False,
128
+ choices=add_blank_choice(choices.IkeVersionChoices),
129
+ widget=StaticSelect2,
130
+ label="IKE Version",
131
+ )
132
+ authentication_method = forms.ChoiceField(
133
+ required=False,
134
+ choices=add_blank_choice(choices.AuthenticationMethodChoices),
135
+ widget=StaticSelect2,
136
+ label="Authentication Method",
137
+ )
138
+
139
+ class Meta:
140
+ """Meta attributes."""
141
+
142
+ model = models.VPNPhase1Policy
143
+ fields = "__all__"
144
+
145
+
146
+ class VPNPhase1PolicyBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm): # pylint: disable=too-many-ancestors
147
+ """VPNPhase1Policy bulk edit form."""
148
+
149
+ pk = forms.ModelMultipleChoiceField(queryset=models.VPNPhase1Policy.objects.all(), widget=forms.MultipleHiddenInput)
150
+ description = forms.CharField(required=False, label="Description")
151
+ ike_version = forms.ChoiceField(
152
+ required=False,
153
+ choices=add_blank_choice(choices.IkeVersionChoices),
154
+ widget=StaticSelect2,
155
+ label="Ike Version",
156
+ )
157
+ aggressive_mode = forms.NullBooleanField(required=False, widget=BulkEditNullBooleanSelect, label="Aggressive Mode")
158
+ encryption_algorithm = JSONArrayFormField(
159
+ choices=choices.EncryptionAlgorithmChoices,
160
+ base_field=forms.CharField(),
161
+ required=False,
162
+ label="Encryption Algorithm",
163
+ )
164
+ integrity_algorithm = JSONArrayFormField(
165
+ choices=choices.IntegrityAlgorithmChoices,
166
+ base_field=forms.CharField(),
167
+ required=False,
168
+ label="Integrity Algorithm",
169
+ )
170
+ dh_group = JSONArrayFormField(
171
+ choices=choices.DhGroupChoices,
172
+ base_field=forms.CharField(),
173
+ required=False,
174
+ label="Dh Group",
175
+ )
176
+ lifetime_seconds = forms.IntegerField(
177
+ min_value=0,
178
+ required=False,
179
+ )
180
+ lifetime_kb = forms.IntegerField(
181
+ min_value=0,
182
+ required=False,
183
+ )
184
+ authentication_method = forms.ChoiceField(
185
+ required=False,
186
+ choices=add_blank_choice(choices.AuthenticationMethodChoices),
187
+ widget=StaticSelect2,
188
+ label="Authentication Method",
189
+ )
190
+
191
+ class Meta:
192
+ """Meta attributes."""
193
+
194
+ model = models.VPNPhase1Policy
195
+ nullable_fields = [
196
+ "description",
197
+ "ike_version",
198
+ "encryption_algorithm",
199
+ "integrity_algorithm",
200
+ "dh_group",
201
+ "lifetime_seconds",
202
+ "lifetime_kb",
203
+ "authentication_method",
204
+ ]
205
+
206
+
207
+ class VPNPhase1PolicyFilterForm(NautobotFilterForm, TenancyFilterForm): # pylint: disable=too-many-ancestors
208
+ """Filter form for VPNPhase1Policy."""
209
+
210
+ model = models.VPNPhase1Policy
211
+ q = forms.CharField(required=False, label="Search")
212
+ tags = TagFilterField(model)
213
+
214
+
215
+ class VPNPhase2PolicyForm(NautobotModelForm, TenancyForm): # pylint: disable=too-many-ancestors
216
+ """Form for creating and updating VPNPhase2Policy."""
217
+
218
+ class Meta:
219
+ """Meta attributes."""
220
+
221
+ model = models.VPNPhase2Policy
222
+ fields = "__all__"
223
+
224
+
225
+ class VPNPhase2PolicyBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm): # pylint: disable=too-many-ancestors
226
+ """VPNPhase2Policy bulk edit form."""
227
+
228
+ pk = forms.ModelMultipleChoiceField(queryset=models.VPNPhase2Policy.objects.all(), widget=forms.MultipleHiddenInput)
229
+ description = forms.CharField(required=False, label="Description")
230
+ encryption_algorithm = JSONArrayFormField(
231
+ choices=choices.EncryptionAlgorithmChoices,
232
+ base_field=forms.CharField(),
233
+ required=False,
234
+ label="Encryption Algorithm",
235
+ )
236
+ integrity_algorithm = JSONArrayFormField(
237
+ choices=choices.IntegrityAlgorithmChoices,
238
+ base_field=forms.CharField(),
239
+ required=False,
240
+ label="Integrity Algorithm",
241
+ )
242
+ pfs_group = JSONArrayFormField(
243
+ choices=choices.DhGroupChoices,
244
+ base_field=forms.CharField(),
245
+ required=False,
246
+ label="Pfs Group",
247
+ )
248
+ lifetime = forms.IntegerField(
249
+ min_value=0,
250
+ required=False,
251
+ )
252
+
253
+ class Meta:
254
+ """Meta attributes."""
255
+
256
+ model = models.VPNPhase2Policy
257
+ nullable_fields = [
258
+ "description",
259
+ "encryption_algorithm",
260
+ "integrity_algorithm",
261
+ "pfs_group",
262
+ "lifetime",
263
+ ]
264
+
265
+
266
+ class VPNPhase2PolicyFilterForm(NautobotFilterForm, TenancyFilterForm): # pylint: disable=too-many-ancestors
267
+ """Filter form for VPNPhase2Policy."""
268
+
269
+ model = models.VPNPhase2Policy
270
+ q = forms.CharField(required=False, label="Search")
271
+ tags = TagFilterField(model)
272
+
273
+
274
+ class VPNForm(NautobotModelForm, TenancyForm): # pylint: disable=too-many-ancestors
275
+ """Form for creating and updating VPN."""
276
+
277
+ vpn_profile = DynamicModelChoiceField(
278
+ queryset=models.VPNProfile.objects.all(),
279
+ required=False,
280
+ label="VPN Profile",
281
+ )
282
+
283
+ class Meta:
284
+ """Meta attributes."""
285
+
286
+ model = models.VPN
287
+ fields = "__all__"
288
+
289
+
290
+ class VPNBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm): # pylint: disable=too-many-ancestors
291
+ """VPN bulk edit form."""
292
+
293
+ pk = forms.ModelMultipleChoiceField(queryset=models.VPN.objects.all(), widget=forms.MultipleHiddenInput)
294
+ description = forms.CharField(required=False, label="Description")
295
+ vpn_profile = DynamicModelChoiceField(
296
+ queryset=models.VPNProfile.objects.all(),
297
+ required=False,
298
+ label="VPN Profile",
299
+ )
300
+
301
+ class Meta:
302
+ """Meta attributes."""
303
+
304
+ model = models.VPN
305
+ nullable_fields = [
306
+ "description",
307
+ "vpn_profile",
308
+ ]
309
+
310
+
311
+ class VPNFilterForm(NautobotFilterForm, TenancyFilterForm): # pylint: disable=too-many-ancestors
312
+ """Filter form for VPN."""
313
+
314
+ model = models.VPN
315
+ q = forms.CharField(required=False, label="Search")
316
+ tags = TagFilterField(model)
317
+
318
+
319
+ class VPNTunnelForm(NautobotModelForm, TenancyForm): # pylint: disable=too-many-ancestors
320
+ """Form for creating and updating VPNTunnel."""
321
+
322
+ vpn_profile = DynamicModelChoiceField(
323
+ queryset=models.VPNProfile.objects.all(),
324
+ required=False,
325
+ label="VPN Profile",
326
+ )
327
+ vpn = DynamicModelChoiceField(
328
+ queryset=models.VPN.objects.all(),
329
+ required=False,
330
+ label="VPN",
331
+ )
332
+ encapsulation = forms.ChoiceField(
333
+ required=True,
334
+ choices=add_blank_choice(choices.EncapsulationChoices),
335
+ widget=StaticSelect2,
336
+ label="Encapsulation",
337
+ )
338
+ endpoint_a = DynamicModelChoiceField(
339
+ queryset=models.VPNTunnelEndpoint.objects.all(),
340
+ required=False,
341
+ label="Endpoint A",
342
+ )
343
+ endpoint_z = DynamicModelChoiceField(
344
+ queryset=models.VPNTunnelEndpoint.objects.all(),
345
+ required=False,
346
+ label="Endpoint Z",
347
+ )
348
+
349
+ class Meta:
350
+ """Meta attributes."""
351
+
352
+ model = models.VPNTunnel
353
+ fields = "__all__"
354
+
355
+
356
+ class VPNTunnelBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm): # pylint: disable=too-many-ancestors
357
+ """VPNTunnel bulk edit form."""
358
+
359
+ pk = forms.ModelMultipleChoiceField(queryset=models.VPNTunnel.objects.all(), widget=forms.MultipleHiddenInput)
360
+ description = forms.CharField(required=False, label="Description")
361
+ vpn_profile = DynamicModelChoiceField(
362
+ queryset=models.VPNProfile.objects.all(),
363
+ required=False,
364
+ label="VPN Profile",
365
+ )
366
+ vpn = DynamicModelChoiceField(
367
+ queryset=models.VPN.objects.all(),
368
+ required=False,
369
+ label="VPN",
370
+ )
371
+ encapsulation = forms.ChoiceField(
372
+ required=False,
373
+ choices=add_blank_choice(choices.EncapsulationChoices),
374
+ widget=StaticSelect2,
375
+ label="Encapsulation",
376
+ )
377
+
378
+ class Meta:
379
+ """Meta attributes."""
380
+
381
+ model = models.VPNTunnel
382
+ nullable_fields = [
383
+ "vpn_profile",
384
+ "vpn",
385
+ "description",
386
+ "encapsulation",
387
+ ]
388
+
389
+
390
+ class VPNTunnelFilterForm(NautobotFilterForm, TenancyFilterForm): # pylint: disable=too-many-ancestors
391
+ """Filter form for VPNTunnel."""
392
+
393
+ model = models.VPNTunnel
394
+ q = forms.CharField(required=False, label="Search")
395
+ tags = TagFilterField(model)
396
+
397
+
398
+ class VPNTunnelEndpointForm(NautobotModelForm, TenancyForm): # pylint: disable=too-many-ancestors
399
+ """Form for creating and updating VPNTunnelEndpoint."""
400
+
401
+ device = DynamicModelChoiceField(
402
+ queryset=Device.objects.all(),
403
+ required=False,
404
+ label="Device",
405
+ )
406
+ source_interface = DynamicModelChoiceField(
407
+ queryset=Interface.objects.all(),
408
+ required=False,
409
+ label="Source Interface",
410
+ query_params={
411
+ "device": "$device",
412
+ },
413
+ )
414
+ source_ipaddress = DynamicModelChoiceField(
415
+ queryset=IPAddress.objects.all(),
416
+ required=False,
417
+ label="Source IP Address",
418
+ query_params={
419
+ "interfaces": "$source_interface",
420
+ },
421
+ )
422
+ tunnel_interface = DynamicModelChoiceField(
423
+ queryset=Interface.objects.all(),
424
+ required=False,
425
+ label="Tunnel Interface",
426
+ query_params={
427
+ "device": "$device",
428
+ "type": InterfaceTypeChoices.TYPE_TUNNEL,
429
+ },
430
+ help_text="Interface must be of type Tunnel",
431
+ )
432
+ vpn_profile = DynamicModelChoiceField(
433
+ queryset=models.VPNProfile.objects.all(),
434
+ required=False,
435
+ label="VPN Profile",
436
+ help_text="VPN Profile for the tunnel endpoint.",
437
+ )
438
+ protected_prefixes = DynamicModelMultipleChoiceField(
439
+ queryset=Prefix.objects.all(),
440
+ required=False,
441
+ label="Protected Prefixes",
442
+ help_text="Protected Prefixes behind the tunnel endpoint.",
443
+ )
444
+ protected_prefixes_dg = DynamicModelMultipleChoiceField(
445
+ queryset=DynamicGroup.objects.all(),
446
+ required=False,
447
+ label="Protected Prefixes Dynamic Group",
448
+ to_field_name="name",
449
+ help_text="Protected Prefixes behind the tunnel endpoint.",
450
+ )
451
+
452
+ class Meta:
453
+ """Meta attributes."""
454
+
455
+ model = models.VPNTunnelEndpoint
456
+ fields = "__all__"
457
+
458
+
459
+ class VPNTunnelEndpointBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm): # pylint: disable=too-many-ancestors
460
+ """VPNTunnelEndpoint bulk edit form."""
461
+
462
+ pk = forms.ModelMultipleChoiceField(
463
+ queryset=models.VPNTunnelEndpoint.objects.all(), widget=forms.MultipleHiddenInput
464
+ )
465
+ vpn_profile = DynamicModelChoiceField(
466
+ queryset=models.VPNProfile.objects.all(),
467
+ required=False,
468
+ label="VPN Profile",
469
+ help_text="VPN Profile for the tunnel endpoint.",
470
+ )
471
+
472
+ class Meta:
473
+ """Meta attributes."""
474
+
475
+ model = models.VPNTunnelEndpoint
476
+ nullable_fields = [
477
+ "vpn_profile",
478
+ ]
479
+
480
+
481
+ class VPNTunnelEndpointFilterForm(NautobotFilterForm, TenancyFilterForm): # pylint: disable=too-many-ancestors
482
+ """Filter form for VPNTunnelEndpoint."""
483
+
484
+ model = models.VPNTunnelEndpoint
485
+ q = forms.CharField(required=False, label="Search")
486
+ tags = TagFilterField(model)
@@ -0,0 +1,19 @@
1
+ from nautobot.core.apps import HomePageItem, HomePagePanel
2
+ from nautobot.vpn.models import VPN
3
+
4
+ layout = (
5
+ HomePagePanel(
6
+ name="VPN",
7
+ weight=550,
8
+ items=(
9
+ HomePageItem(
10
+ name="VPNs",
11
+ link="vpn:vpn_list",
12
+ model=VPN,
13
+ description="VPNs",
14
+ permissions=["vpn.view_vpn"],
15
+ weight=100,
16
+ ),
17
+ ),
18
+ ),
19
+ )