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.
- nautobot/apps/choices.py +4 -2
- nautobot/apps/filters.py +7 -9
- nautobot/apps/models.py +2 -2
- nautobot/apps/ui.py +13 -1
- nautobot/apps/utils.py +8 -0
- nautobot/circuits/filters.py +3 -2
- nautobot/circuits/navigation.py +3 -2
- nautobot/circuits/templates/circuits/circuit_create.html +3 -3
- nautobot/circuits/templates/circuits/circuittermination_create.html +9 -24
- nautobot/circuits/templates/circuits/inc/circuit_termination_cable_fragment.html +6 -6
- nautobot/circuits/templates/circuits/inc/speed_widget.html +12 -12
- nautobot/circuits/tests/integration/test_circuit.py +10 -13
- nautobot/circuits/tests/integration/test_circuits_bulk_operations.py +0 -3
- nautobot/circuits/views.py +6 -2
- nautobot/cloud/filters.py +1 -1
- nautobot/cloud/navigation.py +3 -2
- nautobot/core/api/schema.py +1 -1
- nautobot/core/api/serializers.py +6 -1
- nautobot/core/api/urls.py +2 -0
- nautobot/core/api/views.py +12 -0
- nautobot/core/apps/__init__.py +11 -10
- nautobot/core/celery/__init__.py +3 -5
- nautobot/core/checks.py +46 -0
- nautobot/core/choices.py +1 -1
- nautobot/core/cli/bootstrap_v3_to_v5.py +105 -13
- nautobot/core/cli/migrate_deprecated_templates.py +227 -0
- nautobot/core/constants.py +3 -0
- nautobot/core/context_processors.py +9 -1
- nautobot/core/filters.py +4 -0
- nautobot/core/forms/__init__.py +2 -0
- nautobot/core/forms/forms.py +1 -1
- nautobot/core/forms/widgets.py +21 -2
- nautobot/core/jobs/__init__.py +62 -3
- nautobot/core/jobs/groups.py +31 -1
- nautobot/core/management/commands/generate_test_data.py +28 -9
- nautobot/core/models/__init__.py +11 -0
- nautobot/core/models/generics.py +9 -1
- nautobot/core/models/tree_queries.py +10 -5
- nautobot/core/models/utils.py +1 -1
- nautobot/core/settings.py +35 -19
- nautobot/core/settings.yaml +17 -33
- nautobot/core/signals.py +12 -1
- nautobot/core/tables.py +13 -6
- nautobot/core/templates/40x.html +1 -1
- nautobot/core/templates/500.html +2 -2
- nautobot/core/templates/admin/base.html +1 -2
- nautobot/core/templates/admin/change_list.html +9 -12
- nautobot/core/templates/admin/config/config.html +12 -12
- nautobot/core/templates/admin/index.html +3 -3
- nautobot/core/templates/base_django.html +1 -2
- nautobot/core/templates/buttons/export.html +1 -1
- nautobot/core/templates/components/button/dropdown.html +5 -3
- nautobot/core/templates/components/panel/body_wrapper_generic_table.html +1 -1
- nautobot/core/templates/components/panel/header_extra_content_table.html +1 -1
- nautobot/core/templates/components/panel/panel.html +3 -3
- nautobot/core/templates/components/tab/content_wrapper.html +6 -7
- nautobot/core/templates/components/tab/label_wrapper_distinct_view.html +1 -1
- nautobot/core/templates/echarts/echarts.html +22 -9
- nautobot/core/templates/generic/object_bulk_add_component.html +2 -1
- nautobot/core/templates/generic/object_bulk_create.html +6 -5
- nautobot/core/templates/generic/object_bulk_delete.html +1 -1
- nautobot/core/templates/generic/object_bulk_destroy.html +3 -3
- nautobot/core/templates/generic/object_bulk_edit.html +1 -1
- nautobot/core/templates/generic/object_bulk_import.html +1 -1
- nautobot/core/templates/generic/object_bulk_remove.html +2 -2
- nautobot/core/templates/generic/object_bulk_update.html +5 -4
- nautobot/core/templates/generic/object_create.html +5 -4
- nautobot/core/templates/generic/object_delete.html +1 -1
- nautobot/core/templates/generic/object_detail.html +1 -1
- nautobot/core/templates/generic/object_edit.html +1 -1
- nautobot/core/templates/generic/object_import.html +2 -1
- nautobot/core/templates/generic/object_list.html +12 -4
- nautobot/core/templates/generic/object_notes.html +5 -3
- nautobot/core/templates/generic/object_retrieve.html +4 -5
- nautobot/core/templates/graphene/graphiql.html +7 -8
- nautobot/core/templates/home.html +1 -1
- nautobot/core/templates/import_success.html +2 -1
- nautobot/core/templates/inc/computed_fields/panel_data.html +1 -1
- nautobot/core/templates/inc/created_updated.html +7 -3
- nautobot/core/templates/inc/custom_fields/panel_data.html +1 -1
- nautobot/core/templates/inc/footer.html +3 -1
- nautobot/core/templates/inc/form_static_field.html +6 -0
- nautobot/core/templates/inc/header.html +11 -1
- nautobot/core/templates/inc/image_attachments.html +2 -1
- nautobot/core/templates/inc/media.html +14 -0
- nautobot/core/templates/inc/nav_menu.html +3 -9
- nautobot/core/templates/inc/object_details_advanced_panel.html +2 -2
- nautobot/core/templates/inc/search_panel.html +4 -4
- nautobot/core/templates/login.html +4 -2
- nautobot/core/templates/nautobot_config.py.j2 +6 -11
- nautobot/core/templates/redoc_ui.html +7 -0
- nautobot/core/templates/rest_framework/api.html +103 -2
- nautobot/core/templates/search.html +1 -1
- nautobot/core/templates/swagger_ui.html +17 -3
- nautobot/core/templates/system_jobs/import_objects.html +1 -2
- nautobot/core/templates/utilities/confirmation_form.html +2 -2
- nautobot/core/templates/utilities/obj_table.html +10 -2
- nautobot/core/templates/utilities/render_field.html +7 -7
- nautobot/core/templates/utilities/render_jinja2.html +2 -2
- nautobot/core/templates/utilities/templatetags/filter_form_drawer.html +37 -4
- nautobot/core/templates/utilities/theme_preview.html +19 -3
- nautobot/core/templates/widgets/number_input_with_choices.html +44 -0
- nautobot/core/templates/widgets/selectwithdisabled_option.html +3 -1
- nautobot/core/templatetags/helpers.py +76 -18
- nautobot/core/testing/api.py +68 -9
- nautobot/core/testing/filters.py +0 -23
- nautobot/core/testing/integration.py +41 -17
- nautobot/core/testing/mixins.py +2 -0
- nautobot/core/testing/utils.py +18 -4
- nautobot/core/testing/views.py +104 -13
- nautobot/core/tests/integration/test_app_home.py +34 -30
- nautobot/core/tests/integration/test_app_navbar.py +3 -0
- nautobot/core/tests/integration/test_filters.py +48 -11
- nautobot/core/tests/integration/test_theme.py +22 -21
- nautobot/core/tests/nautobot_config.py +3 -0
- nautobot/core/tests/nautobot_config_without_example_apps.py +4 -0
- nautobot/core/tests/runner.py +8 -1
- nautobot/core/tests/test_api.py +5 -3
- nautobot/core/tests/test_breadcrumbs.py +27 -28
- nautobot/core/tests/test_checks.py +28 -0
- nautobot/core/tests/test_cli.py +40 -0
- nautobot/core/tests/test_config.py +2 -1
- nautobot/core/tests/test_forms.py +55 -13
- nautobot/core/tests/test_jobs.py +144 -3
- nautobot/core/tests/test_nautobot_server.py +2 -0
- nautobot/core/tests/test_navigations.py +76 -1
- nautobot/core/tests/test_patch_social_django.py +42 -0
- nautobot/core/tests/test_renderers.py +59 -0
- nautobot/core/tests/test_settings_schema.py +1 -0
- nautobot/core/tests/test_tables.py +3 -1
- nautobot/core/tests/test_templatetags_helpers.py +62 -13
- nautobot/core/tests/test_templatetags_ui_framework.py +4 -4
- nautobot/core/tests/test_titles.py +0 -16
- nautobot/core/tests/test_tree_queries.py +14 -1
- nautobot/core/tests/test_ui.py +123 -4
- nautobot/core/tests/test_utils.py +72 -5
- nautobot/core/tests/test_views.py +159 -31
- nautobot/core/ui/breadcrumbs.py +70 -29
- nautobot/core/ui/bulk_buttons.py +1 -1
- nautobot/core/ui/choices.py +143 -27
- nautobot/core/ui/constants.py +76 -12
- nautobot/core/ui/echarts.py +15 -20
- nautobot/core/ui/object_detail.py +143 -55
- nautobot/core/ui/titles.py +3 -6
- nautobot/core/urls.py +20 -9
- nautobot/core/utils/cache.py +2 -1
- nautobot/core/utils/filtering.py +28 -18
- nautobot/core/utils/lookup.py +49 -8
- nautobot/core/utils/module_loading.py +21 -0
- nautobot/core/utils/patch_social_django.py +128 -0
- nautobot/core/views/__init__.py +38 -1
- nautobot/core/views/generic.py +3 -3
- nautobot/core/views/mixins.py +45 -22
- nautobot/core/views/renderers.py +4 -3
- nautobot/core/views/viewsets.py +2 -1
- nautobot/data_validation/apps.py +1 -5
- nautobot/data_validation/custom_validators.py +4 -4
- nautobot/data_validation/filters.py +1 -1
- nautobot/data_validation/forms.py +40 -0
- nautobot/data_validation/migrations/0001_initial.py +0 -7
- nautobot/data_validation/migrations/0002_data_migration_from_app.py +3 -14
- nautobot/data_validation/models.py +16 -7
- nautobot/data_validation/navigation.py +8 -1
- nautobot/data_validation/tables.py +12 -5
- nautobot/data_validation/templates/data_validation/datacompliance_tab.html +1 -0
- nautobot/data_validation/templates/data_validation/device_constraints.html +61 -0
- nautobot/data_validation/tests/__init__.py +2 -2
- nautobot/data_validation/tests/migrations/test_migrations.py +83 -3
- nautobot/data_validation/tests/test_data_compliance_rules.py +12 -7
- nautobot/data_validation/tests/test_filters.py +8 -6
- nautobot/data_validation/tests/test_models.py +15 -0
- nautobot/data_validation/tests/test_views.py +190 -32
- nautobot/data_validation/urls.py +2 -5
- nautobot/data_validation/views.py +73 -40
- nautobot/dcim/api/serializers.py +3 -13
- nautobot/dcim/apps.py +4 -0
- nautobot/dcim/choices.py +65 -0
- nautobot/dcim/constants.py +7 -0
- nautobot/dcim/custom_validators.py +84 -0
- nautobot/dcim/factory.py +1 -1
- nautobot/dcim/filter_mixins.py +353 -4
- nautobot/dcim/{filters/__init__.py → filters.py} +15 -36
- nautobot/dcim/forms.py +90 -4
- nautobot/dcim/migrations/0075_interface_duplex_interface_speed_and_more.py +32 -0
- nautobot/dcim/migrations/{0075_add_deviceclusterassignment.py → 0076_add_deviceclusterassignment.py} +1 -1
- nautobot/dcim/migrations/{0076_device_cluster_to_clusters_data_migration.py → 0077_device_cluster_to_clusters_data_migration.py} +1 -1
- nautobot/dcim/migrations/{0077_remove_device_cluster.py → 0078_remove_device_cluster.py} +1 -1
- nautobot/dcim/migrations/0079_remove_device_location_tenant_name_uniqueness.py +16 -0
- nautobot/dcim/migrations/0080_device_name_data_migration.py +59 -0
- nautobot/dcim/migrations/0081_alter_device_device_redundancy_group_priority_and_more.py +25 -0
- nautobot/dcim/models/device_component_templates.py +33 -1
- nautobot/dcim/models/device_components.py +98 -64
- nautobot/dcim/models/devices.py +30 -20
- nautobot/dcim/navigation.py +7 -6
- nautobot/dcim/tables/devices.py +18 -0
- nautobot/dcim/tables/devicetypes.py +8 -1
- nautobot/dcim/tables/racks.py +0 -2
- nautobot/dcim/tables/template_code.py +15 -15
- nautobot/dcim/templates/dcim/cable_connect.html +28 -112
- nautobot/dcim/templates/dcim/cable_trace.html +0 -4
- nautobot/dcim/templates/dcim/{cable_edit.html → cable_update.html} +1 -1
- nautobot/dcim/templates/dcim/consoleport.html +7 -6
- nautobot/dcim/templates/dcim/consoleserverport.html +7 -6
- nautobot/dcim/templates/dcim/device/config.html +2 -2
- nautobot/dcim/templates/dcim/device/lldp_neighbors.html +1 -1
- nautobot/dcim/templates/dcim/device/status.html +8 -8
- nautobot/dcim/templates/dcim/device.html +1 -1
- nautobot/dcim/templates/dcim/device_component_add.html +2 -2
- nautobot/dcim/templates/dcim/device_create.html +5 -3
- nautobot/dcim/templates/dcim/device_interface_delete.html +1 -1
- nautobot/dcim/templates/dcim/device_list.html +73 -10
- nautobot/dcim/templates/dcim/devicebay.html +1 -1
- nautobot/dcim/templates/dcim/devicebay_populate.html +2 -2
- nautobot/dcim/templates/dcim/devicetype_component_add.html +2 -2
- nautobot/dcim/templates/dcim/footer_convert_to_contact_or_team_record.html +14 -0
- nautobot/dcim/templates/dcim/frontport.html +10 -9
- nautobot/dcim/templates/dcim/inc/devicetype_component_table.html +1 -1
- nautobot/dcim/templates/dcim/inc/edit_form_softwareversion_js.html +2 -2
- nautobot/dcim/templates/dcim/inc/moduletype_component_table.html +1 -1
- nautobot/dcim/templates/dcim/inc/rack_elevation.html +1 -1
- nautobot/dcim/templates/dcim/interface.html +35 -7
- nautobot/dcim/templates/dcim/interface_bulk_delete.html +1 -1
- nautobot/dcim/templates/dcim/interface_edit.html +2 -0
- nautobot/dcim/templates/dcim/inventoryitem.html +1 -1
- nautobot/dcim/templates/dcim/inventoryitem_add.html +3 -1
- nautobot/dcim/templates/dcim/inventoryitem_bulk_delete.html +1 -1
- nautobot/dcim/templates/dcim/inventoryitem_edit.html +3 -1
- nautobot/dcim/templates/dcim/module/base.html +49 -9
- nautobot/dcim/templates/dcim/module_consoleports.html +1 -1
- nautobot/dcim/templates/dcim/module_consoleserverports.html +1 -1
- nautobot/dcim/templates/dcim/module_frontports.html +1 -1
- nautobot/dcim/templates/dcim/module_interfaces.html +1 -1
- nautobot/dcim/templates/dcim/module_list.html +57 -8
- nautobot/dcim/templates/dcim/module_modulebays.html +1 -1
- nautobot/dcim/templates/dcim/module_poweroutlets.html +1 -1
- nautobot/dcim/templates/dcim/module_powerports.html +1 -1
- nautobot/dcim/templates/dcim/module_rearports.html +1 -1
- nautobot/dcim/templates/dcim/modulefamily_retrieve.html +1 -1
- nautobot/dcim/templates/dcim/moduletype_list.html +2 -2
- nautobot/dcim/templates/dcim/moduletype_retrieve.html +49 -9
- nautobot/dcim/templates/dcim/platform_create.html +1 -1
- nautobot/dcim/templates/dcim/poweroutlet.html +1 -1
- nautobot/dcim/templates/dcim/powerport.html +6 -5
- nautobot/dcim/templates/dcim/rack_elevation_list.html +17 -5
- nautobot/dcim/templates/dcim/rack_retrieve.html +22 -15
- nautobot/dcim/templates/dcim/rearport.html +8 -7
- nautobot/dcim/templates/dcim/trace/cable.html +1 -1
- nautobot/dcim/templates/dcim/virtualchassis_add_member.html +16 -14
- nautobot/dcim/templates/dcim/virtualchassis_update.html +15 -7
- nautobot/dcim/tests/integration/test_controller.py +4 -6
- nautobot/dcim/tests/integration/test_controller_managed_device_group.py +1 -5
- nautobot/dcim/tests/integration/test_create_device.py +0 -2
- nautobot/dcim/tests/integration/test_device_bulk_operations.py +1 -3
- nautobot/dcim/tests/integration/test_fileinputpicker.py +6 -10
- nautobot/dcim/tests/integration/test_location_bulk_operations.py +0 -2
- nautobot/dcim/tests/integration/test_module_bay_position.py +3 -4
- nautobot/dcim/tests/test_api.py +194 -6
- nautobot/dcim/tests/test_custom_validators.py +229 -0
- nautobot/dcim/tests/test_filters.py +55 -7
- nautobot/dcim/tests/test_forms.py +110 -8
- nautobot/dcim/tests/test_graphql.py +44 -1
- nautobot/dcim/tests/test_models.py +328 -4
- nautobot/dcim/tests/test_tables.py +160 -0
- nautobot/dcim/tests/test_views.py +132 -29
- nautobot/dcim/urls.py +64 -21
- nautobot/dcim/utils.py +3 -3
- nautobot/dcim/views.py +777 -397
- nautobot/extras/api/views.py +60 -45
- nautobot/extras/choices.py +2 -13
- nautobot/extras/datasources/git.py +3 -1
- nautobot/extras/{filters/mixins.py → filter_mixins.py} +1 -1
- nautobot/extras/{filters/customfields.py → filter_mixins_customfields.py} +42 -6
- nautobot/extras/{filters/__init__.py → filters.py} +33 -48
- nautobot/extras/forms/forms.py +14 -15
- nautobot/extras/forms/mixins.py +0 -41
- nautobot/extras/jobs.py +2 -0
- nautobot/extras/jobs_ui.py +4 -3
- nautobot/extras/management/__init__.py +11 -0
- nautobot/extras/management/commands/refresh_dynamic_group_member_caches.py +4 -1
- nautobot/extras/migrations/0127_approval_workflow_models.py +6 -6
- nautobot/extras/migrations/0129_jobresult_debug_log_count_jobresult_error_log_count_and_more.py +37 -0
- nautobot/extras/migrations/0130_jobresult_generate_log_entry_counts.py +42 -0
- nautobot/extras/migrations/0131_configcontext_device_families.py +18 -0
- nautobot/extras/models/__init__.py +1 -2
- nautobot/extras/models/approvals.py +33 -14
- nautobot/extras/models/change_logging.py +4 -0
- nautobot/extras/models/contacts.py +2 -0
- nautobot/extras/models/groups.py +44 -5
- nautobot/extras/models/jobs.py +60 -4
- nautobot/extras/models/mixins.py +28 -0
- nautobot/extras/models/models.py +23 -2
- nautobot/extras/models/secrets.py +1 -0
- nautobot/extras/models/statuses.py +0 -15
- nautobot/extras/navigation.py +13 -9
- nautobot/extras/plugins/__init__.py +33 -55
- nautobot/extras/plugins/marketplace_manifest.yml +49 -1
- nautobot/extras/plugins/tables.py +3 -3
- nautobot/extras/plugins/urls.py +2 -21
- nautobot/extras/plugins/utils.py +1 -33
- nautobot/extras/plugins/views.py +0 -9
- nautobot/extras/querysets.py +8 -0
- nautobot/extras/signals.py +20 -19
- nautobot/extras/tables.py +64 -68
- nautobot/extras/templates/django_ajax_tables/ajax_wrapper.html +2 -0
- nautobot/extras/templates/extras/approval_dashboard.html +7 -5
- nautobot/extras/templates/extras/approvalworkflowdefinition_update.html +4 -2
- nautobot/extras/templates/extras/approvalworkflowstage_retrieve.html +20 -12
- nautobot/extras/templates/extras/configcontext_update.html +1 -0
- nautobot/extras/templates/extras/configcontextschema_validation.html +2 -2
- nautobot/extras/templates/extras/dynamicgroup_retrieve.html +11 -5
- nautobot/extras/templates/extras/dynamicgroup_update.html +1 -1
- nautobot/extras/templates/extras/gitrepository_result.html +0 -2
- nautobot/extras/templates/extras/inc/approval_buttons_column.html +20 -6
- nautobot/extras/templates/extras/inc/bulk_edit_overridable_field.html +8 -7
- nautobot/extras/templates/extras/inc/configcontext_format.html +10 -3
- nautobot/extras/templates/extras/inc/graphqlquery_execute.html +71 -0
- nautobot/extras/templates/extras/inc/job_tiles.html +15 -3
- nautobot/extras/templates/extras/inc/json_format.html +10 -3
- nautobot/extras/templates/extras/inc/overridable_field.html +13 -12
- nautobot/extras/templates/extras/job.html +29 -12
- nautobot/extras/templates/extras/job_bulk_edit.html +18 -0
- nautobot/extras/templates/extras/job_edit.html +52 -46
- nautobot/extras/templates/extras/job_list.html +29 -25
- nautobot/extras/templates/extras/marketplace.html +5 -9
- nautobot/extras/templates/extras/object_configcontext.html +1 -1
- nautobot/extras/templates/extras/object_dynamicgroups.html +2 -2
- nautobot/extras/templates/extras/objectchange_retrieve.html +19 -39
- nautobot/extras/templates/extras/plugin_detail.html +29 -24
- nautobot/extras/templates/extras/plugins_list.html +16 -26
- nautobot/extras/templates/extras/role_retrieve.html +64 -0
- nautobot/extras/templates/extras/scheduledjob.html +4 -2
- nautobot/extras/templates/extras/secret_create.html +1 -1
- nautobot/extras/templatetags/custom_links.py +12 -12
- nautobot/extras/templatetags/job_buttons.py +14 -12
- nautobot/extras/test_jobs/invalid_import.py +9 -0
- nautobot/extras/test_jobs/log_counts_by_level.py +23 -0
- nautobot/extras/test_jobs/missing_import.py +11 -0
- nautobot/extras/tests/integration/test_computedfields.py +8 -9
- nautobot/extras/tests/integration/test_configcontextschema.py +27 -26
- nautobot/extras/tests/integration/test_customfields.py +9 -10
- nautobot/extras/tests/integration/test_dynamicgroups.py +12 -9
- nautobot/extras/tests/integration/test_plugin_banner.py +3 -0
- nautobot/extras/tests/integration/test_plugins.py +18 -6
- nautobot/extras/tests/integration/test_relationships.py +0 -2
- nautobot/extras/tests/test_api.py +90 -18
- nautobot/extras/tests/test_approvals.py +38 -38
- nautobot/extras/tests/test_changelog.py +59 -5
- nautobot/extras/tests/test_customfields.py +22 -13
- nautobot/extras/tests/test_customfields_filters.py +479 -0
- nautobot/extras/tests/test_dynamicgroups.py +39 -1
- nautobot/extras/tests/test_filters.py +57 -22
- nautobot/extras/tests/test_forms.py +18 -21
- nautobot/extras/tests/test_jobs.py +25 -4
- nautobot/extras/tests/test_migrations.py +1 -0
- nautobot/extras/tests/test_models.py +51 -33
- nautobot/extras/tests/test_plugins.py +36 -10
- nautobot/extras/tests/test_utils.py +3 -4
- nautobot/extras/tests/test_views.py +52 -112
- nautobot/extras/urls.py +0 -14
- nautobot/extras/views.py +164 -71
- nautobot/ipam/factory.py +7 -0
- nautobot/ipam/filter_mixins.py +38 -0
- nautobot/ipam/filters.py +53 -38
- nautobot/ipam/formfields.py +1 -1
- nautobot/ipam/forms.py +6 -3
- nautobot/ipam/migrations/0030_ipam__namespaces.py +13 -0
- nautobot/ipam/migrations/0031_ipam___data_migrations.py +4 -1
- nautobot/ipam/migrations/0054_namespace_tenant.py +25 -0
- nautobot/ipam/models.py +29 -2
- nautobot/ipam/navigation.py +3 -2
- nautobot/ipam/signals.py +71 -0
- nautobot/ipam/tables.py +19 -6
- nautobot/ipam/templates/ipam/inc/toggle_available.html +10 -10
- nautobot/ipam/templates/ipam/inc/vlangroup_header.html +1 -0
- nautobot/ipam/templates/ipam/ipaddress.html +14 -0
- nautobot/ipam/templates/ipam/ipaddress_merge.html +3 -3
- nautobot/ipam/templates/ipam/ipaddresstointerface_retrieve.html +1 -0
- nautobot/ipam/templates/ipam/namespace_ip_addresses.html +1 -1
- nautobot/ipam/templates/ipam/namespace_prefixes.html +1 -1
- nautobot/ipam/templates/ipam/namespace_update.html +15 -0
- nautobot/ipam/templates/ipam/namespace_vrfs.html +1 -1
- nautobot/ipam/templates/ipam/prefix_delete.html +1 -1
- nautobot/ipam/templates/ipam/prefix_list.html +14 -13
- nautobot/ipam/templates/ipam/vlan_interfaces.html +1 -1
- nautobot/ipam/templates/ipam/vlan_vminterfaces.html +1 -1
- nautobot/ipam/tests/migration/test_migrations.py +89 -0
- nautobot/ipam/tests/test_api.py +13 -6
- nautobot/ipam/tests/test_filters.py +36 -1
- nautobot/ipam/tests/test_forms.py +1 -1
- nautobot/ipam/tests/test_models.py +44 -2
- nautobot/ipam/tests/test_tables.py +1 -2
- nautobot/ipam/tests/test_utils.py +1 -1
- nautobot/ipam/tests/test_views.py +13 -14
- nautobot/ipam/ui.py +0 -17
- nautobot/ipam/utils/migrations.py +16 -2
- nautobot/ipam/utils/testing.py +9 -3
- nautobot/ipam/views.py +53 -11
- nautobot/load_balancers/__init__.py +0 -0
- nautobot/load_balancers/api/__init__.py +1 -0
- nautobot/load_balancers/api/serializers.py +75 -0
- nautobot/load_balancers/api/urls.py +23 -0
- nautobot/load_balancers/api/views.py +61 -0
- nautobot/load_balancers/apps.py +17 -0
- nautobot/load_balancers/choices.py +167 -0
- nautobot/load_balancers/filters.py +225 -0
- nautobot/load_balancers/forms.py +532 -0
- nautobot/load_balancers/management/commands/__init__.py +0 -0
- nautobot/load_balancers/management/commands/generate_load_balancer_models_test_data.py +38 -0
- nautobot/load_balancers/migrations/0001_initial.py +465 -0
- nautobot/load_balancers/migrations/0002_create_default_statuses_pool_members.py +31 -0
- nautobot/load_balancers/migrations/__init__.py +0 -0
- nautobot/load_balancers/models.py +423 -0
- nautobot/load_balancers/navigation.py +80 -0
- nautobot/load_balancers/tables.py +255 -0
- nautobot/load_balancers/tests/__init__.py +474 -0
- nautobot/load_balancers/tests/test_api.py +353 -0
- nautobot/load_balancers/tests/test_filters.py +134 -0
- nautobot/load_balancers/tests/test_forms.py +266 -0
- nautobot/load_balancers/tests/test_models.py +195 -0
- nautobot/load_balancers/tests/test_views.py +229 -0
- nautobot/load_balancers/urls.py +17 -0
- nautobot/load_balancers/views.py +248 -0
- nautobot/project-static/dist/css/github-dark.min.css +10 -0
- nautobot/project-static/dist/css/github.min.css +10 -0
- nautobot/project-static/dist/css/nautobot.css +1 -11
- nautobot/project-static/dist/css/nautobot.css.map +1 -1
- nautobot/project-static/dist/js/libraries.js +1 -1
- nautobot/project-static/dist/js/libraries.js.map +1 -1
- nautobot/project-static/dist/js/nautobot.js +1 -1
- nautobot/project-static/dist/js/nautobot.js.map +1 -1
- nautobot/project-static/js/cabletrace.js +1 -1
- nautobot/project-static/js/forms.js +13 -0
- nautobot/project-static/js/interface_filtering.js +20 -16
- nautobot/project-static/nautobot-icons/battery-3.svg +3 -0
- nautobot/project-static/nautobot-icons/bus-globe.svg +3 -0
- nautobot/project-static/nautobot-icons/bus-shield-check.svg +3 -0
- nautobot/project-static/nautobot-icons/bus-shield.svg +3 -0
- nautobot/project-static/nautobot-icons/cloud.svg +1 -1
- nautobot/project-static/nautobot-icons/control-panel.svg +1 -1
- nautobot/project-static/nautobot-icons/device-lifecycle.svg +1 -1
- nautobot/project-static/nautobot-icons/elements.svg +1 -1
- nautobot/project-static/nautobot-icons/extensibility.svg +3 -0
- nautobot/project-static/nautobot-icons/hammer.svg +1 -1
- nautobot/project-static/nautobot-icons/organization.svg +3 -0
- nautobot/project-static/nautobot-icons/secrets.svg +1 -1
- nautobot/project-static/nautobot-icons/security.svg +3 -0
- nautobot/project-static/nautobot-icons/server.svg +1 -1
- nautobot/project-static/nautobot-icons/star-filled.svg +1 -1
- nautobot/project-static/nautobot-icons/star.svg +1 -1
- nautobot/tenancy/api/serializers.py +1 -0
- nautobot/tenancy/api/views.py +2 -1
- nautobot/tenancy/{filters/__init__.py → filters.py} +2 -10
- nautobot/tenancy/navigation.py +3 -1
- nautobot/tenancy/tests/test_filters.py +0 -2
- nautobot/tenancy/views.py +2 -1
- nautobot/ui/package-lock.json +87 -4
- nautobot/ui/package.json +2 -1
- nautobot/ui/src/js/collapse.js +3 -3
- nautobot/ui/src/js/nautobot.js +16 -1
- nautobot/ui/src/js/select2.js +53 -2
- nautobot/ui/src/scss/colors.scss +1 -1
- nautobot/ui/src/scss/nautobot.scss +112 -30
- nautobot/ui/webpack.config.js +13 -0
- nautobot/users/templates/users/preferences.html +11 -2
- nautobot/users/templates/users/profile.html +45 -12
- nautobot/users/templates/users/sessionkey_delete.html +1 -1
- nautobot/users/tests/test_api.py +4 -0
- nautobot/users/views.py +4 -2
- nautobot/virtualization/filters.py +6 -1
- nautobot/virtualization/models.py +1 -68
- nautobot/virtualization/navigation.py +3 -2
- nautobot/virtualization/templates/virtualization/virtual_machine_vminterface_delete.html +1 -1
- nautobot/virtualization/templates/virtualization/virtualmachine_list.html +2 -2
- nautobot/virtualization/templates/virtualization/virtualmachine_update.html +3 -1
- nautobot/virtualization/tests/test_api.py +3 -0
- nautobot/virtualization/tests/test_filters.py +10 -1
- nautobot/virtualization/tests/test_models.py +45 -4
- nautobot/virtualization/views.py +4 -1
- nautobot/vpn/__init__.py +0 -0
- nautobot/vpn/api/serializers.py +113 -0
- nautobot/vpn/api/urls.py +19 -0
- nautobot/vpn/api/views.py +70 -0
- nautobot/vpn/apps.py +8 -0
- nautobot/vpn/choices.py +171 -0
- nautobot/vpn/factory.py +219 -0
- nautobot/vpn/filters.py +234 -0
- nautobot/vpn/forms.py +487 -0
- nautobot/vpn/homepage.py +19 -0
- nautobot/vpn/migrations/0001_initial.py +541 -0
- nautobot/vpn/migrations/0002_populate_defaults.py +199 -0
- nautobot/vpn/migrations/__init__.py +0 -0
- nautobot/vpn/models.py +535 -0
- nautobot/vpn/navigation.py +98 -0
- nautobot/vpn/tables.py +383 -0
- nautobot/vpn/templates/vpn/vpnprofile_create.html +150 -0
- nautobot/vpn/tests/__init__.py +0 -0
- nautobot/vpn/tests/test_api.py +336 -0
- nautobot/vpn/tests/test_filters.py +139 -0
- nautobot/vpn/tests/test_forms.py +293 -0
- nautobot/vpn/tests/test_models.py +147 -0
- nautobot/vpn/tests/test_views.py +300 -0
- nautobot/vpn/urls.py +16 -0
- nautobot/vpn/views.py +495 -0
- nautobot/wireless/navigation.py +3 -2
- nautobot/wireless/tests/integration/test_radio_profile.py +1 -5
- nautobot/wireless/tests/test_api.py +1 -1
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/METADATA +15 -15
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/RECORD +514 -572
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/entry_points.txt +1 -0
- nautobot/circuits/templates/circuits/circuit.html +0 -2
- nautobot/circuits/templates/circuits/circuit_edit.html +0 -2
- nautobot/circuits/templates/circuits/circuit_retrieve.html +0 -2
- nautobot/circuits/templates/circuits/circuit_update.html +0 -1
- nautobot/circuits/templates/circuits/circuittermination.html +0 -2
- nautobot/circuits/templates/circuits/circuittermination_edit.html +0 -2
- nautobot/circuits/templates/circuits/circuittermination_retrieve.html +0 -2
- nautobot/circuits/templates/circuits/circuittermination_update.html +0 -1
- nautobot/circuits/templates/circuits/circuittype.html +0 -2
- nautobot/circuits/templates/circuits/circuittype_retrieve.html +0 -2
- nautobot/circuits/templates/circuits/inc/circuit_termination.html +0 -85
- nautobot/circuits/templates/circuits/provider.html +0 -2
- nautobot/circuits/templates/circuits/provider_edit.html +0 -2
- nautobot/circuits/templates/circuits/provider_retrieve.html +0 -1
- nautobot/circuits/templates/circuits/provider_update.html +0 -1
- nautobot/circuits/templates/circuits/providernetwork.html +0 -2
- nautobot/circuits/templates/circuits/providernetwork_retrieve.html +0 -2
- nautobot/cloud/templates/cloud/cloudaccount_retrieve.html +0 -2
- nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +0 -2
- nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +0 -2
- nautobot/cloud/templates/cloud/cloudservice_retrieve.html +0 -2
- nautobot/core/templates/buttons/import.html +0 -9
- nautobot/data_validation/template_content.py +0 -42
- nautobot/data_validation/templates/data_validation/datacompliance_retrieve.html +0 -1
- nautobot/dcim/filters/mixins.py +0 -354
- nautobot/dcim/templates/dcim/controller/base.html +0 -2
- nautobot/dcim/templates/dcim/controller_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/controller_wirelessnetworks.html +0 -2
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/device/base.html +0 -2
- nautobot/dcim/templates/dcim/device/consoleports.html +0 -2
- nautobot/dcim/templates/dcim/device/consoleserverports.html +0 -2
- nautobot/dcim/templates/dcim/device/devicebays.html +0 -2
- nautobot/dcim/templates/dcim/device/frontports.html +0 -2
- nautobot/dcim/templates/dcim/device/interfaces.html +0 -2
- nautobot/dcim/templates/dcim/device/inventory.html +0 -2
- nautobot/dcim/templates/dcim/device/modulebays.html +0 -2
- nautobot/dcim/templates/dcim/device/poweroutlets.html +0 -2
- nautobot/dcim/templates/dcim/device/powerports.html +0 -2
- nautobot/dcim/templates/dcim/device/rearports.html +0 -2
- nautobot/dcim/templates/dcim/device/wireless.html +0 -2
- nautobot/dcim/templates/dcim/device_component.html +0 -2
- nautobot/dcim/templates/dcim/device_edit.html +0 -2
- nautobot/dcim/templates/dcim/devicefamily_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/deviceredundancygroup_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/devicetype.html +0 -2
- nautobot/dcim/templates/dcim/devicetype_edit.html +0 -2
- nautobot/dcim/templates/dcim/devicetype_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/inc/device_napalm_tabs.html +0 -1
- nautobot/dcim/templates/dcim/interfaceredundancygroup_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/location.html +0 -2
- nautobot/dcim/templates/dcim/location_edit.html +0 -2
- nautobot/dcim/templates/dcim/location_retrieve.html +0 -243
- nautobot/dcim/templates/dcim/locationtype.html +0 -2
- nautobot/dcim/templates/dcim/locationtype_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/manufacturer.html +0 -2
- nautobot/dcim/templates/dcim/modulebay_retrieve.html +0 -1
- nautobot/dcim/templates/dcim/platform.html +0 -2
- nautobot/dcim/templates/dcim/powerfeed.html +0 -2
- nautobot/dcim/templates/dcim/powerfeed_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/powerpanel.html +0 -2
- nautobot/dcim/templates/dcim/powerpanel_edit.html +0 -2
- nautobot/dcim/templates/dcim/powerpanel_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/rack.html +0 -2
- nautobot/dcim/templates/dcim/rack_edit.html +0 -2
- nautobot/dcim/templates/dcim/rackgroup.html +0 -2
- nautobot/dcim/templates/dcim/rackreservation.html +0 -2
- nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/softwareversion_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/virtualchassis.html +0 -2
- nautobot/dcim/templates/dcim/virtualchassis_add.html +0 -2
- nautobot/dcim/templates/dcim/virtualchassis_edit.html +0 -2
- nautobot/dcim/templates/dcim/virtualchassis_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +0 -2
- nautobot/dcim/ui.py +0 -29
- nautobot/extras/templates/extras/computedfield.html +0 -2
- nautobot/extras/templates/extras/computedfield_retrieve.html +0 -2
- nautobot/extras/templates/extras/configcontext.html +0 -2
- nautobot/extras/templates/extras/configcontext_edit.html +0 -2
- nautobot/extras/templates/extras/configcontext_retrieve.html +0 -2
- nautobot/extras/templates/extras/configcontextschema.html +0 -2
- nautobot/extras/templates/extras/configcontextschema_edit.html +0 -2
- nautobot/extras/templates/extras/contact_retrieve.html +0 -2
- nautobot/extras/templates/extras/customfield.html +0 -2
- nautobot/extras/templates/extras/customfield_edit.html +0 -2
- nautobot/extras/templates/extras/customfield_retrieve.html +0 -2
- nautobot/extras/templates/extras/customlink.html +0 -2
- nautobot/extras/templates/extras/dynamicgroup.html +0 -2
- nautobot/extras/templates/extras/dynamicgroup_edit.html +0 -2
- nautobot/extras/templates/extras/exporttemplate.html +0 -2
- nautobot/extras/templates/extras/gitrepository.html +0 -2
- nautobot/extras/templates/extras/gitrepository_object_edit.html +0 -2
- nautobot/extras/templates/extras/graphqlquery.html +0 -2
- nautobot/extras/templates/extras/graphqlquery_list.html +0 -1
- nautobot/extras/templates/extras/graphqlquery_retrieve.html +0 -97
- nautobot/extras/templates/extras/job_detail.html +0 -2
- nautobot/extras/templates/extras/jobbutton_retrieve.html +0 -2
- nautobot/extras/templates/extras/jobhook.html +0 -2
- nautobot/extras/templates/extras/jobqueue_retrieve.html +0 -2
- nautobot/extras/templates/extras/jobresult.html +0 -2
- nautobot/extras/templates/extras/metadatatype_retrieve.html +0 -2
- nautobot/extras/templates/extras/note.html +0 -2
- nautobot/extras/templates/extras/note_retrieve.html +0 -1
- nautobot/extras/templates/extras/object_changelog.html +0 -2
- nautobot/extras/templates/extras/object_notes.html +0 -2
- nautobot/extras/templates/extras/objectchange.html +0 -2
- nautobot/extras/templates/extras/objectchange_list.html +0 -3
- nautobot/extras/templates/extras/relationship.html +0 -1
- nautobot/extras/templates/extras/secret.html +0 -1
- nautobot/extras/templates/extras/secret_edit.html +0 -1
- nautobot/extras/templates/extras/secretsgroup.html +0 -2
- nautobot/extras/templates/extras/secretsgroup_edit.html +0 -2
- nautobot/extras/templates/extras/secretsgroup_retrieve.html +0 -2
- nautobot/extras/templates/extras/status.html +0 -2
- nautobot/extras/templates/extras/tag.html +0 -2
- nautobot/extras/templates/extras/tag_edit.html +0 -2
- nautobot/extras/templates/extras/tag_retrieve.html +0 -2
- nautobot/extras/templates/extras/team_retrieve.html +0 -2
- nautobot/ipam/templates/ipam/inc/prefix_header_extra_content_table.html +0 -4
- nautobot/ipam/templates/ipam/namespace_retrieve.html +0 -1
- nautobot/ipam/templates/ipam/prefix.html +0 -2
- nautobot/ipam/templates/ipam/prefix_edit.html +0 -1
- nautobot/ipam/templates/ipam/prefix_retrieve.html +0 -2
- nautobot/ipam/templates/ipam/rir.html +0 -2
- nautobot/ipam/templates/ipam/routetarget.html +0 -1
- nautobot/ipam/templates/ipam/service.html +0 -2
- nautobot/ipam/templates/ipam/service_edit.html +0 -2
- nautobot/ipam/templates/ipam/service_retrieve.html +0 -2
- nautobot/ipam/templates/ipam/vlan.html +0 -2
- nautobot/ipam/templates/ipam/vlan_edit.html +0 -2
- nautobot/ipam/templates/ipam/vlan_retrieve.html +0 -2
- nautobot/ipam/templates/ipam/vlangroup.html +0 -2
- nautobot/ipam/templates/ipam/vrf.html +0 -1
- nautobot/tenancy/templates/tenancy/tenant.html +0 -2
- nautobot/tenancy/templates/tenancy/tenant_edit.html +0 -2
- nautobot/tenancy/templates/tenancy/tenantgroup.html +0 -2
- nautobot/tenancy/templates/tenancy/tenantgroup_retrieve.html +0 -1
- nautobot/virtualization/templates/virtualization/clustergroup.html +0 -2
- nautobot/virtualization/templates/virtualization/clustertype.html +0 -2
- nautobot/virtualization/templates/virtualization/virtualmachine.html +0 -2
- nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +0 -2
- nautobot/virtualization/templates/virtualization/virtualmachine_retrieve.html +0 -2
- nautobot/wireless/templates/wireless/radioprofile_retrieve.html +0 -2
- nautobot/wireless/templates/wireless/supporteddatarate_retrieve.html +0 -2
- nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +0 -2
- /nautobot/dcim/templates/dcim/{cable.html → cable_retrieve.html} +0 -0
- /nautobot/tenancy/{filters/mixins.py → filter_mixins.py} +0 -0
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/LICENSE.txt +0 -0
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/NOTICE +0 -0
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/WHEEL +0 -0
nautobot/ipam/tests/test_api.py
CHANGED
|
@@ -40,6 +40,7 @@ from nautobot.ipam.models import (
|
|
|
40
40
|
VRFDeviceAssignment,
|
|
41
41
|
VRFPrefixAssignment,
|
|
42
42
|
)
|
|
43
|
+
from nautobot.tenancy.models import Tenant
|
|
43
44
|
from nautobot.virtualization.models import Cluster, ClusterType, VirtualMachine, VMInterface
|
|
44
45
|
|
|
45
46
|
|
|
@@ -57,22 +58,28 @@ class NamespaceTest(APIViewTestCases.APIViewTestCase):
|
|
|
57
58
|
@classmethod
|
|
58
59
|
def setUpTestData(cls):
|
|
59
60
|
location = Location.objects.first()
|
|
61
|
+
tenant = Tenant.objects.first()
|
|
60
62
|
cls.create_data = [
|
|
61
63
|
{
|
|
62
64
|
"name": "Purple Monkey Namespace 1",
|
|
63
|
-
"description": "A
|
|
65
|
+
"description": "A namespace with a tenant and location.",
|
|
64
66
|
"location": location.pk,
|
|
67
|
+
"tenant": tenant.pk,
|
|
65
68
|
},
|
|
66
69
|
{
|
|
67
70
|
"name": "Purple Monkey Namespace 2",
|
|
68
|
-
"description": "A
|
|
69
|
-
"
|
|
71
|
+
"description": "A namespace with a tenant and no location.",
|
|
72
|
+
"tenant": tenant.pk,
|
|
70
73
|
},
|
|
71
74
|
{
|
|
72
75
|
"name": "Purple Monkey Namespace 3",
|
|
73
|
-
"description": "A
|
|
76
|
+
"description": "A namespace with no tenant but with a location.",
|
|
74
77
|
"location": location.pk,
|
|
75
78
|
},
|
|
79
|
+
{
|
|
80
|
+
"name": "Purple Monkey Namespace 4",
|
|
81
|
+
"description": "A namespace with no tenant and no location.",
|
|
82
|
+
},
|
|
76
83
|
]
|
|
77
84
|
cls.bulk_update_data = {
|
|
78
85
|
"description": "A perfectly new description.",
|
|
@@ -194,7 +201,7 @@ class VRFDeviceAssignmentTest(APIViewTestCases.APIViewTestCase):
|
|
|
194
201
|
},
|
|
195
202
|
{
|
|
196
203
|
"vrf": cls.vrfs[4].pk,
|
|
197
|
-
"virtual_device_context": cls.vdcs[
|
|
204
|
+
"virtual_device_context": cls.vdcs[1].pk,
|
|
198
205
|
},
|
|
199
206
|
]
|
|
200
207
|
cls.bulk_update_data = {
|
|
@@ -1619,7 +1626,7 @@ class IPAddressTest(APIViewTestCases.APIViewTestCase):
|
|
|
1619
1626
|
self.assertHttpStatus(ip2, status.HTTP_201_CREATED)
|
|
1620
1627
|
|
|
1621
1628
|
response = self.client.get(
|
|
1622
|
-
self._get_detail_url(nat_inside) + "?depth=1",
|
|
1629
|
+
self._get_detail_url(nat_inside) + "?depth=1&exclude_m2m=false",
|
|
1623
1630
|
**self.header,
|
|
1624
1631
|
)
|
|
1625
1632
|
self.assertHttpStatus(response, status.HTTP_200_OK)
|
|
@@ -17,6 +17,7 @@ from nautobot.ipam.choices import PrefixTypeChoices, ServiceProtocolChoices
|
|
|
17
17
|
from nautobot.ipam.filters import (
|
|
18
18
|
IPAddressFilterSet,
|
|
19
19
|
IPAddressToInterfaceFilterSet,
|
|
20
|
+
NamespaceFilterSet,
|
|
20
21
|
PrefixFilterSet,
|
|
21
22
|
PrefixLocationAssignmentFilterSet,
|
|
22
23
|
RIRFilterSet,
|
|
@@ -54,6 +55,15 @@ from nautobot.virtualization.models import (
|
|
|
54
55
|
)
|
|
55
56
|
|
|
56
57
|
|
|
58
|
+
class NamespaceTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyFilterTestCaseMixin):
|
|
59
|
+
"""Namespace FilterSet tests"""
|
|
60
|
+
|
|
61
|
+
queryset = Namespace.objects.all()
|
|
62
|
+
filterset = NamespaceFilterSet
|
|
63
|
+
tenancy_related_name = "namespaces"
|
|
64
|
+
generic_filter_tests = (("name",),)
|
|
65
|
+
|
|
66
|
+
|
|
57
67
|
class VRFTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyFilterTestCaseMixin):
|
|
58
68
|
"""VRF Filterset tests
|
|
59
69
|
|
|
@@ -177,6 +187,7 @@ class PrefixTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyFilt
|
|
|
177
187
|
["status", "status__id"],
|
|
178
188
|
["status", "status__name"],
|
|
179
189
|
["type"],
|
|
190
|
+
["vpn_tunnel_endpoints", "vpn_tunnel_endpoints__id"],
|
|
180
191
|
)
|
|
181
192
|
|
|
182
193
|
def test_filters_generic(self):
|
|
@@ -220,6 +231,17 @@ class PrefixTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyFilt
|
|
|
220
231
|
all_prefixes = self.queryset.all()
|
|
221
232
|
self.assertQuerysetEqualAndNotEmpty(self.filterset(params, self.queryset).qs, all_prefixes)
|
|
222
233
|
|
|
234
|
+
def test_ancestors(self):
|
|
235
|
+
prefixes = (
|
|
236
|
+
Prefix.objects.create(prefix="10.0.0.0/8", status=Status.objects.get_for_model(Prefix).first()),
|
|
237
|
+
Prefix.objects.create(prefix="10.0.0.0/16", status=Status.objects.get_for_model(Prefix).first()),
|
|
238
|
+
Prefix.objects.create(prefix="10.0.0.0/24", status=Status.objects.get_for_model(Prefix).first()),
|
|
239
|
+
)
|
|
240
|
+
params = {"ancestors": [str(prefixes[2].pk)]}
|
|
241
|
+
filterset = self.filterset(params, self.queryset)
|
|
242
|
+
ancestors = [ancestor.id for ancestor in prefixes[2].ancestors()]
|
|
243
|
+
self.assertQuerysetEqualAndNotEmpty(filterset.qs, self.queryset.filter(id__in=ancestors))
|
|
244
|
+
|
|
223
245
|
|
|
224
246
|
class PrefixLocationAssignmentTestCase(FilterTestCases.FilterTestCase):
|
|
225
247
|
queryset = PrefixLocationAssignment.objects.all()
|
|
@@ -508,7 +530,11 @@ class IPAddressTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyF
|
|
|
508
530
|
queryset = IPAddress.objects.all()
|
|
509
531
|
filterset = IPAddressFilterSet
|
|
510
532
|
tenancy_related_name = "ip_addresses"
|
|
511
|
-
generic_filter_tests = (
|
|
533
|
+
generic_filter_tests = (
|
|
534
|
+
["nat_inside", "nat_inside__id"],
|
|
535
|
+
["services", "services__id"],
|
|
536
|
+
["services", "services__name"],
|
|
537
|
+
)
|
|
512
538
|
|
|
513
539
|
@classmethod
|
|
514
540
|
def setUpTestData(cls):
|
|
@@ -700,6 +726,15 @@ class IPAddressTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyF
|
|
|
700
726
|
nat_inside=ip1,
|
|
701
727
|
)
|
|
702
728
|
|
|
729
|
+
services = (
|
|
730
|
+
Service.objects.create(name="Service 1", protocol="TCP", ports=[80]),
|
|
731
|
+
Service.objects.create(name="Service 2", protocol="UDP", ports=[53]),
|
|
732
|
+
Service.objects.create(name="Service 3", protocol="TCP", ports=[443]),
|
|
733
|
+
)
|
|
734
|
+
services[0].ip_addresses.add(ip0)
|
|
735
|
+
services[1].ip_addresses.add(ip1)
|
|
736
|
+
services[2].ip_addresses.add(ip2)
|
|
737
|
+
|
|
703
738
|
def test_search(self):
|
|
704
739
|
ipv4_octets = self.ipv4_address.host.split(".")
|
|
705
740
|
ipv6_hextets = self.ipv6_address.host.split(":")
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"""Test IPAM forms."""
|
|
2
2
|
|
|
3
3
|
from django.forms import Form
|
|
4
|
-
from django.test import TestCase
|
|
5
4
|
|
|
5
|
+
from nautobot.core.testing import TestCase
|
|
6
6
|
from nautobot.core.testing.forms import FormTestCases
|
|
7
7
|
from nautobot.extras.models import Status
|
|
8
8
|
from nautobot.ipam import forms, models
|
|
@@ -5,9 +5,9 @@ from django.contrib.contenttypes.models import ContentType
|
|
|
5
5
|
from django.core.exceptions import ValidationError
|
|
6
6
|
from django.db import connection, IntegrityError
|
|
7
7
|
from django.db.models import ProtectedError
|
|
8
|
-
from django.test import TestCase
|
|
9
8
|
import netaddr
|
|
10
9
|
|
|
10
|
+
from nautobot.core.testing import TestCase
|
|
11
11
|
from nautobot.core.testing.models import ModelTestCases
|
|
12
12
|
from nautobot.dcim import choices as dcim_choices
|
|
13
13
|
from nautobot.dcim.models import Device, DeviceType, Interface, Location, LocationType, Module, ModuleBay, ModuleType
|
|
@@ -34,7 +34,7 @@ class IPAddressToInterfaceTest(TestCase):
|
|
|
34
34
|
|
|
35
35
|
@classmethod
|
|
36
36
|
def setUpTestData(cls):
|
|
37
|
-
cls.namespace = Namespace.objects.
|
|
37
|
+
cls.namespace = Namespace.objects.create(name="IPAM Models Test Namespace")
|
|
38
38
|
cls.status = Status.objects.get(name="Active")
|
|
39
39
|
cls.prefix = Prefix.objects.create(prefix="192.0.2.0/24", status=cls.status, namespace=cls.namespace)
|
|
40
40
|
cls.test_device = Device.objects.create(
|
|
@@ -172,6 +172,48 @@ class IPAddressToInterfaceTest(TestCase):
|
|
|
172
172
|
IPAddressToInterface.objects.create(vm_interface=None, interface=None, ip_address=ip_addr)
|
|
173
173
|
self.assertIn("Must associate to either an Interface or a VMInterface.", str(cm.exception))
|
|
174
174
|
|
|
175
|
+
def test_m2m_save_signal_prevents_iface_ipaddress_and_vminterface_through_defaults(self):
|
|
176
|
+
"""Test that the m2m save signal prevents a VMInterface from using the same IPAddressToInterface instance as an Interface."""
|
|
177
|
+
ip_addr = IPAddress.objects.create(address="192.0.2.1/24", status=self.status, namespace=self.namespace)
|
|
178
|
+
with self.assertRaises(ValidationError) as cm:
|
|
179
|
+
self.test_int1.ip_addresses.add(ip_addr, through_defaults={"vm_interface": self.test_vmint1})
|
|
180
|
+
|
|
181
|
+
self.assertIn(
|
|
182
|
+
"Cannot use a single instance to associate to both an Interface and a VMInterface.", str(cm.exception)
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
def test_m2m_save_signal_prevents_vminterface_ipaddress_and_interface_through_defaults(self):
|
|
186
|
+
"""Test that the m2m save signal prevents an Interface from using the same IPAddressToInterface instance as a VMInterface."""
|
|
187
|
+
ip_addr = IPAddress.objects.create(address="192.0.2.1/24", status=self.status, namespace=self.namespace)
|
|
188
|
+
with self.assertRaises(ValidationError) as cm:
|
|
189
|
+
self.test_vmint1.ip_addresses.add(ip_addr, through_defaults={"interface": self.test_int1})
|
|
190
|
+
|
|
191
|
+
self.assertIn(
|
|
192
|
+
"Cannot use a single instance to associate to both an Interface and a VMInterface.", str(cm.exception)
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
def test_m2m_save_signal_prevents_ipaddress_interface_and_vminterface_through_defaults(self):
|
|
196
|
+
"""Test that the m2m save signal prevents an Interface being added to an IPAddress with a VMInterface through_defaults."""
|
|
197
|
+
ip_addr = IPAddress.objects.create(address="192.0.2.1/24", status=self.status, namespace=self.namespace)
|
|
198
|
+
|
|
199
|
+
with self.assertRaises(ValidationError) as cm:
|
|
200
|
+
ip_addr.interfaces.add(self.test_int1, through_defaults={"vm_interface": self.test_vmint1})
|
|
201
|
+
|
|
202
|
+
self.assertIn(
|
|
203
|
+
"Cannot use a single instance to associate to both an Interface and a VMInterface.", str(cm.exception)
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
def test_m2m_save_signal_prevents_ipaddress_vminterface_and_interface_through_defaults(self):
|
|
207
|
+
"""Test that the m2m save signal prevents a VMInterface being added to an IPAddress with an Interface through_defaults."""
|
|
208
|
+
ip_addr = IPAddress.objects.create(address="192.0.2.1/24", status=self.status, namespace=self.namespace)
|
|
209
|
+
|
|
210
|
+
with self.assertRaises(ValidationError) as cm:
|
|
211
|
+
ip_addr.vm_interfaces.add(self.test_vmint1, through_defaults={"interface": self.test_int1})
|
|
212
|
+
|
|
213
|
+
self.assertIn(
|
|
214
|
+
"Cannot use a single instance to associate to both an Interface and a VMInterface.", str(cm.exception)
|
|
215
|
+
)
|
|
216
|
+
|
|
175
217
|
def test_primary_ip_retained_when_deleted_from_device_or_module_interface(self):
|
|
176
218
|
"""Test primary_ip4 remains set when the same IP is assigned to multiple interfaces and deleted from one."""
|
|
177
219
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
from django.test import TestCase
|
|
2
|
-
|
|
3
1
|
from nautobot.core.models.querysets import count_related
|
|
2
|
+
from nautobot.core.testing import TestCase
|
|
4
3
|
from nautobot.dcim.models.locations import Location
|
|
5
4
|
from nautobot.ipam.models import Prefix
|
|
6
5
|
from nautobot.ipam.tables import PrefixTable
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
from django.test import TestCase
|
|
2
1
|
import netaddr
|
|
3
2
|
|
|
4
3
|
from nautobot.core.forms.utils import parse_numeric_range
|
|
4
|
+
from nautobot.core.testing import TestCase
|
|
5
5
|
from nautobot.extras.models import Status
|
|
6
6
|
from nautobot.ipam.models import IPAddress, Namespace, Prefix, VLAN, VLANGroup
|
|
7
7
|
from nautobot.ipam.utils import add_available_ipaddresses, add_available_vlans
|
|
@@ -51,17 +51,7 @@ from nautobot.users.models import ObjectPermission
|
|
|
51
51
|
from nautobot.virtualization.models import Cluster, ClusterType, VirtualMachine
|
|
52
52
|
|
|
53
53
|
|
|
54
|
-
class NamespaceTestCase(
|
|
55
|
-
ViewTestCases.GetObjectViewTestCase,
|
|
56
|
-
ViewTestCases.GetObjectChangelogViewTestCase,
|
|
57
|
-
ViewTestCases.GetObjectNotesViewTestCase,
|
|
58
|
-
ViewTestCases.CreateObjectViewTestCase,
|
|
59
|
-
ViewTestCases.EditObjectViewTestCase,
|
|
60
|
-
ViewTestCases.DeleteObjectViewTestCase,
|
|
61
|
-
ViewTestCases.ListObjectsViewTestCase,
|
|
62
|
-
ViewTestCases.BulkEditObjectsViewTestCase,
|
|
63
|
-
ViewTestCases.BulkDeleteObjectsViewTestCase,
|
|
64
|
-
):
|
|
54
|
+
class NamespaceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
65
55
|
model = Namespace
|
|
66
56
|
custom_action_required_permissions = {
|
|
67
57
|
"ipam:namespace_vrfs": ["ipam.view_namespace", "ipam.view_vrf"],
|
|
@@ -72,11 +62,18 @@ class NamespaceTestCase(
|
|
|
72
62
|
@classmethod
|
|
73
63
|
def setUpTestData(cls):
|
|
74
64
|
locations = Location.objects.get_for_model(Namespace)
|
|
65
|
+
tenants = Tenant.objects.all()[:2]
|
|
75
66
|
|
|
76
|
-
cls.form_data = {
|
|
67
|
+
cls.form_data = {
|
|
68
|
+
"name": "Namespace X",
|
|
69
|
+
"location": locations[0].pk,
|
|
70
|
+
"tenant": tenants[0].pk,
|
|
71
|
+
"description": "A new Namespace",
|
|
72
|
+
}
|
|
77
73
|
|
|
78
74
|
cls.bulk_edit_data = {
|
|
79
75
|
"description": "New description",
|
|
76
|
+
"tenant": tenants[1].pk,
|
|
80
77
|
"location": locations[1].pk,
|
|
81
78
|
}
|
|
82
79
|
|
|
@@ -165,7 +162,7 @@ class RIRTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
|
|
165
162
|
if count > 1:
|
|
166
163
|
self.assertBodyContains(
|
|
167
164
|
response,
|
|
168
|
-
f'<a href="{prefix_list_url}?{urlencode({"rir": rir.name})}" class="badge">{count}</a>',
|
|
165
|
+
f'<a href="{prefix_list_url}?{urlencode({"rir": rir.name})}" class="badge bg-primary">{count}</a>',
|
|
169
166
|
)
|
|
170
167
|
elif count == 1:
|
|
171
168
|
self.assertBodyContains(response, hyperlinked_object(rir.prefixes.first()))
|
|
@@ -250,7 +247,8 @@ class PrefixTestCase(ViewTestCases.PrimaryObjectViewTestCase, ViewTestCases.List
|
|
|
250
247
|
count = prefix.locations.count()
|
|
251
248
|
if count > 1:
|
|
252
249
|
self.assertBodyContains(
|
|
253
|
-
response,
|
|
250
|
+
response,
|
|
251
|
+
f'<a href="{locations_list_url}?prefixes={prefix.pk}" class="badge bg-primary">{count}</a>',
|
|
254
252
|
)
|
|
255
253
|
elif count == 1:
|
|
256
254
|
self.assertBodyContains(response, hyperlinked_object(prefix.locations.first(), "name"))
|
|
@@ -756,6 +754,7 @@ class IPAddressMergeTestCase(ModelViewTestCase):
|
|
|
756
754
|
self.add_permissions("ipam.change_ipaddress")
|
|
757
755
|
num_ips_before = IPAddress.objects.all().count()
|
|
758
756
|
ips = IPAddress.objects.all().exclude(pk__in=[self.dup_ip_1.pk, self.dup_ip_2.pk, self.dup_ip_3.pk])
|
|
757
|
+
self.assertGreaterEqual(len(ips), 6)
|
|
759
758
|
ip_ct = ContentType.objects.get_for_model(IPAddress)
|
|
760
759
|
locations = Location.objects.all()
|
|
761
760
|
location_ct = ContentType.objects.get_for_model(Location)
|
nautobot/ipam/ui.py
CHANGED
|
@@ -10,29 +10,12 @@ from nautobot.core.ui.object_detail import (
|
|
|
10
10
|
Button,
|
|
11
11
|
KeyValueTablePanel,
|
|
12
12
|
ObjectFieldsPanel,
|
|
13
|
-
ObjectsTablePanel,
|
|
14
13
|
)
|
|
15
14
|
from nautobot.core.views.utils import get_obj_from_context
|
|
16
15
|
|
|
17
16
|
logger = logging.getLogger(__name__)
|
|
18
17
|
|
|
19
18
|
|
|
20
|
-
# TODO: can be removed as a part of NAUTOBOT-1051
|
|
21
|
-
class PrefixChildTablePanel(ObjectsTablePanel):
|
|
22
|
-
def should_render(self, context: Context):
|
|
23
|
-
if not super().should_render(context):
|
|
24
|
-
return False
|
|
25
|
-
return context.get("active_tab") == "prefixes"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
# TODO: can be removed as a part of NAUTOBOT-1051
|
|
29
|
-
class IPAddressTablePanel(ObjectsTablePanel):
|
|
30
|
-
def should_render(self, context: Context):
|
|
31
|
-
if not super().should_render(context):
|
|
32
|
-
return False
|
|
33
|
-
return context.get("active_tab") == "ip-addresses"
|
|
34
|
-
|
|
35
|
-
|
|
36
19
|
class AddChildPrefixButton(Button):
|
|
37
20
|
"""Custom button to add a child prefix inside a Prefix detail view."""
|
|
38
21
|
|
|
@@ -146,7 +146,9 @@ def process_vrfs(apps):
|
|
|
146
146
|
Namespace = apps.get_model("ipam", "Namespace")
|
|
147
147
|
VRF = apps.get_model("ipam", "VRF")
|
|
148
148
|
|
|
149
|
-
global_ns = Namespace.objects.
|
|
149
|
+
global_ns, _ = Namespace.objects.get_or_create(
|
|
150
|
+
name=GLOBAL_NS, defaults={"description": "Default Global namespace. Created by Nautobot."}
|
|
151
|
+
)
|
|
150
152
|
vrfs = VRF.objects.all().order_by("name", "rd")
|
|
151
153
|
unique_non_empty_vrfs = vrfs.filter(enforce_unique=True).exclude(ip_addresses__isnull=True, prefixes__isnull=True)
|
|
152
154
|
# At the point in the migration where we iterate through vrfs in global_ns_vrfs, every vrf that
|
|
@@ -257,6 +259,11 @@ def process_ip_addresses(apps):
|
|
|
257
259
|
broadcast = new_parent_cidr[-1]
|
|
258
260
|
# This can result in duplicate Prefixes being created in the global_ns but that will be
|
|
259
261
|
# cleaned up subsequently in `process_prefix_duplicates`.
|
|
262
|
+
if orphaned_ip.vrf and orphaned_ip.vrf.namespace:
|
|
263
|
+
prefix_namespace = orphaned_ip.vrf.namespace
|
|
264
|
+
else:
|
|
265
|
+
prefix_namespace = global_ns
|
|
266
|
+
|
|
260
267
|
new_parent = Prefix.objects.create(
|
|
261
268
|
ip_version=orphaned_ip.ip_version,
|
|
262
269
|
network=network,
|
|
@@ -264,7 +271,7 @@ def process_ip_addresses(apps):
|
|
|
264
271
|
tenant=orphaned_ip.tenant,
|
|
265
272
|
vrf=orphaned_ip.vrf,
|
|
266
273
|
prefix_length=prefix_length,
|
|
267
|
-
namespace=
|
|
274
|
+
namespace=prefix_namespace,
|
|
268
275
|
description=DESCRIPTION,
|
|
269
276
|
)
|
|
270
277
|
orphaned_ip.parent = new_parent
|
|
@@ -296,6 +303,13 @@ def process_prefix_duplicates(apps):
|
|
|
296
303
|
Prefix = apps.get_model("ipam", "Prefix")
|
|
297
304
|
global_namespace = Namespace.objects.get(name=GLOBAL_NS)
|
|
298
305
|
|
|
306
|
+
# First, assign any remaining prefixes with null namespace to Global namespace
|
|
307
|
+
null_namespace_prefixes = Prefix.objects.filter(namespace__isnull=True)
|
|
308
|
+
if null_namespace_prefixes.exists():
|
|
309
|
+
if "test" not in sys.argv:
|
|
310
|
+
print(f">>> Assigning {null_namespace_prefixes.count()} prefixes with null namespace to Global namespace")
|
|
311
|
+
null_namespace_prefixes.update(namespace=global_namespace)
|
|
312
|
+
|
|
299
313
|
namespaces = list(Namespace.objects.all())
|
|
300
314
|
# Always start with the Global Namespace.
|
|
301
315
|
namespaces.remove(global_namespace)
|
nautobot/ipam/utils/testing.py
CHANGED
|
@@ -5,8 +5,6 @@ import random
|
|
|
5
5
|
from django.apps import apps
|
|
6
6
|
from netaddr import IPNetwork
|
|
7
7
|
|
|
8
|
-
from nautobot.ipam.models import get_default_namespace_pk
|
|
9
|
-
|
|
10
8
|
# Calculate the probabilities to use for the maybe_subdivide() function defined below.
|
|
11
9
|
|
|
12
10
|
# Frequency of IPv4 (leaf, network) Prefixes by each given mask length in a "realistic" data set.
|
|
@@ -129,7 +127,15 @@ def create_prefixes_and_ips(initial_subnet: str, apps=apps, seed="Nautobot"): #
|
|
|
129
127
|
|
|
130
128
|
all_tenants = list(Tenant.objects.all())
|
|
131
129
|
if hasattr(VRF, "namespace"):
|
|
132
|
-
|
|
130
|
+
# Simulate mid-migration state: create Global namespace and assign all VRFs to it
|
|
131
|
+
# This creates more realistic test conditions for namespace-aware migration logic
|
|
132
|
+
Namespace = apps.get_model("ipam", "Namespace")
|
|
133
|
+
global_ns, _ = Namespace.objects.get_or_create(
|
|
134
|
+
name="Global", defaults={"description": "Default Global namespace. Created by Nautobot."}
|
|
135
|
+
)
|
|
136
|
+
# Pre-assign all VRFs to Global namespace to simulate early migration state
|
|
137
|
+
VRF.objects.all().update(namespace=global_ns)
|
|
138
|
+
all_vrfs = list(VRF.objects.filter(namespace_id=global_ns.pk))
|
|
133
139
|
else:
|
|
134
140
|
all_vrfs = list(VRF.objects.all())
|
|
135
141
|
|
nautobot/ipam/views.py
CHANGED
|
@@ -44,6 +44,7 @@ from nautobot.extras.models import Role, SavedView, Status, Tag
|
|
|
44
44
|
from nautobot.ipam.api import serializers
|
|
45
45
|
from nautobot.tenancy.models import Tenant
|
|
46
46
|
from nautobot.virtualization.models import VirtualMachine, VMInterface
|
|
47
|
+
from nautobot.vpn.tables import VPNTunnelEndpointTable
|
|
47
48
|
|
|
48
49
|
from . import filters, forms, tables, ui
|
|
49
50
|
from .models import (
|
|
@@ -241,6 +242,8 @@ class VRFUIViewSet(NautobotUIViewSet):
|
|
|
241
242
|
table_class=tables.VRFDeviceAssignmentTable,
|
|
242
243
|
table_filter="vrf",
|
|
243
244
|
table_title="Assigned Devices",
|
|
245
|
+
related_list_url_name="dcim:device_list",
|
|
246
|
+
related_field_name="vrfs",
|
|
244
247
|
exclude_columns=["vrf", "namespace", "rd"],
|
|
245
248
|
add_button_route=None,
|
|
246
249
|
),
|
|
@@ -350,7 +353,7 @@ class PrefixUIViewSet(NautobotUIViewSet):
|
|
|
350
353
|
ModelBreadcrumbItem(
|
|
351
354
|
model=Prefix,
|
|
352
355
|
reverse_query_params=lambda context: {"namespace": context["object"].namespace.pk},
|
|
353
|
-
|
|
356
|
+
label_type="plural",
|
|
354
357
|
),
|
|
355
358
|
]
|
|
356
359
|
}
|
|
@@ -395,7 +398,7 @@ class PrefixUIViewSet(NautobotUIViewSet):
|
|
|
395
398
|
table_attribute="default_ancestors",
|
|
396
399
|
table_title="Parent Prefixes",
|
|
397
400
|
exclude_columns=["namespace"],
|
|
398
|
-
related_field_name="
|
|
401
|
+
related_field_name="ancestors",
|
|
399
402
|
add_button_route=None,
|
|
400
403
|
paginate=False,
|
|
401
404
|
show_table_config_button=False,
|
|
@@ -406,7 +409,8 @@ class PrefixUIViewSet(NautobotUIViewSet):
|
|
|
406
409
|
table_class=tables.VRFPrefixAssignmentTable,
|
|
407
410
|
table_attribute="vrf_assignments",
|
|
408
411
|
table_title="Assigned VRFs",
|
|
409
|
-
related_field_name="
|
|
412
|
+
related_field_name="prefix",
|
|
413
|
+
related_list_url_name="ipam:vrf_list",
|
|
410
414
|
add_button_route=None,
|
|
411
415
|
paginate=False,
|
|
412
416
|
show_table_config_button=False,
|
|
@@ -418,7 +422,26 @@ class PrefixUIViewSet(NautobotUIViewSet):
|
|
|
418
422
|
table_attribute="cloud_networks",
|
|
419
423
|
table_title="Assigned Cloud Networks",
|
|
420
424
|
exclude_columns=["actions", "assigned_prefix_count", "circuit_count", "cloud_service_count"],
|
|
421
|
-
related_field_name="
|
|
425
|
+
related_field_name="prefixes",
|
|
426
|
+
add_button_route=None,
|
|
427
|
+
paginate=False,
|
|
428
|
+
show_table_config_button=False,
|
|
429
|
+
),
|
|
430
|
+
object_detail.ObjectsTablePanel(
|
|
431
|
+
section=SectionChoices.RIGHT_HALF,
|
|
432
|
+
weight=300,
|
|
433
|
+
table_class=VPNTunnelEndpointTable,
|
|
434
|
+
table_attribute="vpn_tunnel_endpoints",
|
|
435
|
+
table_title="VPN Tunnel Endpoints Protecting Prefix",
|
|
436
|
+
exclude_columns=[
|
|
437
|
+
"vpn_profile",
|
|
438
|
+
"destination_ipaddress",
|
|
439
|
+
"destination_fqdn",
|
|
440
|
+
"protected_prefixes_dg_count",
|
|
441
|
+
"protected_prefixes_count",
|
|
442
|
+
"actions",
|
|
443
|
+
],
|
|
444
|
+
related_field_name="protected_prefixes",
|
|
422
445
|
add_button_route=None,
|
|
423
446
|
paginate=False,
|
|
424
447
|
show_table_config_button=False,
|
|
@@ -432,13 +455,13 @@ class PrefixUIViewSet(NautobotUIViewSet):
|
|
|
432
455
|
related_object_attribute="default_descendants",
|
|
433
456
|
url_name="ipam:prefix_prefixes",
|
|
434
457
|
panels=(
|
|
435
|
-
|
|
458
|
+
object_detail.ObjectsTablePanel(
|
|
436
459
|
section=SectionChoices.FULL_WIDTH,
|
|
437
460
|
weight=100,
|
|
438
461
|
context_table_key="prefix_table",
|
|
439
462
|
add_button_route=None,
|
|
440
463
|
include_paginator=True,
|
|
441
|
-
|
|
464
|
+
related_field_name="within",
|
|
442
465
|
),
|
|
443
466
|
),
|
|
444
467
|
),
|
|
@@ -449,18 +472,24 @@ class PrefixUIViewSet(NautobotUIViewSet):
|
|
|
449
472
|
related_object_attribute="all_ips",
|
|
450
473
|
url_name="ipam:prefix_ipaddresses",
|
|
451
474
|
panels=[
|
|
452
|
-
|
|
475
|
+
object_detail.ObjectsTablePanel(
|
|
453
476
|
section=SectionChoices.FULL_WIDTH,
|
|
454
477
|
weight=100,
|
|
455
478
|
context_table_key="ip_table",
|
|
456
479
|
add_button_route=None,
|
|
457
480
|
include_paginator=True,
|
|
458
|
-
|
|
481
|
+
related_field_name="prefix",
|
|
459
482
|
),
|
|
460
483
|
],
|
|
461
484
|
),
|
|
462
485
|
],
|
|
463
486
|
extra_buttons=[
|
|
487
|
+
object_detail.Button(
|
|
488
|
+
weight=100,
|
|
489
|
+
label="Available",
|
|
490
|
+
render_on_tab_id="prefixes",
|
|
491
|
+
template_path="ipam/inc/toggle_available.html",
|
|
492
|
+
),
|
|
464
493
|
ui.AddChildPrefixButton(
|
|
465
494
|
weight=200,
|
|
466
495
|
label="Add Child Prefix",
|
|
@@ -470,8 +499,14 @@ class PrefixUIViewSet(NautobotUIViewSet):
|
|
|
470
499
|
required_permissions=["ipam.add_prefix"],
|
|
471
500
|
render_on_tab_id="prefixes",
|
|
472
501
|
),
|
|
502
|
+
object_detail.Button(
|
|
503
|
+
weight=100,
|
|
504
|
+
label="Available",
|
|
505
|
+
render_on_tab_id="ip-addresses",
|
|
506
|
+
template_path="ipam/inc/toggle_available.html",
|
|
507
|
+
),
|
|
473
508
|
ui.AddIPAddressButton(
|
|
474
|
-
weight=
|
|
509
|
+
weight=200,
|
|
475
510
|
label="Add an IP Address",
|
|
476
511
|
link_name="ipam:ipaddress_add",
|
|
477
512
|
color=ButtonActionColorChoices.SUBMIT,
|
|
@@ -503,7 +538,6 @@ class PrefixUIViewSet(NautobotUIViewSet):
|
|
|
503
538
|
detail=True,
|
|
504
539
|
url_path="prefixes",
|
|
505
540
|
custom_view_base_action="view",
|
|
506
|
-
custom_view_additional_permissions=["ipam.view_prefix"],
|
|
507
541
|
)
|
|
508
542
|
def prefixes(self, request, *args, **kwargs):
|
|
509
543
|
instance = self.get_object()
|
|
@@ -516,7 +550,9 @@ class PrefixUIViewSet(NautobotUIViewSet):
|
|
|
516
550
|
|
|
517
551
|
prefix_table = tables.PrefixDetailTable(
|
|
518
552
|
child_prefixes,
|
|
553
|
+
configurable=True,
|
|
519
554
|
exclude=["namespace"],
|
|
555
|
+
user=request.user,
|
|
520
556
|
data_transform_callback=data_transform_callback,
|
|
521
557
|
)
|
|
522
558
|
if request.user.has_perm("ipam.change_prefix") or request.user.has_perm("ipam.delete_prefix"):
|
|
@@ -547,6 +583,7 @@ class PrefixUIViewSet(NautobotUIViewSet):
|
|
|
547
583
|
"active_tab": "prefixes",
|
|
548
584
|
"view_action": "prefixes",
|
|
549
585
|
"show_available": request.GET.get("show_available", "true") == "true",
|
|
586
|
+
"badge_count_override": child_prefixes.count(),
|
|
550
587
|
}
|
|
551
588
|
)
|
|
552
589
|
|
|
@@ -568,7 +605,11 @@ class PrefixUIViewSet(NautobotUIViewSet):
|
|
|
568
605
|
)
|
|
569
606
|
|
|
570
607
|
ip_table = tables.IPAddressTable(
|
|
571
|
-
ipaddresses,
|
|
608
|
+
ipaddresses,
|
|
609
|
+
configurable=True,
|
|
610
|
+
exclude=["parent__namespace"],
|
|
611
|
+
user=request.user,
|
|
612
|
+
data_transform_callback=data_transform_callback,
|
|
572
613
|
)
|
|
573
614
|
if request.user.has_perm("ipam.change_ipaddress") or request.user.has_perm("ipam.delete_ipaddress"):
|
|
574
615
|
ip_table.columns.show("pk")
|
|
@@ -597,6 +638,7 @@ class PrefixUIViewSet(NautobotUIViewSet):
|
|
|
597
638
|
"active_tab": "ip-addresses",
|
|
598
639
|
"view_action": "ip_addresses",
|
|
599
640
|
"show_available": request.GET.get("show_available", "true") == "true",
|
|
641
|
+
"badge_count_override": ipaddresses.count(),
|
|
600
642
|
}
|
|
601
643
|
)
|
|
602
644
|
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""REST API module for load_balancers app."""
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""API serializers for nautobot_load_balancer_models."""
|
|
2
|
+
|
|
3
|
+
from nautobot.core.api import NautobotModelSerializer, ValidatedModelSerializer
|
|
4
|
+
from nautobot.extras.api.mixins import TaggedModelSerializerMixin
|
|
5
|
+
from nautobot.load_balancers import models
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class VirtualServerSerializer(TaggedModelSerializerMixin, NautobotModelSerializer): # pylint: disable=too-many-ancestors
|
|
9
|
+
"""VirtualServer Serializer."""
|
|
10
|
+
|
|
11
|
+
class Meta:
|
|
12
|
+
"""Meta attributes."""
|
|
13
|
+
|
|
14
|
+
model = models.VirtualServer
|
|
15
|
+
fields = "__all__"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class LoadBalancerPoolSerializer(TaggedModelSerializerMixin, NautobotModelSerializer): # pylint: disable=too-many-ancestors
|
|
19
|
+
"""LoadBalancerPool Serializer."""
|
|
20
|
+
|
|
21
|
+
class Meta:
|
|
22
|
+
"""Meta attributes."""
|
|
23
|
+
|
|
24
|
+
model = models.LoadBalancerPool
|
|
25
|
+
fields = "__all__"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class LoadBalancerPoolMemberSerializer(TaggedModelSerializerMixin, NautobotModelSerializer): # pylint: disable=too-many-ancestors
|
|
29
|
+
"""LoadBalancerPoolMember Serializer."""
|
|
30
|
+
|
|
31
|
+
class Meta:
|
|
32
|
+
"""Meta attributes."""
|
|
33
|
+
|
|
34
|
+
model = models.LoadBalancerPoolMember
|
|
35
|
+
fields = "__all__"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class HealthCheckMonitorSerializer(TaggedModelSerializerMixin, NautobotModelSerializer): # pylint: disable=too-many-ancestors
|
|
39
|
+
"""HealthCheckMonitor Serializer."""
|
|
40
|
+
|
|
41
|
+
class Meta:
|
|
42
|
+
"""Meta attributes."""
|
|
43
|
+
|
|
44
|
+
model = models.HealthCheckMonitor
|
|
45
|
+
fields = "__all__"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class CertificateProfileSerializer(TaggedModelSerializerMixin, NautobotModelSerializer): # pylint: disable=too-many-ancestors
|
|
49
|
+
"""CertificateProfile Serializer."""
|
|
50
|
+
|
|
51
|
+
class Meta:
|
|
52
|
+
"""Meta attributes."""
|
|
53
|
+
|
|
54
|
+
model = models.CertificateProfile
|
|
55
|
+
fields = "__all__"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class VirtualServerCertificateProfileAssignmentSerializer(ValidatedModelSerializer): # pylint: disable=too-many-ancestors
|
|
59
|
+
"""VirtualServerCertificateProfileAssignment Serializer."""
|
|
60
|
+
|
|
61
|
+
class Meta:
|
|
62
|
+
"""Meta attributes."""
|
|
63
|
+
|
|
64
|
+
model = models.VirtualServerCertificateProfileAssignment
|
|
65
|
+
fields = "__all__"
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class LoadBalancerPoolMemberCertificateProfileAssignmentSerializer(ValidatedModelSerializer): # pylint: disable=too-many-ancestors
|
|
69
|
+
"""LoadBalancerPoolMemberCertificateProfileAssignment Serializer."""
|
|
70
|
+
|
|
71
|
+
class Meta:
|
|
72
|
+
"""Meta attributes."""
|
|
73
|
+
|
|
74
|
+
model = models.LoadBalancerPoolMemberCertificateProfileAssignment
|
|
75
|
+
fields = "__all__"
|