nautobot 3.0.0a2__py3-none-any.whl → 3.0.0rc1__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.
Files changed (659) hide show
  1. nautobot/apps/choices.py +4 -2
  2. nautobot/apps/filters.py +7 -9
  3. nautobot/apps/models.py +2 -2
  4. nautobot/apps/ui.py +13 -1
  5. nautobot/apps/utils.py +8 -0
  6. nautobot/circuits/filters.py +3 -2
  7. nautobot/circuits/navigation.py +3 -2
  8. nautobot/circuits/templates/circuits/circuit_create.html +3 -3
  9. nautobot/circuits/templates/circuits/circuittermination_create.html +9 -24
  10. nautobot/circuits/templates/circuits/inc/circuit_termination_cable_fragment.html +6 -6
  11. nautobot/circuits/templates/circuits/inc/speed_widget.html +12 -12
  12. nautobot/circuits/tests/integration/test_circuit.py +10 -13
  13. nautobot/circuits/tests/integration/test_circuits_bulk_operations.py +0 -3
  14. nautobot/circuits/views.py +6 -2
  15. nautobot/cloud/filters.py +1 -1
  16. nautobot/cloud/navigation.py +3 -2
  17. nautobot/core/api/schema.py +1 -1
  18. nautobot/core/api/serializers.py +6 -1
  19. nautobot/core/api/urls.py +2 -0
  20. nautobot/core/api/views.py +12 -0
  21. nautobot/core/apps/__init__.py +11 -10
  22. nautobot/core/celery/__init__.py +3 -5
  23. nautobot/core/checks.py +46 -0
  24. nautobot/core/choices.py +1 -1
  25. nautobot/core/cli/bootstrap_v3_to_v5.py +105 -13
  26. nautobot/core/cli/migrate_deprecated_templates.py +227 -0
  27. nautobot/core/constants.py +3 -0
  28. nautobot/core/context_processors.py +9 -1
  29. nautobot/core/filters.py +4 -0
  30. nautobot/core/forms/__init__.py +2 -0
  31. nautobot/core/forms/forms.py +1 -1
  32. nautobot/core/forms/widgets.py +21 -2
  33. nautobot/core/jobs/__init__.py +62 -3
  34. nautobot/core/jobs/groups.py +31 -1
  35. nautobot/core/management/commands/generate_test_data.py +28 -9
  36. nautobot/core/models/__init__.py +11 -0
  37. nautobot/core/models/generics.py +9 -1
  38. nautobot/core/models/tree_queries.py +10 -5
  39. nautobot/core/models/utils.py +1 -1
  40. nautobot/core/settings.py +35 -19
  41. nautobot/core/settings.yaml +17 -33
  42. nautobot/core/signals.py +12 -1
  43. nautobot/core/tables.py +13 -6
  44. nautobot/core/templates/40x.html +1 -1
  45. nautobot/core/templates/500.html +2 -2
  46. nautobot/core/templates/admin/base.html +1 -2
  47. nautobot/core/templates/admin/change_list.html +9 -12
  48. nautobot/core/templates/admin/config/config.html +12 -12
  49. nautobot/core/templates/admin/index.html +3 -3
  50. nautobot/core/templates/base_django.html +1 -2
  51. nautobot/core/templates/buttons/export.html +1 -1
  52. nautobot/core/templates/components/button/dropdown.html +5 -3
  53. nautobot/core/templates/components/panel/body_wrapper_generic_table.html +1 -1
  54. nautobot/core/templates/components/panel/header_extra_content_table.html +1 -1
  55. nautobot/core/templates/components/panel/panel.html +3 -3
  56. nautobot/core/templates/components/tab/content_wrapper.html +6 -7
  57. nautobot/core/templates/components/tab/label_wrapper_distinct_view.html +1 -1
  58. nautobot/core/templates/echarts/echarts.html +22 -9
  59. nautobot/core/templates/generic/object_bulk_add_component.html +2 -1
  60. nautobot/core/templates/generic/object_bulk_create.html +6 -5
  61. nautobot/core/templates/generic/object_bulk_delete.html +1 -1
  62. nautobot/core/templates/generic/object_bulk_destroy.html +3 -3
  63. nautobot/core/templates/generic/object_bulk_edit.html +1 -1
  64. nautobot/core/templates/generic/object_bulk_import.html +1 -1
  65. nautobot/core/templates/generic/object_bulk_remove.html +2 -2
  66. nautobot/core/templates/generic/object_bulk_update.html +5 -4
  67. nautobot/core/templates/generic/object_create.html +5 -4
  68. nautobot/core/templates/generic/object_delete.html +1 -1
  69. nautobot/core/templates/generic/object_detail.html +1 -1
  70. nautobot/core/templates/generic/object_edit.html +1 -1
  71. nautobot/core/templates/generic/object_import.html +2 -1
  72. nautobot/core/templates/generic/object_list.html +12 -4
  73. nautobot/core/templates/generic/object_notes.html +5 -3
  74. nautobot/core/templates/generic/object_retrieve.html +4 -5
  75. nautobot/core/templates/graphene/graphiql.html +7 -8
  76. nautobot/core/templates/home.html +1 -1
  77. nautobot/core/templates/import_success.html +2 -1
  78. nautobot/core/templates/inc/computed_fields/panel_data.html +1 -1
  79. nautobot/core/templates/inc/created_updated.html +7 -3
  80. nautobot/core/templates/inc/custom_fields/panel_data.html +1 -1
  81. nautobot/core/templates/inc/footer.html +3 -1
  82. nautobot/core/templates/inc/form_static_field.html +6 -0
  83. nautobot/core/templates/inc/header.html +11 -1
  84. nautobot/core/templates/inc/image_attachments.html +2 -1
  85. nautobot/core/templates/inc/media.html +14 -0
  86. nautobot/core/templates/inc/nav_menu.html +3 -9
  87. nautobot/core/templates/inc/object_details_advanced_panel.html +2 -2
  88. nautobot/core/templates/inc/search_panel.html +4 -4
  89. nautobot/core/templates/login.html +4 -2
  90. nautobot/core/templates/nautobot_config.py.j2 +6 -11
  91. nautobot/core/templates/redoc_ui.html +7 -0
  92. nautobot/core/templates/rest_framework/api.html +103 -2
  93. nautobot/core/templates/search.html +1 -1
  94. nautobot/core/templates/swagger_ui.html +17 -3
  95. nautobot/core/templates/system_jobs/import_objects.html +1 -2
  96. nautobot/core/templates/utilities/confirmation_form.html +2 -2
  97. nautobot/core/templates/utilities/obj_table.html +10 -2
  98. nautobot/core/templates/utilities/render_field.html +7 -7
  99. nautobot/core/templates/utilities/render_jinja2.html +2 -2
  100. nautobot/core/templates/utilities/templatetags/filter_form_drawer.html +37 -4
  101. nautobot/core/templates/utilities/theme_preview.html +19 -3
  102. nautobot/core/templates/widgets/number_input_with_choices.html +44 -0
  103. nautobot/core/templates/widgets/selectwithdisabled_option.html +3 -1
  104. nautobot/core/templatetags/helpers.py +76 -18
  105. nautobot/core/testing/api.py +68 -9
  106. nautobot/core/testing/filters.py +0 -23
  107. nautobot/core/testing/integration.py +41 -17
  108. nautobot/core/testing/mixins.py +2 -0
  109. nautobot/core/testing/utils.py +18 -4
  110. nautobot/core/testing/views.py +104 -13
  111. nautobot/core/tests/integration/test_app_home.py +34 -30
  112. nautobot/core/tests/integration/test_app_navbar.py +3 -0
  113. nautobot/core/tests/integration/test_filters.py +48 -11
  114. nautobot/core/tests/integration/test_theme.py +22 -21
  115. nautobot/core/tests/nautobot_config.py +3 -0
  116. nautobot/core/tests/nautobot_config_without_example_apps.py +4 -0
  117. nautobot/core/tests/runner.py +8 -1
  118. nautobot/core/tests/test_api.py +5 -3
  119. nautobot/core/tests/test_breadcrumbs.py +27 -28
  120. nautobot/core/tests/test_checks.py +28 -0
  121. nautobot/core/tests/test_cli.py +40 -0
  122. nautobot/core/tests/test_config.py +2 -1
  123. nautobot/core/tests/test_forms.py +55 -13
  124. nautobot/core/tests/test_jobs.py +144 -3
  125. nautobot/core/tests/test_nautobot_server.py +2 -0
  126. nautobot/core/tests/test_navigations.py +76 -1
  127. nautobot/core/tests/test_patch_social_django.py +42 -0
  128. nautobot/core/tests/test_renderers.py +59 -0
  129. nautobot/core/tests/test_settings_schema.py +1 -0
  130. nautobot/core/tests/test_tables.py +3 -1
  131. nautobot/core/tests/test_templatetags_helpers.py +62 -13
  132. nautobot/core/tests/test_templatetags_ui_framework.py +4 -4
  133. nautobot/core/tests/test_titles.py +0 -16
  134. nautobot/core/tests/test_tree_queries.py +14 -1
  135. nautobot/core/tests/test_ui.py +123 -4
  136. nautobot/core/tests/test_utils.py +72 -5
  137. nautobot/core/tests/test_views.py +159 -31
  138. nautobot/core/ui/breadcrumbs.py +70 -29
  139. nautobot/core/ui/bulk_buttons.py +1 -1
  140. nautobot/core/ui/choices.py +143 -27
  141. nautobot/core/ui/constants.py +76 -12
  142. nautobot/core/ui/echarts.py +15 -20
  143. nautobot/core/ui/object_detail.py +143 -55
  144. nautobot/core/ui/titles.py +3 -6
  145. nautobot/core/urls.py +20 -9
  146. nautobot/core/utils/cache.py +2 -1
  147. nautobot/core/utils/filtering.py +28 -18
  148. nautobot/core/utils/lookup.py +49 -8
  149. nautobot/core/utils/module_loading.py +21 -0
  150. nautobot/core/utils/patch_social_django.py +128 -0
  151. nautobot/core/views/__init__.py +38 -1
  152. nautobot/core/views/generic.py +3 -3
  153. nautobot/core/views/mixins.py +45 -22
  154. nautobot/core/views/renderers.py +4 -3
  155. nautobot/core/views/viewsets.py +2 -1
  156. nautobot/data_validation/apps.py +1 -5
  157. nautobot/data_validation/custom_validators.py +4 -4
  158. nautobot/data_validation/filters.py +1 -1
  159. nautobot/data_validation/forms.py +40 -0
  160. nautobot/data_validation/migrations/0001_initial.py +0 -7
  161. nautobot/data_validation/migrations/0002_data_migration_from_app.py +3 -14
  162. nautobot/data_validation/models.py +16 -7
  163. nautobot/data_validation/navigation.py +8 -1
  164. nautobot/data_validation/tables.py +12 -5
  165. nautobot/data_validation/templates/data_validation/datacompliance_tab.html +1 -0
  166. nautobot/data_validation/templates/data_validation/device_constraints.html +61 -0
  167. nautobot/data_validation/tests/__init__.py +2 -2
  168. nautobot/data_validation/tests/migrations/test_migrations.py +83 -3
  169. nautobot/data_validation/tests/test_data_compliance_rules.py +12 -7
  170. nautobot/data_validation/tests/test_filters.py +8 -6
  171. nautobot/data_validation/tests/test_models.py +15 -0
  172. nautobot/data_validation/tests/test_views.py +190 -32
  173. nautobot/data_validation/urls.py +2 -5
  174. nautobot/data_validation/views.py +73 -40
  175. nautobot/dcim/api/serializers.py +3 -13
  176. nautobot/dcim/apps.py +4 -0
  177. nautobot/dcim/choices.py +65 -0
  178. nautobot/dcim/constants.py +7 -0
  179. nautobot/dcim/custom_validators.py +84 -0
  180. nautobot/dcim/factory.py +1 -1
  181. nautobot/dcim/filter_mixins.py +353 -4
  182. nautobot/dcim/{filters/__init__.py → filters.py} +15 -36
  183. nautobot/dcim/forms.py +90 -4
  184. nautobot/dcim/migrations/0075_interface_duplex_interface_speed_and_more.py +32 -0
  185. nautobot/dcim/migrations/{0075_add_deviceclusterassignment.py → 0076_add_deviceclusterassignment.py} +1 -1
  186. nautobot/dcim/migrations/{0076_device_cluster_to_clusters_data_migration.py → 0077_device_cluster_to_clusters_data_migration.py} +1 -1
  187. nautobot/dcim/migrations/{0077_remove_device_cluster.py → 0078_remove_device_cluster.py} +1 -1
  188. nautobot/dcim/migrations/0079_remove_device_location_tenant_name_uniqueness.py +16 -0
  189. nautobot/dcim/migrations/0080_device_name_data_migration.py +59 -0
  190. nautobot/dcim/migrations/0081_alter_device_device_redundancy_group_priority_and_more.py +25 -0
  191. nautobot/dcim/models/device_component_templates.py +33 -1
  192. nautobot/dcim/models/device_components.py +98 -64
  193. nautobot/dcim/models/devices.py +30 -20
  194. nautobot/dcim/navigation.py +7 -6
  195. nautobot/dcim/tables/devices.py +18 -0
  196. nautobot/dcim/tables/devicetypes.py +8 -1
  197. nautobot/dcim/tables/racks.py +0 -2
  198. nautobot/dcim/tables/template_code.py +15 -15
  199. nautobot/dcim/templates/dcim/cable_connect.html +28 -112
  200. nautobot/dcim/templates/dcim/cable_trace.html +0 -4
  201. nautobot/dcim/templates/dcim/{cable_edit.html → cable_update.html} +1 -1
  202. nautobot/dcim/templates/dcim/consoleport.html +7 -6
  203. nautobot/dcim/templates/dcim/consoleserverport.html +7 -6
  204. nautobot/dcim/templates/dcim/device/config.html +2 -2
  205. nautobot/dcim/templates/dcim/device/lldp_neighbors.html +1 -1
  206. nautobot/dcim/templates/dcim/device/status.html +8 -8
  207. nautobot/dcim/templates/dcim/device.html +1 -1
  208. nautobot/dcim/templates/dcim/device_component_add.html +2 -2
  209. nautobot/dcim/templates/dcim/device_create.html +5 -3
  210. nautobot/dcim/templates/dcim/device_interface_delete.html +1 -1
  211. nautobot/dcim/templates/dcim/device_list.html +73 -10
  212. nautobot/dcim/templates/dcim/devicebay.html +1 -1
  213. nautobot/dcim/templates/dcim/devicebay_populate.html +2 -2
  214. nautobot/dcim/templates/dcim/devicetype_component_add.html +2 -2
  215. nautobot/dcim/templates/dcim/footer_convert_to_contact_or_team_record.html +14 -0
  216. nautobot/dcim/templates/dcim/frontport.html +10 -9
  217. nautobot/dcim/templates/dcim/inc/devicetype_component_table.html +1 -1
  218. nautobot/dcim/templates/dcim/inc/edit_form_softwareversion_js.html +2 -2
  219. nautobot/dcim/templates/dcim/inc/moduletype_component_table.html +1 -1
  220. nautobot/dcim/templates/dcim/inc/rack_elevation.html +1 -1
  221. nautobot/dcim/templates/dcim/interface.html +35 -7
  222. nautobot/dcim/templates/dcim/interface_bulk_delete.html +1 -1
  223. nautobot/dcim/templates/dcim/interface_edit.html +2 -0
  224. nautobot/dcim/templates/dcim/inventoryitem.html +1 -1
  225. nautobot/dcim/templates/dcim/inventoryitem_add.html +3 -1
  226. nautobot/dcim/templates/dcim/inventoryitem_bulk_delete.html +1 -1
  227. nautobot/dcim/templates/dcim/inventoryitem_edit.html +3 -1
  228. nautobot/dcim/templates/dcim/module/base.html +49 -9
  229. nautobot/dcim/templates/dcim/module_consoleports.html +1 -1
  230. nautobot/dcim/templates/dcim/module_consoleserverports.html +1 -1
  231. nautobot/dcim/templates/dcim/module_frontports.html +1 -1
  232. nautobot/dcim/templates/dcim/module_interfaces.html +1 -1
  233. nautobot/dcim/templates/dcim/module_list.html +57 -8
  234. nautobot/dcim/templates/dcim/module_modulebays.html +1 -1
  235. nautobot/dcim/templates/dcim/module_poweroutlets.html +1 -1
  236. nautobot/dcim/templates/dcim/module_powerports.html +1 -1
  237. nautobot/dcim/templates/dcim/module_rearports.html +1 -1
  238. nautobot/dcim/templates/dcim/modulefamily_retrieve.html +1 -1
  239. nautobot/dcim/templates/dcim/moduletype_list.html +2 -2
  240. nautobot/dcim/templates/dcim/moduletype_retrieve.html +49 -9
  241. nautobot/dcim/templates/dcim/platform_create.html +1 -1
  242. nautobot/dcim/templates/dcim/poweroutlet.html +1 -1
  243. nautobot/dcim/templates/dcim/powerport.html +6 -5
  244. nautobot/dcim/templates/dcim/rack_elevation_list.html +17 -5
  245. nautobot/dcim/templates/dcim/rack_retrieve.html +22 -15
  246. nautobot/dcim/templates/dcim/rearport.html +8 -7
  247. nautobot/dcim/templates/dcim/trace/cable.html +1 -1
  248. nautobot/dcim/templates/dcim/virtualchassis_add_member.html +16 -14
  249. nautobot/dcim/templates/dcim/virtualchassis_update.html +15 -7
  250. nautobot/dcim/tests/integration/test_controller.py +4 -6
  251. nautobot/dcim/tests/integration/test_controller_managed_device_group.py +1 -5
  252. nautobot/dcim/tests/integration/test_create_device.py +0 -2
  253. nautobot/dcim/tests/integration/test_device_bulk_operations.py +1 -3
  254. nautobot/dcim/tests/integration/test_fileinputpicker.py +6 -10
  255. nautobot/dcim/tests/integration/test_location_bulk_operations.py +0 -2
  256. nautobot/dcim/tests/integration/test_module_bay_position.py +3 -4
  257. nautobot/dcim/tests/test_api.py +194 -6
  258. nautobot/dcim/tests/test_custom_validators.py +229 -0
  259. nautobot/dcim/tests/test_filters.py +55 -7
  260. nautobot/dcim/tests/test_forms.py +110 -8
  261. nautobot/dcim/tests/test_graphql.py +44 -1
  262. nautobot/dcim/tests/test_models.py +328 -4
  263. nautobot/dcim/tests/test_tables.py +160 -0
  264. nautobot/dcim/tests/test_views.py +132 -29
  265. nautobot/dcim/urls.py +64 -21
  266. nautobot/dcim/utils.py +3 -3
  267. nautobot/dcim/views.py +777 -397
  268. nautobot/extras/api/views.py +60 -45
  269. nautobot/extras/choices.py +2 -13
  270. nautobot/extras/datasources/git.py +3 -1
  271. nautobot/extras/{filters/mixins.py → filter_mixins.py} +1 -1
  272. nautobot/extras/{filters/customfields.py → filter_mixins_customfields.py} +42 -6
  273. nautobot/extras/{filters/__init__.py → filters.py} +33 -48
  274. nautobot/extras/forms/forms.py +14 -15
  275. nautobot/extras/forms/mixins.py +0 -41
  276. nautobot/extras/jobs.py +2 -0
  277. nautobot/extras/jobs_ui.py +4 -3
  278. nautobot/extras/management/__init__.py +11 -0
  279. nautobot/extras/management/commands/refresh_dynamic_group_member_caches.py +4 -1
  280. nautobot/extras/migrations/0127_approval_workflow_models.py +6 -6
  281. nautobot/extras/migrations/0129_jobresult_debug_log_count_jobresult_error_log_count_and_more.py +37 -0
  282. nautobot/extras/migrations/0130_jobresult_generate_log_entry_counts.py +42 -0
  283. nautobot/extras/migrations/0131_configcontext_device_families.py +18 -0
  284. nautobot/extras/models/__init__.py +1 -2
  285. nautobot/extras/models/approvals.py +33 -14
  286. nautobot/extras/models/change_logging.py +4 -0
  287. nautobot/extras/models/contacts.py +2 -0
  288. nautobot/extras/models/groups.py +44 -5
  289. nautobot/extras/models/jobs.py +60 -4
  290. nautobot/extras/models/mixins.py +28 -0
  291. nautobot/extras/models/models.py +23 -2
  292. nautobot/extras/models/secrets.py +1 -0
  293. nautobot/extras/models/statuses.py +0 -15
  294. nautobot/extras/navigation.py +13 -9
  295. nautobot/extras/plugins/__init__.py +33 -55
  296. nautobot/extras/plugins/marketplace_manifest.yml +49 -1
  297. nautobot/extras/plugins/tables.py +3 -3
  298. nautobot/extras/plugins/urls.py +2 -21
  299. nautobot/extras/plugins/utils.py +1 -33
  300. nautobot/extras/plugins/views.py +0 -9
  301. nautobot/extras/querysets.py +8 -0
  302. nautobot/extras/signals.py +20 -19
  303. nautobot/extras/tables.py +64 -68
  304. nautobot/extras/templates/django_ajax_tables/ajax_wrapper.html +2 -0
  305. nautobot/extras/templates/extras/approval_dashboard.html +7 -5
  306. nautobot/extras/templates/extras/approvalworkflowdefinition_update.html +4 -2
  307. nautobot/extras/templates/extras/approvalworkflowstage_retrieve.html +20 -12
  308. nautobot/extras/templates/extras/configcontext_update.html +1 -0
  309. nautobot/extras/templates/extras/configcontextschema_validation.html +2 -2
  310. nautobot/extras/templates/extras/dynamicgroup_retrieve.html +11 -5
  311. nautobot/extras/templates/extras/dynamicgroup_update.html +1 -1
  312. nautobot/extras/templates/extras/gitrepository_result.html +0 -2
  313. nautobot/extras/templates/extras/inc/approval_buttons_column.html +20 -6
  314. nautobot/extras/templates/extras/inc/bulk_edit_overridable_field.html +8 -7
  315. nautobot/extras/templates/extras/inc/configcontext_format.html +10 -3
  316. nautobot/extras/templates/extras/inc/graphqlquery_execute.html +71 -0
  317. nautobot/extras/templates/extras/inc/job_tiles.html +15 -3
  318. nautobot/extras/templates/extras/inc/json_format.html +10 -3
  319. nautobot/extras/templates/extras/inc/overridable_field.html +13 -12
  320. nautobot/extras/templates/extras/job.html +29 -12
  321. nautobot/extras/templates/extras/job_bulk_edit.html +18 -0
  322. nautobot/extras/templates/extras/job_edit.html +52 -46
  323. nautobot/extras/templates/extras/job_list.html +29 -25
  324. nautobot/extras/templates/extras/marketplace.html +5 -9
  325. nautobot/extras/templates/extras/object_configcontext.html +1 -1
  326. nautobot/extras/templates/extras/object_dynamicgroups.html +2 -2
  327. nautobot/extras/templates/extras/objectchange_retrieve.html +19 -39
  328. nautobot/extras/templates/extras/plugin_detail.html +29 -24
  329. nautobot/extras/templates/extras/plugins_list.html +16 -26
  330. nautobot/extras/templates/extras/role_retrieve.html +64 -0
  331. nautobot/extras/templates/extras/scheduledjob.html +4 -2
  332. nautobot/extras/templates/extras/secret_create.html +1 -1
  333. nautobot/extras/templatetags/custom_links.py +12 -12
  334. nautobot/extras/templatetags/job_buttons.py +14 -12
  335. nautobot/extras/test_jobs/invalid_import.py +9 -0
  336. nautobot/extras/test_jobs/log_counts_by_level.py +23 -0
  337. nautobot/extras/test_jobs/missing_import.py +11 -0
  338. nautobot/extras/tests/integration/test_computedfields.py +8 -9
  339. nautobot/extras/tests/integration/test_configcontextschema.py +27 -26
  340. nautobot/extras/tests/integration/test_customfields.py +9 -10
  341. nautobot/extras/tests/integration/test_dynamicgroups.py +12 -9
  342. nautobot/extras/tests/integration/test_plugin_banner.py +3 -0
  343. nautobot/extras/tests/integration/test_plugins.py +18 -6
  344. nautobot/extras/tests/integration/test_relationships.py +0 -2
  345. nautobot/extras/tests/test_api.py +90 -18
  346. nautobot/extras/tests/test_approvals.py +38 -38
  347. nautobot/extras/tests/test_changelog.py +59 -5
  348. nautobot/extras/tests/test_customfields.py +22 -13
  349. nautobot/extras/tests/test_customfields_filters.py +479 -0
  350. nautobot/extras/tests/test_dynamicgroups.py +39 -1
  351. nautobot/extras/tests/test_filters.py +57 -22
  352. nautobot/extras/tests/test_forms.py +18 -21
  353. nautobot/extras/tests/test_jobs.py +25 -4
  354. nautobot/extras/tests/test_migrations.py +1 -0
  355. nautobot/extras/tests/test_models.py +51 -33
  356. nautobot/extras/tests/test_plugins.py +36 -10
  357. nautobot/extras/tests/test_utils.py +3 -4
  358. nautobot/extras/tests/test_views.py +52 -112
  359. nautobot/extras/urls.py +0 -14
  360. nautobot/extras/views.py +164 -71
  361. nautobot/ipam/factory.py +7 -0
  362. nautobot/ipam/filter_mixins.py +38 -0
  363. nautobot/ipam/filters.py +53 -38
  364. nautobot/ipam/formfields.py +1 -1
  365. nautobot/ipam/forms.py +6 -3
  366. nautobot/ipam/migrations/0030_ipam__namespaces.py +13 -0
  367. nautobot/ipam/migrations/0031_ipam___data_migrations.py +4 -1
  368. nautobot/ipam/migrations/0054_namespace_tenant.py +25 -0
  369. nautobot/ipam/models.py +29 -2
  370. nautobot/ipam/navigation.py +3 -2
  371. nautobot/ipam/signals.py +71 -0
  372. nautobot/ipam/tables.py +19 -6
  373. nautobot/ipam/templates/ipam/inc/toggle_available.html +10 -10
  374. nautobot/ipam/templates/ipam/inc/vlangroup_header.html +1 -0
  375. nautobot/ipam/templates/ipam/ipaddress.html +14 -0
  376. nautobot/ipam/templates/ipam/ipaddress_merge.html +3 -3
  377. nautobot/ipam/templates/ipam/ipaddresstointerface_retrieve.html +1 -0
  378. nautobot/ipam/templates/ipam/namespace_ip_addresses.html +1 -1
  379. nautobot/ipam/templates/ipam/namespace_prefixes.html +1 -1
  380. nautobot/ipam/templates/ipam/namespace_update.html +15 -0
  381. nautobot/ipam/templates/ipam/namespace_vrfs.html +1 -1
  382. nautobot/ipam/templates/ipam/prefix_delete.html +1 -1
  383. nautobot/ipam/templates/ipam/prefix_list.html +14 -13
  384. nautobot/ipam/templates/ipam/vlan_interfaces.html +1 -1
  385. nautobot/ipam/templates/ipam/vlan_vminterfaces.html +1 -1
  386. nautobot/ipam/tests/migration/test_migrations.py +89 -0
  387. nautobot/ipam/tests/test_api.py +13 -6
  388. nautobot/ipam/tests/test_filters.py +36 -1
  389. nautobot/ipam/tests/test_forms.py +1 -1
  390. nautobot/ipam/tests/test_models.py +44 -2
  391. nautobot/ipam/tests/test_tables.py +1 -2
  392. nautobot/ipam/tests/test_utils.py +1 -1
  393. nautobot/ipam/tests/test_views.py +13 -14
  394. nautobot/ipam/ui.py +0 -17
  395. nautobot/ipam/utils/migrations.py +16 -2
  396. nautobot/ipam/utils/testing.py +9 -3
  397. nautobot/ipam/views.py +53 -11
  398. nautobot/load_balancers/__init__.py +0 -0
  399. nautobot/load_balancers/api/__init__.py +1 -0
  400. nautobot/load_balancers/api/serializers.py +75 -0
  401. nautobot/load_balancers/api/urls.py +23 -0
  402. nautobot/load_balancers/api/views.py +61 -0
  403. nautobot/load_balancers/apps.py +17 -0
  404. nautobot/load_balancers/choices.py +167 -0
  405. nautobot/load_balancers/filters.py +225 -0
  406. nautobot/load_balancers/forms.py +532 -0
  407. nautobot/load_balancers/management/commands/__init__.py +0 -0
  408. nautobot/load_balancers/management/commands/generate_load_balancer_models_test_data.py +38 -0
  409. nautobot/load_balancers/migrations/0001_initial.py +465 -0
  410. nautobot/load_balancers/migrations/0002_create_default_statuses_pool_members.py +31 -0
  411. nautobot/load_balancers/migrations/__init__.py +0 -0
  412. nautobot/load_balancers/models.py +423 -0
  413. nautobot/load_balancers/navigation.py +80 -0
  414. nautobot/load_balancers/tables.py +255 -0
  415. nautobot/load_balancers/tests/__init__.py +474 -0
  416. nautobot/load_balancers/tests/test_api.py +353 -0
  417. nautobot/load_balancers/tests/test_filters.py +134 -0
  418. nautobot/load_balancers/tests/test_forms.py +266 -0
  419. nautobot/load_balancers/tests/test_models.py +195 -0
  420. nautobot/load_balancers/tests/test_views.py +229 -0
  421. nautobot/load_balancers/urls.py +17 -0
  422. nautobot/load_balancers/views.py +248 -0
  423. nautobot/project-static/dist/css/github-dark.min.css +10 -0
  424. nautobot/project-static/dist/css/github.min.css +10 -0
  425. nautobot/project-static/dist/css/nautobot.css +1 -11
  426. nautobot/project-static/dist/css/nautobot.css.map +1 -1
  427. nautobot/project-static/dist/js/libraries.js +1 -1
  428. nautobot/project-static/dist/js/libraries.js.map +1 -1
  429. nautobot/project-static/dist/js/nautobot.js +1 -1
  430. nautobot/project-static/dist/js/nautobot.js.map +1 -1
  431. nautobot/project-static/js/cabletrace.js +1 -1
  432. nautobot/project-static/js/forms.js +13 -0
  433. nautobot/project-static/js/interface_filtering.js +20 -16
  434. nautobot/project-static/nautobot-icons/battery-3.svg +3 -0
  435. nautobot/project-static/nautobot-icons/bus-globe.svg +3 -0
  436. nautobot/project-static/nautobot-icons/bus-shield-check.svg +3 -0
  437. nautobot/project-static/nautobot-icons/bus-shield.svg +3 -0
  438. nautobot/project-static/nautobot-icons/cloud.svg +1 -1
  439. nautobot/project-static/nautobot-icons/control-panel.svg +1 -1
  440. nautobot/project-static/nautobot-icons/device-lifecycle.svg +1 -1
  441. nautobot/project-static/nautobot-icons/elements.svg +1 -1
  442. nautobot/project-static/nautobot-icons/extensibility.svg +3 -0
  443. nautobot/project-static/nautobot-icons/hammer.svg +1 -1
  444. nautobot/project-static/nautobot-icons/organization.svg +3 -0
  445. nautobot/project-static/nautobot-icons/secrets.svg +1 -1
  446. nautobot/project-static/nautobot-icons/security.svg +3 -0
  447. nautobot/project-static/nautobot-icons/server.svg +1 -1
  448. nautobot/project-static/nautobot-icons/star-filled.svg +1 -1
  449. nautobot/project-static/nautobot-icons/star.svg +1 -1
  450. nautobot/tenancy/api/serializers.py +1 -0
  451. nautobot/tenancy/api/views.py +2 -1
  452. nautobot/tenancy/{filters/__init__.py → filters.py} +2 -10
  453. nautobot/tenancy/navigation.py +3 -1
  454. nautobot/tenancy/tests/test_filters.py +0 -2
  455. nautobot/tenancy/views.py +2 -1
  456. nautobot/ui/package-lock.json +87 -4
  457. nautobot/ui/package.json +2 -1
  458. nautobot/ui/src/js/collapse.js +3 -3
  459. nautobot/ui/src/js/nautobot.js +16 -1
  460. nautobot/ui/src/js/select2.js +53 -2
  461. nautobot/ui/src/scss/colors.scss +1 -1
  462. nautobot/ui/src/scss/nautobot.scss +112 -30
  463. nautobot/ui/webpack.config.js +13 -0
  464. nautobot/users/templates/users/preferences.html +11 -2
  465. nautobot/users/templates/users/profile.html +45 -12
  466. nautobot/users/templates/users/sessionkey_delete.html +1 -1
  467. nautobot/users/tests/test_api.py +4 -0
  468. nautobot/users/views.py +4 -2
  469. nautobot/virtualization/filters.py +6 -1
  470. nautobot/virtualization/models.py +1 -68
  471. nautobot/virtualization/navigation.py +3 -2
  472. nautobot/virtualization/templates/virtualization/virtual_machine_vminterface_delete.html +1 -1
  473. nautobot/virtualization/templates/virtualization/virtualmachine_list.html +2 -2
  474. nautobot/virtualization/templates/virtualization/virtualmachine_update.html +3 -1
  475. nautobot/virtualization/tests/test_api.py +3 -0
  476. nautobot/virtualization/tests/test_filters.py +10 -1
  477. nautobot/virtualization/tests/test_models.py +45 -4
  478. nautobot/virtualization/views.py +4 -1
  479. nautobot/vpn/__init__.py +0 -0
  480. nautobot/vpn/api/serializers.py +113 -0
  481. nautobot/vpn/api/urls.py +19 -0
  482. nautobot/vpn/api/views.py +70 -0
  483. nautobot/vpn/apps.py +8 -0
  484. nautobot/vpn/choices.py +171 -0
  485. nautobot/vpn/factory.py +219 -0
  486. nautobot/vpn/filters.py +234 -0
  487. nautobot/vpn/forms.py +487 -0
  488. nautobot/vpn/homepage.py +19 -0
  489. nautobot/vpn/migrations/0001_initial.py +541 -0
  490. nautobot/vpn/migrations/0002_populate_defaults.py +199 -0
  491. nautobot/vpn/migrations/__init__.py +0 -0
  492. nautobot/vpn/models.py +535 -0
  493. nautobot/vpn/navigation.py +98 -0
  494. nautobot/vpn/tables.py +383 -0
  495. nautobot/vpn/templates/vpn/vpnprofile_create.html +150 -0
  496. nautobot/vpn/tests/__init__.py +0 -0
  497. nautobot/vpn/tests/test_api.py +336 -0
  498. nautobot/vpn/tests/test_filters.py +139 -0
  499. nautobot/vpn/tests/test_forms.py +293 -0
  500. nautobot/vpn/tests/test_models.py +147 -0
  501. nautobot/vpn/tests/test_views.py +300 -0
  502. nautobot/vpn/urls.py +16 -0
  503. nautobot/vpn/views.py +495 -0
  504. nautobot/wireless/navigation.py +3 -2
  505. nautobot/wireless/tests/integration/test_radio_profile.py +1 -5
  506. nautobot/wireless/tests/test_api.py +1 -1
  507. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/METADATA +15 -15
  508. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/RECORD +514 -572
  509. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/entry_points.txt +1 -0
  510. nautobot/circuits/templates/circuits/circuit.html +0 -2
  511. nautobot/circuits/templates/circuits/circuit_edit.html +0 -2
  512. nautobot/circuits/templates/circuits/circuit_retrieve.html +0 -2
  513. nautobot/circuits/templates/circuits/circuit_update.html +0 -1
  514. nautobot/circuits/templates/circuits/circuittermination.html +0 -2
  515. nautobot/circuits/templates/circuits/circuittermination_edit.html +0 -2
  516. nautobot/circuits/templates/circuits/circuittermination_retrieve.html +0 -2
  517. nautobot/circuits/templates/circuits/circuittermination_update.html +0 -1
  518. nautobot/circuits/templates/circuits/circuittype.html +0 -2
  519. nautobot/circuits/templates/circuits/circuittype_retrieve.html +0 -2
  520. nautobot/circuits/templates/circuits/inc/circuit_termination.html +0 -85
  521. nautobot/circuits/templates/circuits/provider.html +0 -2
  522. nautobot/circuits/templates/circuits/provider_edit.html +0 -2
  523. nautobot/circuits/templates/circuits/provider_retrieve.html +0 -1
  524. nautobot/circuits/templates/circuits/provider_update.html +0 -1
  525. nautobot/circuits/templates/circuits/providernetwork.html +0 -2
  526. nautobot/circuits/templates/circuits/providernetwork_retrieve.html +0 -2
  527. nautobot/cloud/templates/cloud/cloudaccount_retrieve.html +0 -2
  528. nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +0 -2
  529. nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +0 -2
  530. nautobot/cloud/templates/cloud/cloudservice_retrieve.html +0 -2
  531. nautobot/core/templates/buttons/import.html +0 -9
  532. nautobot/data_validation/template_content.py +0 -42
  533. nautobot/data_validation/templates/data_validation/datacompliance_retrieve.html +0 -1
  534. nautobot/dcim/filters/mixins.py +0 -354
  535. nautobot/dcim/templates/dcim/controller/base.html +0 -2
  536. nautobot/dcim/templates/dcim/controller_retrieve.html +0 -2
  537. nautobot/dcim/templates/dcim/controller_wirelessnetworks.html +0 -2
  538. nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +0 -2
  539. nautobot/dcim/templates/dcim/device/base.html +0 -2
  540. nautobot/dcim/templates/dcim/device/consoleports.html +0 -2
  541. nautobot/dcim/templates/dcim/device/consoleserverports.html +0 -2
  542. nautobot/dcim/templates/dcim/device/devicebays.html +0 -2
  543. nautobot/dcim/templates/dcim/device/frontports.html +0 -2
  544. nautobot/dcim/templates/dcim/device/interfaces.html +0 -2
  545. nautobot/dcim/templates/dcim/device/inventory.html +0 -2
  546. nautobot/dcim/templates/dcim/device/modulebays.html +0 -2
  547. nautobot/dcim/templates/dcim/device/poweroutlets.html +0 -2
  548. nautobot/dcim/templates/dcim/device/powerports.html +0 -2
  549. nautobot/dcim/templates/dcim/device/rearports.html +0 -2
  550. nautobot/dcim/templates/dcim/device/wireless.html +0 -2
  551. nautobot/dcim/templates/dcim/device_component.html +0 -2
  552. nautobot/dcim/templates/dcim/device_edit.html +0 -2
  553. nautobot/dcim/templates/dcim/devicefamily_retrieve.html +0 -2
  554. nautobot/dcim/templates/dcim/deviceredundancygroup_retrieve.html +0 -2
  555. nautobot/dcim/templates/dcim/devicetype.html +0 -2
  556. nautobot/dcim/templates/dcim/devicetype_edit.html +0 -2
  557. nautobot/dcim/templates/dcim/devicetype_retrieve.html +0 -2
  558. nautobot/dcim/templates/dcim/inc/device_napalm_tabs.html +0 -1
  559. nautobot/dcim/templates/dcim/interfaceredundancygroup_retrieve.html +0 -2
  560. nautobot/dcim/templates/dcim/location.html +0 -2
  561. nautobot/dcim/templates/dcim/location_edit.html +0 -2
  562. nautobot/dcim/templates/dcim/location_retrieve.html +0 -243
  563. nautobot/dcim/templates/dcim/locationtype.html +0 -2
  564. nautobot/dcim/templates/dcim/locationtype_retrieve.html +0 -2
  565. nautobot/dcim/templates/dcim/manufacturer.html +0 -2
  566. nautobot/dcim/templates/dcim/modulebay_retrieve.html +0 -1
  567. nautobot/dcim/templates/dcim/platform.html +0 -2
  568. nautobot/dcim/templates/dcim/powerfeed.html +0 -2
  569. nautobot/dcim/templates/dcim/powerfeed_retrieve.html +0 -2
  570. nautobot/dcim/templates/dcim/powerpanel.html +0 -2
  571. nautobot/dcim/templates/dcim/powerpanel_edit.html +0 -2
  572. nautobot/dcim/templates/dcim/powerpanel_retrieve.html +0 -2
  573. nautobot/dcim/templates/dcim/rack.html +0 -2
  574. nautobot/dcim/templates/dcim/rack_edit.html +0 -2
  575. nautobot/dcim/templates/dcim/rackgroup.html +0 -2
  576. nautobot/dcim/templates/dcim/rackreservation.html +0 -2
  577. nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +0 -2
  578. nautobot/dcim/templates/dcim/softwareversion_retrieve.html +0 -2
  579. nautobot/dcim/templates/dcim/virtualchassis.html +0 -2
  580. nautobot/dcim/templates/dcim/virtualchassis_add.html +0 -2
  581. nautobot/dcim/templates/dcim/virtualchassis_edit.html +0 -2
  582. nautobot/dcim/templates/dcim/virtualchassis_retrieve.html +0 -2
  583. nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +0 -2
  584. nautobot/dcim/ui.py +0 -29
  585. nautobot/extras/templates/extras/computedfield.html +0 -2
  586. nautobot/extras/templates/extras/computedfield_retrieve.html +0 -2
  587. nautobot/extras/templates/extras/configcontext.html +0 -2
  588. nautobot/extras/templates/extras/configcontext_edit.html +0 -2
  589. nautobot/extras/templates/extras/configcontext_retrieve.html +0 -2
  590. nautobot/extras/templates/extras/configcontextschema.html +0 -2
  591. nautobot/extras/templates/extras/configcontextschema_edit.html +0 -2
  592. nautobot/extras/templates/extras/contact_retrieve.html +0 -2
  593. nautobot/extras/templates/extras/customfield.html +0 -2
  594. nautobot/extras/templates/extras/customfield_edit.html +0 -2
  595. nautobot/extras/templates/extras/customfield_retrieve.html +0 -2
  596. nautobot/extras/templates/extras/customlink.html +0 -2
  597. nautobot/extras/templates/extras/dynamicgroup.html +0 -2
  598. nautobot/extras/templates/extras/dynamicgroup_edit.html +0 -2
  599. nautobot/extras/templates/extras/exporttemplate.html +0 -2
  600. nautobot/extras/templates/extras/gitrepository.html +0 -2
  601. nautobot/extras/templates/extras/gitrepository_object_edit.html +0 -2
  602. nautobot/extras/templates/extras/graphqlquery.html +0 -2
  603. nautobot/extras/templates/extras/graphqlquery_list.html +0 -1
  604. nautobot/extras/templates/extras/graphqlquery_retrieve.html +0 -97
  605. nautobot/extras/templates/extras/job_detail.html +0 -2
  606. nautobot/extras/templates/extras/jobbutton_retrieve.html +0 -2
  607. nautobot/extras/templates/extras/jobhook.html +0 -2
  608. nautobot/extras/templates/extras/jobqueue_retrieve.html +0 -2
  609. nautobot/extras/templates/extras/jobresult.html +0 -2
  610. nautobot/extras/templates/extras/metadatatype_retrieve.html +0 -2
  611. nautobot/extras/templates/extras/note.html +0 -2
  612. nautobot/extras/templates/extras/note_retrieve.html +0 -1
  613. nautobot/extras/templates/extras/object_changelog.html +0 -2
  614. nautobot/extras/templates/extras/object_notes.html +0 -2
  615. nautobot/extras/templates/extras/objectchange.html +0 -2
  616. nautobot/extras/templates/extras/objectchange_list.html +0 -3
  617. nautobot/extras/templates/extras/relationship.html +0 -1
  618. nautobot/extras/templates/extras/secret.html +0 -1
  619. nautobot/extras/templates/extras/secret_edit.html +0 -1
  620. nautobot/extras/templates/extras/secretsgroup.html +0 -2
  621. nautobot/extras/templates/extras/secretsgroup_edit.html +0 -2
  622. nautobot/extras/templates/extras/secretsgroup_retrieve.html +0 -2
  623. nautobot/extras/templates/extras/status.html +0 -2
  624. nautobot/extras/templates/extras/tag.html +0 -2
  625. nautobot/extras/templates/extras/tag_edit.html +0 -2
  626. nautobot/extras/templates/extras/tag_retrieve.html +0 -2
  627. nautobot/extras/templates/extras/team_retrieve.html +0 -2
  628. nautobot/ipam/templates/ipam/inc/prefix_header_extra_content_table.html +0 -4
  629. nautobot/ipam/templates/ipam/namespace_retrieve.html +0 -1
  630. nautobot/ipam/templates/ipam/prefix.html +0 -2
  631. nautobot/ipam/templates/ipam/prefix_edit.html +0 -1
  632. nautobot/ipam/templates/ipam/prefix_retrieve.html +0 -2
  633. nautobot/ipam/templates/ipam/rir.html +0 -2
  634. nautobot/ipam/templates/ipam/routetarget.html +0 -1
  635. nautobot/ipam/templates/ipam/service.html +0 -2
  636. nautobot/ipam/templates/ipam/service_edit.html +0 -2
  637. nautobot/ipam/templates/ipam/service_retrieve.html +0 -2
  638. nautobot/ipam/templates/ipam/vlan.html +0 -2
  639. nautobot/ipam/templates/ipam/vlan_edit.html +0 -2
  640. nautobot/ipam/templates/ipam/vlan_retrieve.html +0 -2
  641. nautobot/ipam/templates/ipam/vlangroup.html +0 -2
  642. nautobot/ipam/templates/ipam/vrf.html +0 -1
  643. nautobot/tenancy/templates/tenancy/tenant.html +0 -2
  644. nautobot/tenancy/templates/tenancy/tenant_edit.html +0 -2
  645. nautobot/tenancy/templates/tenancy/tenantgroup.html +0 -2
  646. nautobot/tenancy/templates/tenancy/tenantgroup_retrieve.html +0 -1
  647. nautobot/virtualization/templates/virtualization/clustergroup.html +0 -2
  648. nautobot/virtualization/templates/virtualization/clustertype.html +0 -2
  649. nautobot/virtualization/templates/virtualization/virtualmachine.html +0 -2
  650. nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +0 -2
  651. nautobot/virtualization/templates/virtualization/virtualmachine_retrieve.html +0 -2
  652. nautobot/wireless/templates/wireless/radioprofile_retrieve.html +0 -2
  653. nautobot/wireless/templates/wireless/supporteddatarate_retrieve.html +0 -2
  654. nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +0 -2
  655. /nautobot/dcim/templates/dcim/{cable.html → cable_retrieve.html} +0 -0
  656. /nautobot/tenancy/{filters/mixins.py → filter_mixins.py} +0 -0
  657. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/LICENSE.txt +0 -0
  658. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/NOTICE +0 -0
  659. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/WHEEL +0 -0
@@ -2,6 +2,7 @@
2
2
 
3
3
  import path from 'node:path';
4
4
  import autoprefixer from 'autoprefixer';
5
+ import CopyPlugin from 'copy-webpack-plugin';
5
6
  import miniCssExtractPlugin from 'mini-css-extract-plugin'
6
7
 
7
8
  const __dirname = import.meta.dirname;
@@ -24,6 +25,18 @@ export default [
24
25
  }
25
26
  },
26
27
  plugins: [
28
+ new CopyPlugin({
29
+ patterns: [
30
+ {
31
+ from: path.resolve(__dirname, 'node_modules', 'highlight.js', 'styles', 'github.min.css'),
32
+ to: path.resolve(__dirname, '..', 'project-static', 'dist', 'css'),
33
+ },
34
+ {
35
+ from: path.resolve(__dirname, 'node_modules', 'highlight.js', 'styles', 'github-dark.min.css'),
36
+ to: path.resolve(__dirname, '..', 'project-static', 'dist', 'css'),
37
+ },
38
+ ],
39
+ }),
27
40
  new miniCssExtractPlugin(
28
41
  {
29
42
  filename: 'css/[name].css'
@@ -13,7 +13,11 @@
13
13
  <table class="table table-striped">
14
14
  <thead>
15
15
  <tr>
16
- <th><input type="checkbox" class="toggle" title="Toggle all"></th>
16
+ <th>
17
+ <input class="form-check-input nb-form-check-input-sm mt-2 toggle"
18
+ title="Toggle all"
19
+ type="checkbox">
20
+ </th>
17
21
  <th>Preference</th>
18
22
  <th>Value</th>
19
23
  </tr>
@@ -21,7 +25,12 @@
21
25
  <tbody>
22
26
  {% for key, value in preferences.items %}
23
27
  <tr>
24
- <td class="nb-w-0"><input type="checkbox" name="pk" value="{{ key }}"></td>
28
+ <td class="nb-w-0">
29
+ <input class="form-check-input nb-form-check-input-sm mt-2"
30
+ name="pk"
31
+ type="checkbox"
32
+ value="{{ key }}">
33
+ </td>
25
34
  <td><samp>{{ key }}</samp></td>
26
35
  <td><samp>{{ value }}</samp></td>
27
36
  </tr>
@@ -2,16 +2,49 @@
2
2
  {% load helpers %}
3
3
 
4
4
  {% block usercontent %}
5
- <small class="text-secondary">User login</small>
6
- <h5>{{ request.user.username }}</h5>
7
- <small class="text-secondary">Full name</small>
8
- <h5>{{ request.user.first_name }} {{ request.user.last_name }}</h5>
9
- <small class="text-secondary">Email</small>
10
- <h5>{{ request.user.email }}</h5>
11
- <small class="text-secondary">Registered</small>
12
- <h5>{{ request.user.date_joined }}</h5>
13
- <small class="text-secondary">Groups</small>
14
- <h5>{{ request.user.groups.all|join:', ' }}</h5>
15
- <small class="text-secondary">Admin access</small>
16
- <h5>{{ request.user.is_staff|yesno|capfirst }}</h5>
5
+ <div class="row align-content-start flex-fill">
6
+ <div class="col-md-8 offset-md-2">
7
+ <div class="card">
8
+ <div class="card-header">
9
+ <strong>User Profile</strong>
10
+ </div>
11
+ <div class="collapse show">
12
+ <table class="table table-hover attr-table">
13
+ <tr>
14
+ <td>User login</td>
15
+ <td>{{ request.user.username }}</td>
16
+ </tr>
17
+ <tr>
18
+ <td>Full name</td>
19
+ {% if request.user.first_name or request.user.last_name %}
20
+ <td>{{ request.user.first_name }} {{ request.user.last_name }}</td>
21
+ {% else %}
22
+ <td>{{ None|placeholder }}</td>
23
+ {% endif %}
24
+ </tr>
25
+ <tr>
26
+ <td>Email</td>
27
+ <td>{{ request.user.email|hyperlinked_email }}</td>
28
+ </tr>
29
+ <tr>
30
+ <td>Registered</td>
31
+ <td>{{ request.user.date_joined|date:settings.SHORT_DATETIME_FORMAT }}</td>
32
+ </tr>
33
+ <tr>
34
+ <td>Groups</td>
35
+ <td>{{ request.user.groups.all|join:', '|placeholder }}</td>
36
+ </tr>
37
+ <tr>
38
+ <td>Admin access</td>
39
+ <td>{{ request.user.is_staff|render_boolean }}</td>
40
+ </tr>
41
+ <tr>
42
+ <td>Superuser access</td>
43
+ <td>{{ request.user.is_superuser|render_boolean }}</td>
44
+ </tr>
45
+ </table>
46
+ </div>
47
+ </div>
48
+ </div>
49
+ </div>
17
50
  {% endblock %}
@@ -1,4 +1,4 @@
1
- {% extends 'generic/object_delete.html' %}
1
+ {% extends 'generic/object_destroy.html' %}
2
2
 
3
3
  {% block message %}
4
4
  <p>Are you sure you want to delete your session key?</p>
@@ -348,6 +348,10 @@ class TokenTest(APIViewTestCases.APIViewTestCase):
348
348
 
349
349
  class ObjectPermissionTest(APIViewTestCases.APIViewTestCase):
350
350
  model = ObjectPermission
351
+ validation_excluded_fields = [
352
+ "groups", # M2M field, excluded by default
353
+ "users", # M2M field, excluded by default
354
+ ]
351
355
 
352
356
  @classmethod
353
357
  def setUpTestData(cls):
nautobot/users/views.py CHANGED
@@ -64,6 +64,7 @@ class LoginView(View):
64
64
  self.template_name,
65
65
  {
66
66
  "form": form,
67
+ "title": "Login",
67
68
  },
68
69
  )
69
70
 
@@ -91,6 +92,7 @@ class LoginView(View):
91
92
  self.template_name,
92
93
  {
93
94
  "form": form,
95
+ "title": "Login",
94
96
  },
95
97
  )
96
98
 
@@ -402,7 +404,7 @@ class TokenDeleteView(GenericView):
402
404
 
403
405
  return render(
404
406
  request,
405
- "generic/object_delete.html",
407
+ "generic/object_destroy.html",
406
408
  {
407
409
  "obj": token,
408
410
  "obj_type": token._meta.verbose_name,
@@ -421,7 +423,7 @@ class TokenDeleteView(GenericView):
421
423
 
422
424
  return render(
423
425
  request,
424
- "generic/object_delete.html",
426
+ "generic/object_destroy.html",
425
427
  {
426
428
  "obj": token,
427
429
  "obj_type": token._meta.verbose_name,
@@ -22,7 +22,7 @@ from nautobot.extras.filters import (
22
22
  RoleModelFilterSetMixin,
23
23
  StatusModelFilterSetMixin,
24
24
  )
25
- from nautobot.ipam.models import IPAddress, Service, VLAN
25
+ from nautobot.ipam.models import IPAddress, Service, VLAN, VRF
26
26
  from nautobot.tenancy.filters import TenancyModelFilterSetMixin
27
27
 
28
28
  from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
@@ -224,6 +224,11 @@ class VirtualMachineFilterSet(
224
224
  distinct=True,
225
225
  )
226
226
  has_ip_addresses = RelatedMembershipBooleanFilter(field_name="interfaces__ip_addresses", label="Has IP addresses")
227
+ vrfs = NaturalKeyOrPKMultipleChoiceFilter(
228
+ queryset=VRF.objects.all(),
229
+ to_field_name="rd",
230
+ label="VRFs (ID or RD)",
231
+ )
227
232
 
228
233
  def filter_ip_addresses(self, queryset, name, value):
229
234
  pk_values = set(item for item in value if is_uuid(item))
@@ -1,6 +1,6 @@
1
1
  from django.contrib.contenttypes.models import ContentType
2
2
  from django.core.exceptions import ValidationError
3
- from django.db import models, transaction
3
+ from django.db import models
4
4
 
5
5
  from nautobot.core.constants import CHARFIELD_MAX_LENGTH
6
6
  from nautobot.core.models import BaseManager
@@ -382,73 +382,6 @@ class VMInterface(PrimaryModel, BaseInterface):
382
382
 
383
383
  return super().to_objectchange(action, related_object=virtual_machine, **kwargs)
384
384
 
385
- def add_ip_addresses(
386
- self,
387
- ip_addresses,
388
- is_source=False,
389
- is_destination=False,
390
- is_default=False,
391
- is_preferred=False,
392
- is_primary=False,
393
- is_secondary=False,
394
- is_standby=False,
395
- ):
396
- """Add one or more IPAddress instances to this interface's `ip_addresses` many-to-many relationship.
397
-
398
- Args:
399
- ip_addresses (:obj:`list` or `IPAddress`): Instance of `nautobot.ipam.models.IPAddress` or list of `IPAddress` instances.
400
- is_source (bool, optional): Is source address. Defaults to False.
401
- is_destination (bool, optional): Is destination address. Defaults to False.
402
- is_default (bool, optional): Is default address. Defaults to False.
403
- is_preferred (bool, optional): Is preferred address. Defaults to False.
404
- is_primary (bool, optional): Is primary address. Defaults to False.
405
- is_secondary (bool, optional): Is secondary address. Defaults to False.
406
- is_standby (bool, optional): Is standby address. Defaults to False.
407
-
408
- Returns:
409
- Number of instances added.
410
- """
411
- if not isinstance(ip_addresses, (tuple, list)):
412
- ip_addresses = [ip_addresses]
413
- with transaction.atomic():
414
- for ip in ip_addresses:
415
- instance = self.ip_addresses.through(
416
- ip_address=ip,
417
- vm_interface=self,
418
- is_source=is_source,
419
- is_destination=is_destination,
420
- is_default=is_default,
421
- is_preferred=is_preferred,
422
- is_primary=is_primary,
423
- is_secondary=is_secondary,
424
- is_standby=is_standby,
425
- )
426
- instance.validated_save()
427
- return len(ip_addresses)
428
-
429
- add_ip_addresses.alters_data = True
430
-
431
- def remove_ip_addresses(self, ip_addresses):
432
- """Remove one or more IPAddress instances from this interface's `ip_addresses` many-to-many relationship.
433
-
434
- Args:
435
- ip_addresses (:obj:`list` or `IPAddress`): Instance of `nautobot.ipam.models.IPAddress` or list of `IPAddress` instances.
436
-
437
- Returns:
438
- Number of instances removed.
439
- """
440
- count = 0
441
- if not isinstance(ip_addresses, (tuple, list)):
442
- ip_addresses = [ip_addresses]
443
- with transaction.atomic():
444
- for ip in ip_addresses:
445
- qs = self.ip_addresses.through.objects.filter(ip_address=ip, vm_interface=self)
446
- deleted_count, _ = qs.delete()
447
- count += deleted_count
448
- return count
449
-
450
- remove_ip_addresses.alters_data = True
451
-
452
385
  @property
453
386
  def parent(self):
454
387
  return self.virtual_machine
@@ -4,12 +4,13 @@ from nautobot.core.apps import (
4
4
  NavMenuItem,
5
5
  NavMenuTab,
6
6
  )
7
+ from nautobot.core.ui.choices import NavigationIconChoices, NavigationWeightChoices
7
8
 
8
9
  menu_items = (
9
10
  NavMenuTab(
10
11
  name="Virtualization",
11
- icon="cloud-upload",
12
- weight=400,
12
+ icon=NavigationIconChoices.VIRTUALIZATION,
13
+ weight=NavigationWeightChoices.VIRTUALIZATION,
13
14
  groups=(
14
15
  NavMenuGroup(
15
16
  name="Virtual Machines",
@@ -1,3 +1,3 @@
1
- {% extends 'generic/object_delete.html' %}
1
+ {% extends 'generic/object_destroy.html' %}
2
2
 
3
3
  {% block message_extra %}This would also delete any/all child VMInterfaces of this VMInterface.{% endblock %}
@@ -2,12 +2,12 @@
2
2
 
3
3
  {% block bulk_buttons %}
4
4
  {% if perms.virtualization.change_virtualmachine %}
5
- <div class="btn-group">
5
+ <div class="dropdown d-inline-flex">
6
6
  <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
7
7
  <span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add Components <span class="mdi mdi-chevron-down"></span>
8
8
  </button>
9
9
  <ul class="dropdown-menu">
10
- {% if perms.virtualization.add_vminterface %}<li><a href="{% url 'virtualization:virtualmachine_bulk_add_vminterface' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction">Interfaces</a></li>{% endif %}
10
+ {% if perms.virtualization.add_vminterface %}<li><a href="{% url 'virtualization:virtualmachine_bulk_add_vminterface' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="dropdown-item formaction">Interfaces</a></li>{% endif %}
11
11
  </ul>
12
12
  </div>
13
13
  {% endif %}
@@ -31,7 +31,9 @@
31
31
  {% render_field form.primary_ip4 %}
32
32
  {% render_field form.primary_ip6 %}
33
33
  {% render_field form.software_version %}
34
- <div class="mb-10 d-flex justify-content-center" id="software_version_image_container" style="display:none">
34
+ <div class="mb-10 d-flex justify-content-center"
35
+ id="software_version_image_container"
36
+ style="display:none !important">{# !important is required to override d-flex #}
35
37
  <div class="col-lg-3"></div>
36
38
  <div class="col-lg-9">
37
39
  <span class="form-text">
@@ -281,6 +281,9 @@ class VMInterfaceTest(APIViewTestCases.APIViewTestCase):
281
281
  "description": "New description",
282
282
  }
283
283
  choices_fields = ["mode"]
284
+ validation_excluded_fields = [
285
+ "tagged_vlans", # M2M field, excluded by default
286
+ ]
284
287
 
285
288
  @classmethod
286
289
  def setUpTestData(cls):
@@ -3,7 +3,7 @@ from nautobot.dcim.choices import InterfaceModeChoices
3
3
  from nautobot.dcim.models import Device, DeviceType, Location, LocationType, Manufacturer, Platform, SoftwareVersion
4
4
  from nautobot.extras.models import Role, Status, Tag
5
5
  from nautobot.ipam.choices import ServiceProtocolChoices
6
- from nautobot.ipam.models import IPAddress, Namespace, Prefix, Service, VLAN
6
+ from nautobot.ipam.models import IPAddress, Namespace, Prefix, Service, VLAN, VRF, VRFDeviceAssignment
7
7
  from nautobot.tenancy.models import Tenant
8
8
  from nautobot.virtualization.filters import (
9
9
  ClusterFilterSet,
@@ -238,6 +238,8 @@ class VirtualMachineTestCase(FilterTestCases.FilterTestCase, FilterTestCases.Ten
238
238
  ("status", "status__id"),
239
239
  ("status", "status__name"),
240
240
  ("vcpus",),
241
+ ("vrfs", "vrfs__id"),
242
+ ("vrfs", "vrfs__rd"),
241
243
  )
242
244
 
243
245
  @classmethod
@@ -446,6 +448,13 @@ class VirtualMachineTestCase(FilterTestCases.FilterTestCase, FilterTestCases.Ten
446
448
  vms[0].tags.set(Tag.objects.get_for_model(VirtualMachine))
447
449
  vms[1].tags.set(Tag.objects.get_for_model(VirtualMachine)[:3])
448
450
 
451
+ vrfs = (
452
+ VRF.objects.create(name="VRF 1", rd="1:1"),
453
+ VRF.objects.create(name="VRF 2", rd="1:2"),
454
+ )
455
+ VRFDeviceAssignment.objects.create(virtual_machine=vms[0], vrf=vrfs[0])
456
+ VRFDeviceAssignment.objects.create(virtual_machine=vms[1], vrf=vrfs[1])
457
+
449
458
  def test_filters_generic(self):
450
459
  # Assign more than 2 different software versions to VirtualMachine before we test generic filters
451
460
  software_versions = list(SoftwareVersion.objects.all())
@@ -145,6 +145,7 @@ class VMInterfaceTestCase(TestCase): # TODO: change to BaseModelTestCase
145
145
  name="Int1", virtual_machine=self.virtualmachine, status=self.int_status
146
146
  )
147
147
  ips = list(IPAddress.objects.all()[:10])
148
+ self.assertEqual(len(ips), 10)
148
149
 
149
150
  # baseline (no vm_interface to ip address relationships exists)
150
151
  self.assertFalse(IPAddressToInterface.objects.filter(vm_interface=vm_interface).exists())
@@ -154,6 +155,11 @@ class VMInterfaceTestCase(TestCase): # TODO: change to BaseModelTestCase
154
155
  self.assertEqual(count, 1)
155
156
  self.assertEqual(IPAddressToInterface.objects.filter(ip_address=ips[-1], vm_interface=vm_interface).count(), 1)
156
157
 
158
+ # add a single instance which is already there
159
+ count = vm_interface.add_ip_addresses(ips[-1])
160
+ self.assertEqual(count, 0)
161
+ self.assertEqual(IPAddressToInterface.objects.filter(ip_address=ips[-1], vm_interface=vm_interface).count(), 1)
162
+
157
163
  # add multiple instances
158
164
  count = vm_interface.add_ip_addresses(ips[:5])
159
165
  self.assertEqual(count, 5)
@@ -161,12 +167,27 @@ class VMInterfaceTestCase(TestCase): # TODO: change to BaseModelTestCase
161
167
  for ip in ips[:5]:
162
168
  self.assertEqual(IPAddressToInterface.objects.filter(ip_address=ip, vm_interface=vm_interface).count(), 1)
163
169
 
170
+ # add multiple instances all of which are already there
171
+ count = vm_interface.add_ip_addresses(ips[:5])
172
+ self.assertEqual(count, 0)
173
+ self.assertEqual(IPAddressToInterface.objects.filter(vm_interface=vm_interface).count(), 6)
174
+ for ip in ips[:5]:
175
+ self.assertEqual(IPAddressToInterface.objects.filter(ip_address=ip, vm_interface=vm_interface).count(), 1)
176
+
177
+ # add multiple IPs some of which are there
178
+ count = vm_interface.add_ip_addresses(ips[3:7])
179
+ self.assertEqual(count, 2)
180
+ self.assertEqual(IPAddressToInterface.objects.filter(vm_interface=vm_interface).count(), 8)
181
+ for ip in ips[3:7]:
182
+ self.assertEqual(IPAddressToInterface.objects.filter(ip_address=ip, vm_interface=vm_interface).count(), 1)
183
+
164
184
  def test_remove_ip_addresses(self):
165
185
  """Test the `remove_ip_addresses` helper method on `VMInterface`"""
166
186
  vm_interface = VMInterface.objects.create(
167
187
  name="Int1", virtual_machine=self.virtualmachine, status=self.int_status
168
188
  )
169
- ips = list(IPAddress.objects.all()[:10])
189
+ ips = list(IPAddress.objects.filter(ip_version=4)[:10])
190
+ self.assertEqual(len(ips), 10)
170
191
 
171
192
  # baseline (no vm_interface to ip address relationships exists)
172
193
  self.assertFalse(IPAddressToInterface.objects.filter(vm_interface=vm_interface).exists())
@@ -179,13 +200,28 @@ class VMInterfaceTestCase(TestCase): # TODO: change to BaseModelTestCase
179
200
  self.assertEqual(count, 1)
180
201
  self.assertEqual(IPAddressToInterface.objects.filter(vm_interface=vm_interface).count(), 9)
181
202
 
203
+ # remove a single instance which has already been removed
204
+ count = vm_interface.remove_ip_addresses(ips[-1])
205
+ self.assertEqual(count, 0)
206
+ self.assertEqual(IPAddressToInterface.objects.filter(vm_interface=vm_interface).count(), 9)
207
+
182
208
  # remove multiple instances
183
209
  count = vm_interface.remove_ip_addresses(ips[:5])
184
210
  self.assertEqual(count, 5)
185
211
  self.assertEqual(IPAddressToInterface.objects.filter(vm_interface=vm_interface).count(), 4)
186
212
 
213
+ # remove multiple instances all which have already been removed
214
+ count = vm_interface.remove_ip_addresses(ips[:5])
215
+ self.assertEqual(count, 0)
216
+ self.assertEqual(IPAddressToInterface.objects.filter(vm_interface=vm_interface).count(), 4)
217
+
218
+ # remove multiple instances some of which have already been removed
219
+ count = vm_interface.remove_ip_addresses(ips[3:7])
220
+ self.assertEqual(count, 2)
221
+ self.assertEqual(IPAddressToInterface.objects.filter(vm_interface=vm_interface).count(), 2)
222
+
187
223
  count = vm_interface.remove_ip_addresses(ips)
188
- self.assertEqual(count, 4)
224
+ self.assertEqual(count, 2)
189
225
  self.assertEqual(IPAddressToInterface.objects.filter(vm_interface=vm_interface).count(), 0)
190
226
 
191
227
  # Test the pre_delete signal for IPAddressToInterface instances
@@ -194,9 +230,14 @@ class VMInterfaceTestCase(TestCase): # TODO: change to BaseModelTestCase
194
230
  self.virtualmachine.primary_ip6 = vm_interface.ip_addresses.all().filter(ip_version=6).first()
195
231
  self.virtualmachine.save()
196
232
 
197
- vm_interface.remove_ip_addresses(self.virtualmachine.primary_ip4)
233
+ count = vm_interface.remove_ip_addresses(self.virtualmachine.primary_ip4)
234
+ self.assertEqual(count, 1)
198
235
  self.virtualmachine.refresh_from_db()
199
236
  self.assertEqual(self.virtualmachine.primary_ip4, None)
200
- vm_interface.remove_ip_addresses(self.virtualmachine.primary_ip6)
237
+ # NOTE: This effectively tests what happens when you pass remove_ip_addresses None; it
238
+ # NOTE: does not remove a v6 address, because there are no v6 IPs used in this test
239
+ # NOTE: class.
240
+ count = vm_interface.remove_ip_addresses(self.virtualmachine.primary_ip6)
241
+ self.assertEqual(count, 0)
201
242
  self.virtualmachine.refresh_from_db()
202
243
  self.assertEqual(self.virtualmachine.primary_ip6, None)
@@ -191,6 +191,8 @@ class VirtualMachineUIViewSet(NautobotUIViewSet):
191
191
  table_class=VRFDeviceAssignmentTable,
192
192
  table_filter="virtual_machine",
193
193
  exclude_columns=["related_object_type", "related_object_name"],
194
+ related_list_url_name="ipam:vrf_list",
195
+ related_field_name="virtual_machines",
194
196
  ),
195
197
  object_detail.ObjectFieldsPanel(
196
198
  weight=200,
@@ -262,6 +264,7 @@ class VirtualMachineUIViewSet(NautobotUIViewSet):
262
264
  detail=True,
263
265
  url_path="config-context",
264
266
  url_name="configcontext",
267
+ custom_view_base_action="view",
265
268
  custom_view_additional_permissions=["extras.view_configcontext"],
266
269
  )
267
270
  def config_context(self, request, pk):
@@ -288,7 +291,7 @@ class VirtualMachineUIViewSet(NautobotUIViewSet):
288
291
  "source_contexts": ConfigContext.objects.restrict(request.user, "view").get_for_object(instance),
289
292
  "format": data_format,
290
293
  "template": "extras/object_configcontext.html",
291
- "base_template": "virtualization/virtualmachine.html",
294
+ "base_template": "generic/object_retrieve.html",
292
295
  }
293
296
 
294
297
  return Response(context)
File without changes
@@ -0,0 +1,113 @@
1
+ from rest_framework.serializers import ChoiceField, ListField
2
+
3
+ from nautobot.apps.api import NautobotModelSerializer, TaggedModelSerializerMixin
4
+
5
+ from .. import choices, models
6
+
7
+
8
+ class VPNProfileSerializer(TaggedModelSerializerMixin, NautobotModelSerializer): # pylint: disable=too-many-ancestors
9
+ """VPNProfile Serializer."""
10
+
11
+ class Meta:
12
+ """Meta attributes."""
13
+
14
+ model = models.VPNProfile
15
+ fields = "__all__"
16
+
17
+
18
+ class VPNPhase1PolicySerializer(TaggedModelSerializerMixin, NautobotModelSerializer): # pylint: disable=too-many-ancestors
19
+ """VPNPhase1Policy Serializer."""
20
+
21
+ encryption_algorithm = ListField(
22
+ child=ChoiceField(choices=choices.EncryptionAlgorithmChoices),
23
+ allow_empty=True,
24
+ required=False,
25
+ )
26
+ integrity_algorithm = ListField(
27
+ child=ChoiceField(choices=choices.IntegrityAlgorithmChoices),
28
+ allow_empty=True,
29
+ required=False,
30
+ )
31
+ dh_group = ListField(
32
+ child=ChoiceField(choices=choices.DhGroupChoices),
33
+ allow_empty=True,
34
+ required=False,
35
+ )
36
+
37
+ class Meta:
38
+ """Meta attributes."""
39
+
40
+ model = models.VPNPhase1Policy
41
+ fields = "__all__"
42
+
43
+
44
+ class VPNPhase2PolicySerializer(TaggedModelSerializerMixin, NautobotModelSerializer): # pylint: disable=too-many-ancestors
45
+ """VPNPhase2Policy Serializer."""
46
+
47
+ encryption_algorithm = ListField(
48
+ child=ChoiceField(choices=choices.EncryptionAlgorithmChoices),
49
+ allow_empty=True,
50
+ required=False,
51
+ )
52
+ integrity_algorithm = ListField(
53
+ child=ChoiceField(choices=choices.IntegrityAlgorithmChoices),
54
+ allow_empty=True,
55
+ required=False,
56
+ )
57
+ pfs_group = ListField(
58
+ child=ChoiceField(choices=choices.DhGroupChoices),
59
+ allow_empty=True,
60
+ required=False,
61
+ )
62
+
63
+ class Meta:
64
+ """Meta attributes."""
65
+
66
+ model = models.VPNPhase2Policy
67
+ fields = "__all__"
68
+
69
+
70
+ class VPNProfilePhase1PolicyAssignmentSerializer(NautobotModelSerializer):
71
+ """Serializer for `VPNProfilePhase1PolicyAssignment` objects."""
72
+
73
+ class Meta:
74
+ model = models.VPNProfilePhase1PolicyAssignment
75
+ fields = "__all__"
76
+
77
+
78
+ class VPNProfilePhase2PolicyAssignmentSerializer(NautobotModelSerializer):
79
+ """Serializer for `VPNProfilePhase2PolicyAssignment` objects."""
80
+
81
+ class Meta:
82
+ model = models.VPNProfilePhase2PolicyAssignment
83
+ fields = "__all__"
84
+
85
+
86
+ class VPNSerializer(TaggedModelSerializerMixin, NautobotModelSerializer): # pylint: disable=too-many-ancestors
87
+ """VPN Serializer."""
88
+
89
+ class Meta:
90
+ """Meta attributes."""
91
+
92
+ model = models.VPN
93
+ fields = "__all__"
94
+
95
+
96
+ class VPNTunnelSerializer(TaggedModelSerializerMixin, NautobotModelSerializer): # pylint: disable=too-many-ancestors
97
+ """VPNTunnel Serializer."""
98
+
99
+ class Meta:
100
+ """Meta attributes."""
101
+
102
+ model = models.VPNTunnel
103
+ fields = "__all__"
104
+
105
+
106
+ class VPNTunnelEndpointSerializer(TaggedModelSerializerMixin, NautobotModelSerializer): # pylint: disable=too-many-ancestors
107
+ """VPNTunnelEndpoint Serializer."""
108
+
109
+ class Meta:
110
+ """Meta attributes."""
111
+
112
+ model = models.VPNTunnelEndpoint
113
+ fields = "__all__"
@@ -0,0 +1,19 @@
1
+ """Django API urlpatterns declaration for the vpn models."""
2
+
3
+ from nautobot.apps.api import OrderedDefaultRouter
4
+
5
+ from . import views
6
+
7
+ app_name = "vpn-api"
8
+ router = OrderedDefaultRouter()
9
+ # add the name of your api endpoint, usually hyphenated model name in plural, e.g. "my-model-classes"
10
+ router.register("vpn-profiles", views.VPNProfileViewSet)
11
+ router.register("vpn-phase-1-policies", views.VPNPhase1PolicyViewSet)
12
+ router.register("vpn-phase-2-policies", views.VPNPhase2PolicyViewSet)
13
+ router.register("vpn-profile-phase-1-policy-assignments", views.VPNProfilePhase1PolicyAssignmentViewSet)
14
+ router.register("vpn-profile-phase-2-policy-assignments", views.VPNProfilePhase2PolicyAssignmentViewSet)
15
+ router.register("vpns", views.VPNViewSet)
16
+ router.register("vpn-tunnels", views.VPNTunnelViewSet)
17
+ router.register("vpn-tunnel-endpoints", views.VPNTunnelEndpointViewSet)
18
+
19
+ urlpatterns = router.urls