nautobot 2.3.16__py3-none-any.whl → 2.4.0b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of nautobot might be problematic. Click here for more details.
- nautobot/__init__.py +15 -0
- nautobot/apps/api.py +0 -2
- nautobot/apps/config.py +32 -3
- nautobot/apps/events.py +19 -0
- nautobot/apps/exceptions.py +0 -2
- nautobot/apps/ui.py +44 -9
- nautobot/apps/utils.py +0 -8
- nautobot/apps/views.py +2 -0
- nautobot/circuits/navigation.py +0 -57
- nautobot/circuits/tables.py +1 -2
- nautobot/circuits/templates/circuits/circuit_retrieve.html +0 -71
- nautobot/circuits/templates/circuits/inc/circuit_termination.html +6 -64
- nautobot/circuits/templates/circuits/inc/circuit_termination_cable_fragment.html +40 -0
- nautobot/circuits/templates/circuits/inc/circuit_termination_header_extra_content.html +26 -0
- nautobot/circuits/templates/circuits/provider_retrieve.html +0 -76
- nautobot/circuits/tests/integration/test_relationships.py +33 -24
- nautobot/circuits/tests/test_filters.py +4 -8
- nautobot/circuits/views.py +143 -26
- nautobot/cloud/factory.py +4 -1
- nautobot/cloud/models.py +1 -1
- nautobot/cloud/tests/test_filters.py +5 -4
- nautobot/core/api/fields.py +5 -5
- nautobot/core/api/metadata.py +28 -256
- nautobot/core/api/pagination.py +3 -2
- nautobot/core/api/renderers.py +3 -0
- nautobot/core/api/serializers.py +24 -244
- nautobot/core/api/urls.py +3 -4
- nautobot/core/api/utils.py +0 -62
- nautobot/core/api/views.py +48 -158
- nautobot/core/apps/__init__.py +22 -578
- nautobot/core/celery/__init__.py +13 -0
- nautobot/core/celery/log.py +4 -4
- nautobot/core/celery/schedulers.py +48 -3
- nautobot/core/cli/__init__.py +8 -0
- nautobot/core/constants.py +7 -0
- nautobot/core/events/__init__.py +116 -0
- nautobot/core/events/base.py +27 -0
- nautobot/core/events/exceptions.py +10 -0
- nautobot/core/events/redis_broker.py +48 -0
- nautobot/core/events/syslog_broker.py +19 -0
- nautobot/core/exceptions.py +0 -6
- nautobot/core/filters.py +16 -21
- nautobot/core/fixtures/user-data.json +59 -0
- nautobot/core/forms/fields.py +53 -8
- nautobot/core/forms/utils.py +2 -1
- nautobot/core/graphql/schema.py +3 -1
- nautobot/core/graphql/types.py +1 -1
- nautobot/core/jobs/__init__.py +4 -4
- nautobot/core/jobs/cleanup.py +13 -49
- nautobot/core/jobs/groups.py +1 -1
- nautobot/core/management/commands/generate_test_data.py +21 -0
- nautobot/core/management/commands/validate_models.py +1 -1
- nautobot/core/middleware.py +16 -0
- nautobot/core/models/__init__.py +1 -1
- nautobot/core/models/fields.py +11 -7
- nautobot/core/models/query_functions.py +2 -2
- nautobot/core/models/tree_queries.py +3 -6
- nautobot/core/settings.py +44 -7
- nautobot/core/settings.yaml +86 -8
- nautobot/core/tables.py +15 -65
- nautobot/core/tasks.py +1 -1
- nautobot/core/templates/components/button/default.html +7 -0
- nautobot/core/templates/components/button/dropdown.html +20 -0
- nautobot/core/templates/components/layout/one_over_two.html +19 -0
- nautobot/core/templates/components/layout/two_over_one.html +19 -0
- nautobot/core/templates/components/panel/body_content_data_table.html +27 -0
- nautobot/core/templates/components/panel/body_content_objects_table.html +4 -0
- nautobot/core/templates/components/panel/body_content_tags.html +6 -0
- nautobot/core/templates/components/panel/body_content_text.html +12 -0
- nautobot/core/templates/components/panel/body_wrapper_generic.html +3 -0
- nautobot/core/templates/components/panel/body_wrapper_key_value_table.html +3 -0
- nautobot/core/templates/components/panel/body_wrapper_table.html +3 -0
- nautobot/core/templates/components/panel/footer_contacts_table.html +20 -0
- nautobot/core/templates/components/panel/footer_content_table.html +14 -0
- nautobot/core/templates/components/panel/grouping_toggle.html +14 -0
- nautobot/core/templates/components/panel/header_extra_content_table.html +3 -0
- nautobot/core/templates/components/panel/panel.html +16 -0
- nautobot/core/templates/components/panel/stats_panel_body.html +8 -0
- nautobot/core/templates/components/tab/content_wrapper.html +3 -0
- nautobot/core/templates/components/tab/label_wrapper.html +5 -0
- nautobot/core/templates/components/tab/label_wrapper_distinct_view.html +3 -0
- nautobot/core/templates/generic/object_retrieve.html +28 -17
- nautobot/core/templates/inc/computed_fields/panel_data.html +4 -7
- nautobot/core/templates/inc/custom_fields/panel.html +2 -2
- nautobot/core/templates/inc/custom_fields/panel_data.html +4 -7
- nautobot/core/templates/inc/footer.html +1 -0
- nautobot/core/templates/inc/media.html +0 -3
- nautobot/core/templates/inc/nav_menu.html +1 -1
- nautobot/core/templates/inc/relationships_panel.html +1 -1
- nautobot/core/templates/nautobot_config.py.j2 +3 -3
- nautobot/core/templates/panel_table.html +12 -0
- nautobot/core/templates/search.html +0 -7
- nautobot/core/templates/utilities/render_jinja2.html +117 -0
- nautobot/core/templatetags/helpers.py +101 -12
- nautobot/core/templatetags/ui_framework.py +40 -0
- nautobot/core/testing/api.py +23 -128
- nautobot/core/testing/context.py +18 -0
- nautobot/core/testing/filters.py +41 -58
- nautobot/core/testing/mixins.py +2 -7
- nautobot/core/testing/views.py +25 -123
- nautobot/core/tests/integration/test_app_home.py +1 -0
- nautobot/core/tests/integration/test_app_navbar.py +1 -0
- nautobot/core/tests/integration/test_filters.py +2 -0
- nautobot/core/tests/integration/test_home.py +1 -0
- nautobot/core/tests/integration/test_navbar.py +1 -0
- nautobot/core/tests/integration/test_view_authentication.py +1 -2
- nautobot/core/tests/nautobot_config.py +198 -0
- nautobot/core/tests/runner.py +3 -3
- nautobot/core/tests/test_api.py +82 -201
- nautobot/core/tests/test_csv.py +3 -25
- nautobot/core/tests/test_events.py +214 -0
- nautobot/core/tests/test_jinja_filters.py +1 -0
- nautobot/core/tests/test_jobs.py +84 -13
- nautobot/core/tests/test_navigations.py +7 -241
- nautobot/core/tests/test_templatetags_helpers.py +16 -0
- nautobot/core/tests/test_ui.py +150 -0
- nautobot/core/tests/test_utils.py +0 -25
- nautobot/core/tests/test_views.py +123 -31
- nautobot/core/ui/__init__.py +0 -0
- nautobot/core/ui/base.py +11 -0
- nautobot/core/ui/choices.py +44 -0
- nautobot/core/ui/homepage.py +167 -0
- nautobot/core/ui/nav.py +279 -0
- nautobot/core/ui/object_detail.py +1841 -0
- nautobot/core/ui/utils.py +36 -0
- nautobot/core/urls.py +4 -9
- nautobot/core/utils/config.py +30 -3
- nautobot/core/utils/lookup.py +20 -13
- nautobot/core/views/__init__.py +6 -1
- nautobot/core/views/generic.py +47 -52
- nautobot/core/views/mixins.py +15 -25
- nautobot/core/views/paginator.py +8 -5
- nautobot/core/views/renderers.py +3 -3
- nautobot/core/views/utils.py +11 -0
- nautobot/core/wsgi.py +3 -3
- nautobot/dcim/api/serializers.py +80 -179
- nautobot/dcim/api/urls.py +5 -0
- nautobot/dcim/api/views.py +17 -4
- nautobot/dcim/apps.py +1 -0
- nautobot/dcim/choices.py +28 -0
- nautobot/dcim/factory.py +58 -0
- nautobot/dcim/filters/__init__.py +197 -24
- nautobot/dcim/forms.py +203 -12
- nautobot/dcim/graphql/types.py +2 -2
- nautobot/dcim/migrations/0063_interfacevdcassignment_virtualdevicecontext_and_more.py +165 -0
- nautobot/dcim/migrations/0064_virtualdevicecontext_status_data_migration.py +28 -0
- nautobot/dcim/migrations/0065_controller_capabilities_and_more.py +29 -0
- nautobot/dcim/migrations/0066_controllermanageddevicegroup_radio_profiles_and_more.py +33 -0
- nautobot/dcim/models/__init__.py +4 -0
- nautobot/dcim/models/device_component_templates.py +2 -2
- nautobot/dcim/models/device_components.py +20 -22
- nautobot/dcim/models/devices.py +173 -4
- nautobot/dcim/models/locations.py +3 -3
- nautobot/dcim/models/power.py +5 -6
- nautobot/dcim/models/racks.py +6 -6
- nautobot/dcim/navigation.py +25 -224
- nautobot/dcim/signals.py +44 -0
- nautobot/dcim/tables/__init__.py +5 -3
- nautobot/dcim/tables/devices.py +96 -2
- nautobot/dcim/tables/devicetypes.py +2 -2
- nautobot/dcim/templates/dcim/controller/base.html +10 -0
- nautobot/dcim/templates/dcim/controller_create.html +1 -0
- nautobot/dcim/templates/dcim/controller_retrieve.html +5 -1
- nautobot/dcim/templates/dcim/controller_wirelessnetworks.html +25 -0
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +66 -0
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +46 -0
- nautobot/dcim/templates/dcim/device/base.html +6 -42
- nautobot/dcim/templates/dcim/device/wireless.html +73 -0
- nautobot/dcim/templates/dcim/device.html +3 -1
- nautobot/dcim/templates/dcim/interface.html +1 -0
- nautobot/dcim/templates/dcim/interface_edit.html +1 -0
- nautobot/dcim/templates/dcim/locationtype.html +0 -107
- nautobot/dcim/templates/dcim/locationtype_retrieve.html +8 -0
- nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +76 -0
- nautobot/dcim/templates/dcim/virtualdevicecontext_update.html +34 -0
- nautobot/dcim/tests/test_api.py +172 -61
- nautobot/dcim/tests/test_filters.py +171 -109
- nautobot/dcim/tests/test_forms.py +2 -51
- nautobot/dcim/tests/test_graphql.py +0 -52
- nautobot/dcim/tests/test_models.py +126 -4
- nautobot/dcim/tests/test_signals.py +1 -0
- nautobot/dcim/tests/test_views.py +103 -11
- nautobot/dcim/urls.py +72 -27
- nautobot/dcim/utils.py +2 -2
- nautobot/dcim/views.py +369 -62
- nautobot/extras/api/customfields.py +2 -2
- nautobot/extras/api/serializers.py +91 -75
- nautobot/extras/api/urls.py +4 -0
- nautobot/extras/api/views.py +78 -15
- nautobot/extras/choices.py +13 -0
- nautobot/extras/constants.py +0 -1
- nautobot/extras/context_managers.py +23 -6
- nautobot/extras/datasources/git.py +4 -1
- nautobot/extras/factory.py +27 -0
- nautobot/extras/filters/__init__.py +59 -0
- nautobot/extras/forms/forms.py +125 -30
- nautobot/extras/forms/mixins.py +3 -11
- nautobot/extras/graphql/types.py +25 -1
- nautobot/extras/group_sync.py +3 -3
- nautobot/extras/health_checks.py +2 -1
- nautobot/extras/jobs.py +62 -26
- nautobot/extras/management/__init__.py +1 -0
- nautobot/extras/management/commands/runjob.py +7 -79
- nautobot/extras/management/commands/runjob_with_job_result.py +46 -0
- nautobot/extras/management/utils.py +87 -0
- nautobot/extras/managers.py +1 -3
- nautobot/extras/migrations/0018_joblog_data_migration.py +9 -7
- nautobot/extras/migrations/0117_create_job_queue_model.py +129 -0
- nautobot/extras/migrations/0118_task_queue_to_job_queue_migration.py +78 -0
- nautobot/extras/migrations/0119_remove_task_queues_from_job_and_queue_from_scheduled_job.py +28 -0
- nautobot/extras/models/__init__.py +4 -0
- nautobot/extras/models/change_logging.py +7 -3
- nautobot/extras/models/customfields.py +11 -12
- nautobot/extras/models/groups.py +9 -13
- nautobot/extras/models/jobs.py +218 -37
- nautobot/extras/models/models.py +2 -2
- nautobot/extras/models/relationships.py +69 -1
- nautobot/extras/models/secrets.py +5 -0
- nautobot/extras/navigation.py +20 -262
- nautobot/extras/plugins/__init__.py +56 -32
- nautobot/extras/plugins/marketplace_manifest.yml +450 -0
- nautobot/extras/plugins/urls.py +1 -0
- nautobot/extras/plugins/views.py +48 -1
- nautobot/extras/signals.py +39 -1
- nautobot/extras/tables.py +40 -6
- nautobot/extras/templates/extras/externalintegration_retrieve.html +0 -47
- nautobot/extras/templates/extras/inc/tags_panel.html +1 -5
- nautobot/extras/templates/extras/job_bulk_edit.html +2 -1
- nautobot/extras/templates/extras/job_detail.html +36 -6
- nautobot/extras/templates/extras/job_edit.html +5 -2
- nautobot/extras/templates/extras/job_list.html +2 -7
- nautobot/extras/templates/extras/jobqueue_retrieve.html +44 -0
- nautobot/extras/templates/extras/marketplace.html +278 -0
- nautobot/extras/templates/extras/plugins_list.html +35 -1
- nautobot/extras/templates/extras/plugins_tiles.html +79 -0
- nautobot/extras/templates/extras/role_retrieve.html +16 -0
- nautobot/extras/templates/extras/secret.html +0 -65
- nautobot/extras/templates/extras/secret_check.js +16 -0
- nautobot/extras/templates/extras/secret_create.html +114 -0
- nautobot/extras/templates/extras/secret_edit.html +1 -114
- nautobot/extras/templates/extras/secretsgroup_edit.html +1 -1
- nautobot/extras/templates/extras/templatetags/plugin_object_detail_tabs.html +2 -0
- nautobot/extras/templatetags/job_buttons.py +5 -4
- nautobot/extras/templatetags/plugins.py +69 -6
- nautobot/extras/test_jobs/api_test_job.py +1 -1
- nautobot/extras/test_jobs/atomic_transaction.py +2 -2
- nautobot/extras/test_jobs/dry_run.py +1 -1
- nautobot/extras/test_jobs/fail.py +5 -5
- nautobot/extras/test_jobs/file_output.py +1 -1
- nautobot/extras/test_jobs/file_upload_fail.py +1 -1
- nautobot/extras/test_jobs/file_upload_pass.py +1 -1
- nautobot/extras/test_jobs/ipaddress_vars.py +1 -3
- nautobot/extras/test_jobs/jobs_module/jobs_submodule/jobs.py +1 -1
- nautobot/extras/test_jobs/location_with_custom_field.py +1 -1
- nautobot/extras/test_jobs/log_redaction.py +1 -1
- nautobot/extras/test_jobs/log_skip_db_logging.py +1 -1
- nautobot/extras/test_jobs/modify_db.py +1 -1
- nautobot/extras/test_jobs/object_var_optional.py +1 -1
- nautobot/extras/test_jobs/object_var_required.py +1 -1
- nautobot/extras/test_jobs/object_vars.py +1 -1
- nautobot/extras/test_jobs/pass.py +3 -3
- nautobot/extras/test_jobs/profiling.py +1 -1
- nautobot/extras/test_jobs/relative_import.py +3 -3
- nautobot/extras/test_jobs/soft_time_limit_greater_than_time_limit.py +1 -1
- nautobot/extras/test_jobs/task_queues.py +1 -1
- nautobot/extras/tests/integration/test_plugin_banner.py +2 -0
- nautobot/extras/tests/test_api.py +157 -55
- nautobot/extras/tests/test_context_managers.py +4 -1
- nautobot/extras/tests/test_customfields.py +1 -1
- nautobot/extras/tests/test_datasources.py +1 -2
- nautobot/extras/tests/test_dynamicgroups.py +1 -1
- nautobot/extras/tests/test_filters.py +219 -535
- nautobot/extras/tests/test_forms.py +1 -20
- nautobot/extras/tests/test_job_variables.py +73 -152
- nautobot/extras/tests/test_jobs.py +43 -54
- nautobot/extras/tests/test_models.py +71 -16
- nautobot/extras/tests/test_relationships.py +5 -2
- nautobot/extras/tests/test_utils.py +23 -2
- nautobot/extras/tests/test_views.py +183 -43
- nautobot/extras/tests/test_webhooks.py +2 -1
- nautobot/extras/urls.py +2 -20
- nautobot/extras/utils.py +118 -4
- nautobot/extras/views.py +203 -92
- nautobot/extras/webhooks.py +5 -2
- nautobot/ipam/api/fields.py +3 -3
- nautobot/ipam/api/serializers.py +36 -137
- nautobot/ipam/api/views.py +93 -62
- nautobot/ipam/lookups.py +62 -101
- nautobot/ipam/models.py +11 -63
- nautobot/ipam/navigation.py +0 -90
- nautobot/ipam/querysets.py +2 -2
- nautobot/ipam/tables.py +6 -20
- nautobot/ipam/templates/ipam/routetarget.html +0 -28
- nautobot/ipam/templates/ipam/vrf.html +0 -47
- nautobot/ipam/tests/test_api.py +8 -419
- nautobot/ipam/tests/test_filters.py +39 -119
- nautobot/ipam/tests/test_forms.py +47 -51
- nautobot/ipam/tests/test_migrations.py +30 -30
- nautobot/ipam/tests/test_models.py +0 -41
- nautobot/ipam/tests/test_querysets.py +1 -63
- nautobot/ipam/urls.py +3 -69
- nautobot/ipam/utils/__init__.py +0 -24
- nautobot/ipam/views.py +153 -198
- nautobot/project-static/css/base.css +38 -3
- nautobot/project-static/docs/404.html +421 -19
- nautobot/project-static/docs/apps/index.html +421 -19
- nautobot/project-static/docs/apps/nautobot-apps.html +421 -19
- nautobot/project-static/docs/assets/extra.css +5 -1
- nautobot/project-static/docs/assets/javascripts/{bundle.88dd0f4e.min.js → bundle.83f73b43.min.js} +2 -2
- nautobot/project-static/docs/assets/javascripts/{bundle.88dd0f4e.min.js.map → bundle.83f73b43.min.js.map} +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +421 -172
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +425 -21
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +424 -22
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +9809 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +424 -63
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +457 -20
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +425 -25
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +457 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +425 -215
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +430 -342
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +5799 -1054
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +421 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +447 -176
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +460 -21
- nautobot/project-static/docs/development/apps/api/configuration-view.html +421 -19
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +421 -19
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +421 -19
- nautobot/project-static/docs/development/apps/api/models/global-search.html +421 -19
- nautobot/project-static/docs/development/apps/api/models/graphql.html +421 -19
- nautobot/project-static/docs/development/apps/api/models/index.html +421 -19
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +421 -19
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +421 -19
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +421 -19
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +421 -19
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +421 -19
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +421 -19
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +421 -19
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +421 -19
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +421 -19
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +424 -41
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +421 -19
- nautobot/project-static/docs/development/apps/api/prometheus.html +421 -19
- nautobot/project-static/docs/development/apps/api/setup.html +425 -155
- nautobot/project-static/docs/development/apps/api/testing.html +421 -19
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +421 -19
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +421 -19
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +421 -19
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +421 -19
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +701 -130
- nautobot/project-static/docs/development/apps/api/views/base-template.html +421 -19
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +421 -19
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +421 -19
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +421 -19
- nautobot/project-static/docs/development/apps/api/views/index.html +423 -20
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +425 -19
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +451 -19
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +421 -19
- nautobot/project-static/docs/development/apps/api/views/notes.html +421 -19
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +421 -19
- nautobot/project-static/docs/development/apps/api/views/urls.html +421 -19
- nautobot/project-static/docs/development/apps/index.html +421 -19
- nautobot/project-static/docs/development/apps/migration/code-updates.html +422 -52
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +422 -20
- nautobot/project-static/docs/development/apps/migration/from-v1.html +421 -19
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +421 -19
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +421 -19
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +421 -19
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +424 -22
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +9219 -0
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +9333 -0
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +9474 -0
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +9517 -0
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +424 -22
- nautobot/project-static/docs/development/core/application-registry.html +421 -19
- nautobot/project-static/docs/development/core/best-practices.html +421 -19
- nautobot/project-static/docs/development/core/bootstrap-ui.html +421 -19
- nautobot/project-static/docs/development/core/caching.html +421 -19
- nautobot/project-static/docs/development/core/controllers.html +423 -19
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +490 -45
- nautobot/project-static/docs/development/core/generic-views.html +421 -19
- nautobot/project-static/docs/development/core/getting-started.html +566 -179
- nautobot/project-static/docs/development/core/homepage.html +432 -30
- nautobot/project-static/docs/development/core/index.html +421 -19
- nautobot/project-static/docs/development/core/local-k8s.html +9453 -0
- nautobot/project-static/docs/development/core/model-checklist.html +424 -22
- nautobot/project-static/docs/development/core/model-features.html +421 -19
- nautobot/project-static/docs/development/core/natural-keys.html +421 -19
- nautobot/project-static/docs/development/core/navigation-menu.html +438 -26
- nautobot/project-static/docs/development/core/release-checklist.html +435 -45
- nautobot/project-static/docs/development/core/role-internals.html +421 -19
- nautobot/project-static/docs/development/core/settings.html +421 -19
- nautobot/project-static/docs/development/core/style-guide.html +421 -19
- nautobot/project-static/docs/development/core/templates.html +431 -22
- nautobot/project-static/docs/development/core/testing.html +421 -19
- nautobot/project-static/docs/development/core/ui-component-framework.html +11020 -0
- nautobot/project-static/docs/development/core/user-preferences.html +424 -22
- nautobot/project-static/docs/development/index.html +421 -19
- nautobot/project-static/docs/development/jobs/index.html +546 -160
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +421 -19
- nautobot/project-static/docs/index.html +421 -19
- nautobot/project-static/docs/media/development/core/ui-component-framework/basic-panel-layout.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/button-example.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/dropdown-button-example.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/grouped-key-value-table-panel-example-1.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/grouped-key-value-table-panel-example-2.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/object-fields-panel-example.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/stats-panel-example.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/table-panels-family.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/text-panels-family.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/ui-framework-example.png +0 -0
- nautobot/project-static/docs/media/models/virtual_device_context_overview.drawio +73 -0
- nautobot/project-static/docs/media/models/virtual_device_context_overview.png +0 -0
- nautobot/project-static/docs/models/dcim/virtualdevicecontext.html +14 -0
- nautobot/project-static/docs/models/extras/jobqueue.html +14 -0
- nautobot/project-static/docs/models/wireless/radioprofile.html +14 -0
- nautobot/project-static/docs/models/wireless/supporteddatarate.html +14 -0
- nautobot/project-static/docs/models/wireless/wirelessnetwork.html +14 -0
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +426 -20
- nautobot/project-static/docs/overview/design_philosophy.html +421 -19
- nautobot/project-static/docs/release-notes/index.html +445 -22
- nautobot/project-static/docs/release-notes/version-1.0.html +421 -19
- nautobot/project-static/docs/release-notes/version-1.1.html +421 -19
- nautobot/project-static/docs/release-notes/version-1.2.html +421 -19
- nautobot/project-static/docs/release-notes/version-1.3.html +421 -19
- nautobot/project-static/docs/release-notes/version-1.4.html +421 -19
- nautobot/project-static/docs/release-notes/version-1.5.html +421 -19
- nautobot/project-static/docs/release-notes/version-1.6.html +634 -667
- nautobot/project-static/docs/release-notes/version-2.0.html +421 -19
- nautobot/project-static/docs/release-notes/version-2.1.html +421 -19
- nautobot/project-static/docs/release-notes/version-2.2.html +421 -19
- nautobot/project-static/docs/release-notes/version-2.3.html +684 -886
- nautobot/project-static/docs/release-notes/version-2.4.html +10007 -0
- nautobot/project-static/docs/requirements.txt +2 -2
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +334 -270
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +421 -19
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +421 -19
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +423 -21
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +433 -32
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +421 -19
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +765 -180
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +421 -19
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +421 -19
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +434 -29
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +421 -19
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +421 -19
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +421 -19
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +421 -19
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +421 -19
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +421 -19
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +421 -19
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +421 -19
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +421 -19
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +421 -19
- nautobot/project-static/docs/user-guide/administration/installation/index.html +426 -20
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +421 -19
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +421 -19
- nautobot/project-static/docs/user-guide/administration/installation/services.html +421 -19
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +421 -19
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +442 -41
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +435 -66
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +435 -66
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +421 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +421 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +421 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +421 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +421 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +421 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +421 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/tables/v2-code-nautobot-app-location.yaml +0 -16
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +421 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +427 -21
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +457 -20
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +447 -22
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +9333 -0
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +424 -22
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +421 -19
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +424 -22
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +9271 -0
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +9175 -0
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +9169 -0
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +9235 -0
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +421 -19
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +421 -19
- nautobot/project-static/docs/user-guide/index.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +424 -22
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +9575 -0
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +424 -22
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +426 -20
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +424 -22
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +9182 -0
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +424 -22
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +424 -22
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +9250 -0
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +424 -22
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +424 -22
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +489 -56
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +421 -19
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +421 -19
- nautobot/project-static/img/jinja_logo.svg +97 -0
- nautobot/project-static/js/forms.js +5 -0
- nautobot/project-static/js/nav_menu.js +2 -1
- nautobot/tenancy/api/serializers.py +0 -2
- nautobot/tenancy/factory.py +1 -1
- nautobot/tenancy/navigation.py +0 -29
- nautobot/tenancy/templates/tenancy/tenant.html +4 -91
- nautobot/tenancy/tests/test_filters.py +29 -134
- nautobot/tenancy/views.py +32 -23
- nautobot/users/admin.py +3 -1
- nautobot/users/api/serializers.py +4 -5
- nautobot/users/api/views.py +1 -1
- nautobot/users/forms.py +19 -0
- nautobot/users/templates/users/preferences.html +22 -0
- nautobot/users/tests/test_filters.py +1 -19
- nautobot/users/tests/test_views.py +57 -0
- nautobot/users/utils.py +8 -0
- nautobot/users/views.py +48 -11
- nautobot/virtualization/api/serializers.py +4 -4
- nautobot/virtualization/filters.py +2 -20
- nautobot/virtualization/navigation.py +0 -48
- nautobot/virtualization/templates/virtualization/clustertype.html +0 -39
- nautobot/virtualization/tests/test_filters.py +57 -183
- nautobot/virtualization/views.py +18 -15
- nautobot/wireless/__init__.py +0 -0
- nautobot/wireless/api/__init__.py +0 -0
- nautobot/wireless/api/serializers.py +44 -0
- nautobot/wireless/api/urls.py +20 -0
- nautobot/wireless/api/views.py +34 -0
- nautobot/wireless/apps.py +8 -0
- nautobot/wireless/choices.py +345 -0
- nautobot/wireless/factory.py +138 -0
- nautobot/wireless/filters.py +167 -0
- nautobot/wireless/forms.py +283 -0
- nautobot/wireless/homepage.py +19 -0
- nautobot/wireless/migrations/0001_initial.py +223 -0
- nautobot/wireless/migrations/__init__.py +0 -0
- nautobot/wireless/models.py +207 -0
- nautobot/wireless/navigation.py +105 -0
- nautobot/wireless/tables.py +244 -0
- nautobot/wireless/templates/wireless/radioprofile_retrieve.html +81 -0
- nautobot/wireless/templates/wireless/supporteddatarate_retrieve.html +26 -0
- nautobot/wireless/templates/wireless/wirelessnetwork_create.html +88 -0
- nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +64 -0
- nautobot/wireless/tests/__init__.py +0 -0
- nautobot/wireless/tests/test_api.py +247 -0
- nautobot/wireless/tests/test_filters.py +54 -0
- nautobot/wireless/tests/test_models.py +22 -0
- nautobot/wireless/tests/test_views.py +378 -0
- nautobot/wireless/urls.py +13 -0
- nautobot/wireless/views.py +129 -0
- {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/METADATA +11 -14
- {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/RECORD +674 -551
- {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/WHEEL +1 -1
- nautobot/core/utils/navigation.py +0 -54
- {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/NOTICE +0 -0
- {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/entry_points.txt +0 -0
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# pylint: disable=no-member # it doesn't recognize the class attributes assigned in common_test_data()
|
|
2
1
|
import uuid
|
|
3
2
|
|
|
4
3
|
from django.contrib.auth import get_user_model
|
|
@@ -45,6 +44,7 @@ from nautobot.dcim.filters import (
|
|
|
45
44
|
InterfaceRedundancyGroupAssociationFilterSet,
|
|
46
45
|
InterfaceRedundancyGroupFilterSet,
|
|
47
46
|
InterfaceTemplateFilterSet,
|
|
47
|
+
InterfaceVDCAssignmentFilterSet,
|
|
48
48
|
InventoryItemFilterSet,
|
|
49
49
|
LocationFilterSet,
|
|
50
50
|
LocationTypeFilterSet,
|
|
@@ -68,6 +68,7 @@ from nautobot.dcim.filters import (
|
|
|
68
68
|
SoftwareImageFileFilterSet,
|
|
69
69
|
SoftwareVersionFilterSet,
|
|
70
70
|
VirtualChassisFilterSet,
|
|
71
|
+
VirtualDeviceContextFilterSet,
|
|
71
72
|
)
|
|
72
73
|
from nautobot.dcim.models import (
|
|
73
74
|
Cable,
|
|
@@ -90,6 +91,7 @@ from nautobot.dcim.models import (
|
|
|
90
91
|
InterfaceRedundancyGroup,
|
|
91
92
|
InterfaceRedundancyGroupAssociation,
|
|
92
93
|
InterfaceTemplate,
|
|
94
|
+
InterfaceVDCAssignment,
|
|
93
95
|
InventoryItem,
|
|
94
96
|
Location,
|
|
95
97
|
LocationType,
|
|
@@ -113,11 +115,13 @@ from nautobot.dcim.models import (
|
|
|
113
115
|
SoftwareImageFile,
|
|
114
116
|
SoftwareVersion,
|
|
115
117
|
VirtualChassis,
|
|
118
|
+
VirtualDeviceContext,
|
|
116
119
|
)
|
|
117
120
|
from nautobot.extras.models import ExternalIntegration, Role, SecretsGroup, Status, Tag
|
|
118
121
|
from nautobot.ipam.models import IPAddress, Namespace, Prefix, Service, VLAN, VLANGroup
|
|
119
122
|
from nautobot.tenancy.models import Tenant
|
|
120
123
|
from nautobot.virtualization.models import Cluster, ClusterType, VirtualMachine
|
|
124
|
+
from nautobot.wireless.models import RadioProfile, WirelessNetwork
|
|
121
125
|
|
|
122
126
|
# Use the proper swappable User model
|
|
123
127
|
User = get_user_model()
|
|
@@ -594,7 +598,6 @@ def common_test_data(cls):
|
|
|
594
598
|
)
|
|
595
599
|
|
|
596
600
|
device_statuses = Status.objects.get_for_model(Device)
|
|
597
|
-
|
|
598
601
|
cls.devices = (
|
|
599
602
|
Device.objects.create(
|
|
600
603
|
name="Device 1",
|
|
@@ -995,11 +998,12 @@ class PathEndpointModelTestMixin:
|
|
|
995
998
|
)
|
|
996
999
|
|
|
997
1000
|
|
|
998
|
-
class LocationTypeFilterSetTestCase(FilterTestCases.
|
|
1001
|
+
class LocationTypeFilterSetTestCase(FilterTestCases.FilterTestCase):
|
|
999
1002
|
queryset = LocationType.objects.all()
|
|
1000
1003
|
filterset = LocationTypeFilterSet
|
|
1001
1004
|
generic_filter_tests = [
|
|
1002
1005
|
("description",),
|
|
1006
|
+
("name",),
|
|
1003
1007
|
("parent", "parent__id"),
|
|
1004
1008
|
("parent", "parent__name"),
|
|
1005
1009
|
]
|
|
@@ -1031,7 +1035,7 @@ class LocationTypeFilterSetTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
|
1031
1035
|
)
|
|
1032
1036
|
|
|
1033
1037
|
|
|
1034
|
-
class LocationFilterSetTestCase(FilterTestCases.
|
|
1038
|
+
class LocationFilterSetTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyFilterTestCaseMixin):
|
|
1035
1039
|
queryset = Location.objects.all()
|
|
1036
1040
|
filterset = LocationFilterSet
|
|
1037
1041
|
tenancy_related_name = "locations"
|
|
@@ -1052,6 +1056,7 @@ class LocationFilterSetTestCase(FilterTestCases.NameOnlyFilterTestCase, FilterTe
|
|
|
1052
1056
|
("longitude",),
|
|
1053
1057
|
("location_type", "location_type__id"),
|
|
1054
1058
|
("location_type", "location_type__name"),
|
|
1059
|
+
("name",),
|
|
1055
1060
|
("parent", "parent__id"),
|
|
1056
1061
|
("parent", "parent__name"),
|
|
1057
1062
|
("physical_address",),
|
|
@@ -1102,17 +1107,13 @@ class LocationFilterSetTestCase(FilterTestCases.NameOnlyFilterTestCase, FilterTe
|
|
|
1102
1107
|
Location.objects.filter(location_type__content_types=ct),
|
|
1103
1108
|
)
|
|
1104
1109
|
|
|
1105
|
-
def test_search(self):
|
|
1106
|
-
value = self.queryset.values_list("pk", flat=True)[0]
|
|
1107
|
-
params = {"q": value}
|
|
1108
|
-
self.assertQuerysetEqualAndNotEmpty(self.filterset(params, self.queryset).qs, self.queryset.filter(pk=value))
|
|
1109
1110
|
|
|
1110
|
-
|
|
1111
|
-
class RackGroupTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
1111
|
+
class RackGroupTestCase(FilterTestCases.FilterTestCase):
|
|
1112
1112
|
queryset = RackGroup.objects.all()
|
|
1113
1113
|
filterset = RackGroupFilterSet
|
|
1114
1114
|
generic_filter_tests = [
|
|
1115
1115
|
("description",),
|
|
1116
|
+
("name",),
|
|
1116
1117
|
("parent", "parent__id"),
|
|
1117
1118
|
("parent", "parent__name"),
|
|
1118
1119
|
("power_panels", "power_panels__id"),
|
|
@@ -1231,11 +1232,6 @@ class RackTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyFilter
|
|
|
1231
1232
|
params = {"outer_unit": [RackDimensionUnitChoices.UNIT_MILLIMETER]}
|
|
1232
1233
|
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
|
1233
1234
|
|
|
1234
|
-
def test_search(self):
|
|
1235
|
-
value = self.queryset.values_list("pk", flat=True)[0]
|
|
1236
|
-
params = {"q": value}
|
|
1237
|
-
self.assertEqual(self.filterset(params, self.queryset).qs.values_list("pk", flat=True)[0], value)
|
|
1238
|
-
|
|
1239
1235
|
|
|
1240
1236
|
class RackReservationTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyFilterTestCaseMixin):
|
|
1241
1237
|
queryset = RackReservation.objects.all()
|
|
@@ -1255,13 +1251,8 @@ class RackReservationTestCase(FilterTestCases.FilterTestCase, FilterTestCases.Te
|
|
|
1255
1251
|
def setUpTestData(cls):
|
|
1256
1252
|
common_test_data(cls)
|
|
1257
1253
|
|
|
1258
|
-
def test_search(self):
|
|
1259
|
-
value = self.queryset.values_list("pk", flat=True)[0]
|
|
1260
|
-
params = {"q": value}
|
|
1261
|
-
self.assertEqual(self.filterset(params, self.queryset).qs.values_list("pk", flat=True)[0], value)
|
|
1262
1254
|
|
|
1263
|
-
|
|
1264
|
-
class ManufacturerTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
1255
|
+
class ManufacturerTestCase(FilterTestCases.FilterTestCase):
|
|
1265
1256
|
queryset = Manufacturer.objects.all()
|
|
1266
1257
|
filterset = ManufacturerFilterSet
|
|
1267
1258
|
generic_filter_tests = [
|
|
@@ -1270,6 +1261,7 @@ class ManufacturerTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
|
1270
1261
|
("device_types", "device_types__model"),
|
|
1271
1262
|
("inventory_items", "inventory_items__id"),
|
|
1272
1263
|
("inventory_items", "inventory_items__name"),
|
|
1264
|
+
("name",),
|
|
1273
1265
|
("platforms", "platforms__id"),
|
|
1274
1266
|
("platforms", "platforms__name"),
|
|
1275
1267
|
]
|
|
@@ -1285,13 +1277,14 @@ class ManufacturerTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
|
1285
1277
|
InventoryItem.objects.create(device=devices[2], name="Inventory Item 3", manufacturer=cls.manufacturers[2])
|
|
1286
1278
|
|
|
1287
1279
|
|
|
1288
|
-
class DeviceFamilyTestCase(FilterTestCases.
|
|
1280
|
+
class DeviceFamilyTestCase(FilterTestCases.FilterTestCase):
|
|
1289
1281
|
queryset = DeviceFamily.objects.all()
|
|
1290
1282
|
filterset = DeviceFamilyFilterSet
|
|
1291
1283
|
generic_filter_tests = [
|
|
1292
1284
|
("description",),
|
|
1293
1285
|
("device_types", "device_types__id"),
|
|
1294
1286
|
("device_types", "device_types__model"),
|
|
1287
|
+
("name",),
|
|
1295
1288
|
]
|
|
1296
1289
|
|
|
1297
1290
|
|
|
@@ -1481,11 +1474,6 @@ class DeviceTypeTestCase(FilterTestCases.FilterTestCase):
|
|
|
1481
1474
|
self.queryset.exclude(device_bay_templates__isnull=False),
|
|
1482
1475
|
)
|
|
1483
1476
|
|
|
1484
|
-
def test_search(self):
|
|
1485
|
-
value = self.queryset.values_list("pk", flat=True)[0]
|
|
1486
|
-
params = {"q": value}
|
|
1487
|
-
self.assertEqual(self.filterset(params, self.queryset).qs.values_list("pk", flat=True)[0], value)
|
|
1488
|
-
|
|
1489
1477
|
|
|
1490
1478
|
class ConsolePortTemplateTestCase(ModularComponentTemplateTestMixin, FilterTestCases.FilterTestCase):
|
|
1491
1479
|
queryset = ConsolePortTemplate.objects.all()
|
|
@@ -1633,7 +1621,7 @@ class DeviceBayTemplateTestCase(ComponentTemplateTestMixin, FilterTestCases.Filt
|
|
|
1633
1621
|
filterset = DeviceBayTemplateFilterSet
|
|
1634
1622
|
|
|
1635
1623
|
|
|
1636
|
-
class PlatformTestCase(FilterTestCases.
|
|
1624
|
+
class PlatformTestCase(FilterTestCases.FilterTestCase):
|
|
1637
1625
|
queryset = Platform.objects.all()
|
|
1638
1626
|
filterset = PlatformFilterSet
|
|
1639
1627
|
generic_filter_tests = [
|
|
@@ -1641,6 +1629,7 @@ class PlatformTestCase(FilterTestCases.NameOnlyFilterTestCase):
|
|
|
1641
1629
|
("devices", "devices__id"),
|
|
1642
1630
|
("manufacturer", "manufacturer__id"),
|
|
1643
1631
|
("manufacturer", "manufacturer__name"),
|
|
1632
|
+
("name",),
|
|
1644
1633
|
("napalm_driver",),
|
|
1645
1634
|
("virtual_machines", "virtual_machines__id"),
|
|
1646
1635
|
]
|
|
@@ -1702,7 +1691,6 @@ class DeviceTestCase(
|
|
|
1702
1691
|
("front_ports", "front_ports__id"),
|
|
1703
1692
|
("interfaces", "interfaces__id"),
|
|
1704
1693
|
("interfaces", "interfaces__name"),
|
|
1705
|
-
("ip_addresses", "interfaces__ip_addresses__id"),
|
|
1706
1694
|
("mac_address", "interfaces__mac_address"),
|
|
1707
1695
|
("manufacturer", "device_type__manufacturer__id"),
|
|
1708
1696
|
("manufacturer", "device_type__manufacturer__name"),
|
|
@@ -1717,6 +1705,8 @@ class DeviceTestCase(
|
|
|
1717
1705
|
("rack", "rack__name"),
|
|
1718
1706
|
("rack_group", "rack__rack_group__id"),
|
|
1719
1707
|
("rack_group", "rack__rack_group__name"),
|
|
1708
|
+
("radio_profiles", "controller_managed_device_group__radio_profiles__id"),
|
|
1709
|
+
("radio_profiles", "controller_managed_device_group__radio_profiles__name"),
|
|
1720
1710
|
("rear_ports", "rear_ports__id"),
|
|
1721
1711
|
("role", "role__id"),
|
|
1722
1712
|
("role", "role__name"),
|
|
@@ -1732,6 +1722,8 @@ class DeviceTestCase(
|
|
|
1732
1722
|
("vc_priority",),
|
|
1733
1723
|
("virtual_chassis", "virtual_chassis__id"),
|
|
1734
1724
|
("virtual_chassis", "virtual_chassis__name"),
|
|
1725
|
+
("wireless_networks", "controller_managed_device_group__wireless_networks__id"),
|
|
1726
|
+
("wireless_networks", "controller_managed_device_group__wireless_networks__name"),
|
|
1735
1727
|
]
|
|
1736
1728
|
|
|
1737
1729
|
@classmethod
|
|
@@ -1773,6 +1765,14 @@ class DeviceTestCase(
|
|
|
1773
1765
|
Service.objects.create(device=devices[1], name="dns", protocol="udp", ports=[53])
|
|
1774
1766
|
|
|
1775
1767
|
cls.controller_managed_device_groups = list(ControllerManagedDeviceGroup.objects.all()[:2])
|
|
1768
|
+
cls.controller_managed_device_groups[0].radio_profiles.set(RadioProfile.objects.all()[:2])
|
|
1769
|
+
cls.controller_managed_device_groups[0].wireless_networks.set(
|
|
1770
|
+
WirelessNetwork.objects.filter(controller_managed_device_groups__isnull=True)[:2]
|
|
1771
|
+
)
|
|
1772
|
+
cls.controller_managed_device_groups[1].radio_profiles.set(RadioProfile.objects.all()[2:4])
|
|
1773
|
+
cls.controller_managed_device_groups[1].wireless_networks.set(
|
|
1774
|
+
WirelessNetwork.objects.filter(controller_managed_device_groups__isnull=True)[2:4]
|
|
1775
|
+
)
|
|
1776
1776
|
cls.device_redundancy_groups = list(DeviceRedundancyGroup.objects.all()[:2])
|
|
1777
1777
|
Device.objects.filter(pk=devices[0].pk).update(
|
|
1778
1778
|
controller_managed_device_group=cls.controller_managed_device_groups[0],
|
|
@@ -1876,14 +1876,6 @@ class DeviceTestCase(
|
|
|
1876
1876
|
Device.objects.filter(primary_ip4__isnull=True, primary_ip6__isnull=True),
|
|
1877
1877
|
)
|
|
1878
1878
|
|
|
1879
|
-
def test_ip_addresses(self):
|
|
1880
|
-
addresses = list(IPAddress.objects.filter(interfaces__isnull=False)[:2])
|
|
1881
|
-
params = {"ip_addresses": [addresses[0].address, addresses[1].id]}
|
|
1882
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
1883
|
-
self.filterset(params, self.queryset).qs,
|
|
1884
|
-
self.queryset.filter(interfaces__ip_addresses__in=addresses).distinct(),
|
|
1885
|
-
)
|
|
1886
|
-
|
|
1887
1879
|
def test_virtual_chassis_member(self):
|
|
1888
1880
|
# TODO: Not a generic_filter_test because this is a boolean filter but not a RelatedMembershipBooleanFilter
|
|
1889
1881
|
with self.subTest():
|
|
@@ -1929,45 +1921,6 @@ class DeviceTestCase(
|
|
|
1929
1921
|
Device.objects.filter(local_config_context_data__isnull=True),
|
|
1930
1922
|
)
|
|
1931
1923
|
|
|
1932
|
-
def test_search(self):
|
|
1933
|
-
filter_fields = (
|
|
1934
|
-
"name",
|
|
1935
|
-
"serial",
|
|
1936
|
-
"inventory_items__serial",
|
|
1937
|
-
"asset_tag",
|
|
1938
|
-
"device_type__manufacturer__name",
|
|
1939
|
-
"comments",
|
|
1940
|
-
)
|
|
1941
|
-
for filter_field in filter_fields:
|
|
1942
|
-
with self.subTest(f"test q filter by field {filter_field}"):
|
|
1943
|
-
value = (
|
|
1944
|
-
self.queryset.values_list(filter_field, flat=True)
|
|
1945
|
-
.exclude(**{f"{filter_field}__in": ["", None]})
|
|
1946
|
-
.first()
|
|
1947
|
-
)
|
|
1948
|
-
params = {"q": value}
|
|
1949
|
-
# TODO: Remove pylint disable after issue is resolved (see: https://github.com/PyCQA/pylint/issues/7381)
|
|
1950
|
-
# pylint: disable=unsupported-binary-operation
|
|
1951
|
-
qs_filter = (
|
|
1952
|
-
Q(name__icontains=value)
|
|
1953
|
-
| Q(serial__icontains=value.strip())
|
|
1954
|
-
| Q(inventory_items__serial__icontains=value.strip())
|
|
1955
|
-
| Q(asset_tag__icontains=value.strip())
|
|
1956
|
-
| Q(device_type__manufacturer__name__icontains=value.strip())
|
|
1957
|
-
| Q(comments__icontains=value)
|
|
1958
|
-
)
|
|
1959
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
1960
|
-
self.filterset(params, self.queryset).qs,
|
|
1961
|
-
self.queryset.filter(qs_filter),
|
|
1962
|
-
)
|
|
1963
|
-
|
|
1964
|
-
with self.subTest("test q filter by field pk"):
|
|
1965
|
-
value = self.queryset.values_list("pk", flat=True).first()
|
|
1966
|
-
params = {"q": value}
|
|
1967
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
1968
|
-
self.filterset(params, self.queryset).qs, self.queryset.filter(id=value)
|
|
1969
|
-
)
|
|
1970
|
-
|
|
1971
1924
|
|
|
1972
1925
|
class ConsolePortTestCase(PathEndpointModelTestMixin, ModularDeviceComponentTestMixin, FilterTestCases.FilterTestCase):
|
|
1973
1926
|
queryset = ConsolePort.objects.all()
|
|
@@ -2178,7 +2131,6 @@ class InterfaceTestCase(PathEndpointModelTestMixin, ModularDeviceComponentTestMi
|
|
|
2178
2131
|
("child_interfaces", "child_interfaces__name"),
|
|
2179
2132
|
("description",),
|
|
2180
2133
|
# ("device", "device__id"), # TODO - InterfaceFilterSet overrides device as a MultiValueCharFilter on name only
|
|
2181
|
-
("ip_addresses", "ip_addresses__id"),
|
|
2182
2134
|
("label",),
|
|
2183
2135
|
("lag", "lag__id"),
|
|
2184
2136
|
("lag", "lag__name"),
|
|
@@ -2200,6 +2152,8 @@ class InterfaceTestCase(PathEndpointModelTestMixin, ModularDeviceComponentTestMi
|
|
|
2200
2152
|
("tagged_vlans", "tagged_vlans__vid"),
|
|
2201
2153
|
("untagged_vlan", "untagged_vlan__id"),
|
|
2202
2154
|
("untagged_vlan", "untagged_vlan__vid"),
|
|
2155
|
+
("virtual_device_contexts", "virtual_device_contexts__id"),
|
|
2156
|
+
("virtual_device_contexts", "virtual_device_contexts__name"),
|
|
2203
2157
|
]
|
|
2204
2158
|
|
|
2205
2159
|
@classmethod
|
|
@@ -2424,20 +2378,17 @@ class InterfaceTestCase(PathEndpointModelTestMixin, ModularDeviceComponentTestMi
|
|
|
2424
2378
|
status=interface_statuses[3],
|
|
2425
2379
|
)
|
|
2426
2380
|
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
)
|
|
2438
|
-
|
|
2439
|
-
cabled_interfaces[0].add_ip_addresses([ipaddresses[0], ipaddresses[2]])
|
|
2440
|
-
cabled_interfaces[1].add_ip_addresses([ipaddresses[1], ipaddresses[3]])
|
|
2381
|
+
# Virtual Device Context
|
|
2382
|
+
vdc_status = Status.objects.get_for_model(VirtualDeviceContext).first()
|
|
2383
|
+
vdcs = [
|
|
2384
|
+
VirtualDeviceContext.objects.create(
|
|
2385
|
+
device=devices[2], status=vdc_status, identifier=200 + idx, name=f"Test VDC {idx}"
|
|
2386
|
+
)
|
|
2387
|
+
for idx in range(3)
|
|
2388
|
+
]
|
|
2389
|
+
vdcs[0].interfaces.set(lag_interfaces)
|
|
2390
|
+
vdcs[1].interfaces.set(lag_interfaces)
|
|
2391
|
+
vdcs[2].interfaces.set(lag_interfaces)
|
|
2441
2392
|
|
|
2442
2393
|
def test_enabled(self):
|
|
2443
2394
|
# TODO: Not a generic_filter_test because this is a boolean filter but not a RelatedMembershipBooleanFilter
|
|
@@ -2672,14 +2623,6 @@ class InterfaceTestCase(PathEndpointModelTestMixin, ModularDeviceComponentTestMi
|
|
|
2672
2623
|
with self.subTest("device (pk) filter with an invalid uuid"):
|
|
2673
2624
|
self.assertFalse(self.filterset({"device": [uuid.uuid4()]}, self.queryset).is_valid())
|
|
2674
2625
|
|
|
2675
|
-
def test_ip_addresses(self):
|
|
2676
|
-
addresses = list(IPAddress.objects.filter(interfaces__isnull=False)[:2])
|
|
2677
|
-
params = {"ip_addresses": [addresses[0].address, addresses[1].id]}
|
|
2678
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
2679
|
-
self.filterset(params, self.queryset).qs,
|
|
2680
|
-
self.queryset.filter(ip_addresses__in=addresses).distinct(),
|
|
2681
|
-
)
|
|
2682
|
-
|
|
2683
2626
|
def test_kind(self):
|
|
2684
2627
|
# TODO: Not a generic_filter_test because this is a single-value filter
|
|
2685
2628
|
# 2.0 TODO: Support filtering for multiple values
|
|
@@ -3089,11 +3032,6 @@ class InventoryItemTestCase(DeviceComponentTestMixin, FilterTestCases.FilterTest
|
|
|
3089
3032
|
params = {"serial": "abc"}
|
|
3090
3033
|
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
|
|
3091
3034
|
|
|
3092
|
-
def test_search(self):
|
|
3093
|
-
value = self.queryset.values_list("pk", flat=True)[0]
|
|
3094
|
-
params = {"q": value}
|
|
3095
|
-
self.assertEqual(self.filterset(params, self.queryset).qs.values_list("pk", flat=True)[0], value)
|
|
3096
|
-
|
|
3097
3035
|
|
|
3098
3036
|
class VirtualChassisTestCase(FilterTestCases.FilterTestCase):
|
|
3099
3037
|
queryset = VirtualChassis.objects.all()
|
|
@@ -3178,11 +3116,6 @@ class VirtualChassisTestCase(FilterTestCases.FilterTestCase):
|
|
|
3178
3116
|
Device.objects.filter(pk=devices[3].pk).update(virtual_chassis=virtual_chassis[1])
|
|
3179
3117
|
Device.objects.filter(pk=devices[5].pk).update(virtual_chassis=virtual_chassis[2])
|
|
3180
3118
|
|
|
3181
|
-
def test_search(self):
|
|
3182
|
-
value = self.queryset.values_list("pk", flat=True)[0]
|
|
3183
|
-
params = {"q": value}
|
|
3184
|
-
self.assertEqual(self.filterset(params, self.queryset).qs.values_list("pk", flat=True)[0], value)
|
|
3185
|
-
|
|
3186
3119
|
|
|
3187
3120
|
class CableTestCase(FilterTestCases.FilterTestCase):
|
|
3188
3121
|
queryset = Cable.objects.all()
|
|
@@ -3976,6 +3909,8 @@ class ControllerFilterSetTestCase(FilterTestCases.FilterTestCase):
|
|
|
3976
3909
|
("controller_device", "controller_device__name"),
|
|
3977
3910
|
("controller_device_redundancy_group", "controller_device_redundancy_group__id"),
|
|
3978
3911
|
("controller_device_redundancy_group", "controller_device_redundancy_group__name"),
|
|
3912
|
+
("wireless_networks", "controller_managed_device_groups__wireless_networks__id"),
|
|
3913
|
+
("wireless_networks", "controller_managed_device_groups__wireless_networks__name"),
|
|
3979
3914
|
)
|
|
3980
3915
|
|
|
3981
3916
|
@classmethod
|
|
@@ -4118,3 +4053,130 @@ class ModuleBayTestCase(FilterTestCases.FilterTestCase):
|
|
|
4118
4053
|
module_bays = ModuleBay.objects.all()[:2]
|
|
4119
4054
|
module_bays[0].tags.set(Tag.objects.get_for_model(ModuleBay))
|
|
4120
4055
|
module_bays[1].tags.set(Tag.objects.get_for_model(ModuleBay)[:3])
|
|
4056
|
+
|
|
4057
|
+
|
|
4058
|
+
class VirtualDeviceContextTestCase(FilterTestCases.FilterTestCase, FilterTestCases):
|
|
4059
|
+
queryset = VirtualDeviceContext.objects.all()
|
|
4060
|
+
filterset = VirtualDeviceContextFilterSet
|
|
4061
|
+
generic_filter_tests = [
|
|
4062
|
+
("description",),
|
|
4063
|
+
("device", "device__name"),
|
|
4064
|
+
("device", "device__id"),
|
|
4065
|
+
("tenant", "tenant__name"),
|
|
4066
|
+
("tenant", "tenant__id"),
|
|
4067
|
+
("interfaces", "interfaces__id"),
|
|
4068
|
+
("interfaces", "interfaces__name"),
|
|
4069
|
+
("name",),
|
|
4070
|
+
("role", "role__name"),
|
|
4071
|
+
("status", "status__name"),
|
|
4072
|
+
("role", "role__id"),
|
|
4073
|
+
("status", "status__id"),
|
|
4074
|
+
]
|
|
4075
|
+
|
|
4076
|
+
@classmethod
|
|
4077
|
+
def setUpTestData(cls):
|
|
4078
|
+
device = Device.objects.first()
|
|
4079
|
+
intf_status = Status.objects.get_for_model(Interface).first()
|
|
4080
|
+
vdc_status = Status.objects.get_for_model(VirtualDeviceContext).first()
|
|
4081
|
+
intf_role = Role.objects.get_for_model(Interface).first()
|
|
4082
|
+
interface = Interface.objects.create(
|
|
4083
|
+
name="Int1", device=device, status=intf_status, role=intf_role, type=InterfaceTypeChoices.TYPE_100GE_CFP
|
|
4084
|
+
)
|
|
4085
|
+
cls.ips_v4 = IPAddress.objects.filter(ip_version=4)[:3]
|
|
4086
|
+
cls.ips_v6 = IPAddress.objects.filter(ip_version=6)[:3]
|
|
4087
|
+
interface.add_ip_addresses([*cls.ips_v4, *cls.ips_v6])
|
|
4088
|
+
vdcs = [
|
|
4089
|
+
VirtualDeviceContext.objects.create(
|
|
4090
|
+
device=device,
|
|
4091
|
+
status=vdc_status,
|
|
4092
|
+
identifier=200 + idx,
|
|
4093
|
+
name=f"Test VDC {idx}",
|
|
4094
|
+
primary_ip4=cls.ips_v4[idx],
|
|
4095
|
+
primary_ip6=cls.ips_v6[idx],
|
|
4096
|
+
)
|
|
4097
|
+
for idx in range(3)
|
|
4098
|
+
]
|
|
4099
|
+
vdcs[0].tags.set(Tag.objects.get_for_model(VirtualDeviceContext))
|
|
4100
|
+
vdcs[1].tags.set(Tag.objects.get_for_model(VirtualDeviceContext)[:3])
|
|
4101
|
+
|
|
4102
|
+
interfaces = [
|
|
4103
|
+
Interface.objects.create(
|
|
4104
|
+
device=device,
|
|
4105
|
+
type=InterfaceTypeChoices.TYPE_1GE_FIXED,
|
|
4106
|
+
name=f"Interface 00{idx}",
|
|
4107
|
+
status=intf_status,
|
|
4108
|
+
)
|
|
4109
|
+
for idx in range(3)
|
|
4110
|
+
]
|
|
4111
|
+
InterfaceVDCAssignment.objects.create(virtual_device_context=vdcs[0], interface=interfaces[0])
|
|
4112
|
+
InterfaceVDCAssignment.objects.create(virtual_device_context=vdcs[1], interface=interfaces[0])
|
|
4113
|
+
InterfaceVDCAssignment.objects.create(virtual_device_context=vdcs[1], interface=interfaces[1])
|
|
4114
|
+
InterfaceVDCAssignment.objects.create(virtual_device_context=vdcs[2], interface=interfaces[2])
|
|
4115
|
+
|
|
4116
|
+
def test_has_primary_ip(self):
|
|
4117
|
+
# TODO: Not a generic_filter_test because this is a boolean filter but not a RelatedMembershipBooleanFilter
|
|
4118
|
+
with self.subTest():
|
|
4119
|
+
params = {"has_primary_ip": True}
|
|
4120
|
+
self.assertQuerysetEqualAndNotEmpty(
|
|
4121
|
+
self.filterset(params, self.queryset).qs,
|
|
4122
|
+
VirtualDeviceContext.objects.filter(Q(primary_ip4__isnull=False) | Q(primary_ip6__isnull=False)),
|
|
4123
|
+
)
|
|
4124
|
+
with self.subTest():
|
|
4125
|
+
params = {"has_primary_ip": False}
|
|
4126
|
+
self.assertQuerysetEqualAndNotEmpty(
|
|
4127
|
+
self.filterset(params, self.queryset).qs,
|
|
4128
|
+
VirtualDeviceContext.objects.filter(primary_ip4__isnull=True, primary_ip6__isnull=True),
|
|
4129
|
+
)
|
|
4130
|
+
|
|
4131
|
+
def test_primary_ip4(self):
|
|
4132
|
+
params = {"primary_ip4": ["192.0.2.1/24", self.ips_v4[0].pk]}
|
|
4133
|
+
self.assertQuerysetEqualAndNotEmpty(
|
|
4134
|
+
self.filterset(params, self.queryset).qs, VirtualDeviceContext.objects.filter(primary_ip4=self.ips_v4[0])
|
|
4135
|
+
)
|
|
4136
|
+
|
|
4137
|
+
def test_primary_ip6(self):
|
|
4138
|
+
params = {"primary_ip6": ["fe80::8ef:3eff:fe4c:3895/24", self.ips_v6[1].pk]}
|
|
4139
|
+
self.assertQuerysetEqualAndNotEmpty(
|
|
4140
|
+
self.filterset(params, self.queryset).qs, VirtualDeviceContext.objects.filter(primary_ip6=self.ips_v6[1])
|
|
4141
|
+
)
|
|
4142
|
+
|
|
4143
|
+
|
|
4144
|
+
class InterfaceVDCAssignmentTestCase(FilterTestCases.FilterTestCase):
|
|
4145
|
+
queryset = InterfaceVDCAssignment.objects.all()
|
|
4146
|
+
filterset = InterfaceVDCAssignmentFilterSet
|
|
4147
|
+
generic_filter_tests = [
|
|
4148
|
+
("virtual_device_context", "virtual_device_context__id"),
|
|
4149
|
+
("virtual_device_context", "virtual_device_context__name"),
|
|
4150
|
+
("interface", "interface__id"),
|
|
4151
|
+
("interface", "interface__name"),
|
|
4152
|
+
("device", "interface__device__id"),
|
|
4153
|
+
("device", "interface__device__name"),
|
|
4154
|
+
]
|
|
4155
|
+
|
|
4156
|
+
@classmethod
|
|
4157
|
+
def setUpTestData(cls):
|
|
4158
|
+
device = Device.objects.first()
|
|
4159
|
+
vdc_status = Status.objects.get_for_model(VirtualDeviceContext)[0]
|
|
4160
|
+
interface_status = Status.objects.get_for_model(Interface)[0]
|
|
4161
|
+
interfaces = [
|
|
4162
|
+
Interface.objects.create(
|
|
4163
|
+
device=device,
|
|
4164
|
+
type=InterfaceTypeChoices.TYPE_1GE_FIXED,
|
|
4165
|
+
name=f"Interface 00{idx}",
|
|
4166
|
+
status=interface_status,
|
|
4167
|
+
)
|
|
4168
|
+
for idx in range(3)
|
|
4169
|
+
]
|
|
4170
|
+
vdcs = [
|
|
4171
|
+
VirtualDeviceContext.objects.create(
|
|
4172
|
+
device=device,
|
|
4173
|
+
status=vdc_status,
|
|
4174
|
+
identifier=200 + idx,
|
|
4175
|
+
name=f"Test VDC {idx}",
|
|
4176
|
+
)
|
|
4177
|
+
for idx in range(3)
|
|
4178
|
+
]
|
|
4179
|
+
InterfaceVDCAssignment.objects.create(virtual_device_context=vdcs[0], interface=interfaces[0])
|
|
4180
|
+
InterfaceVDCAssignment.objects.create(virtual_device_context=vdcs[1], interface=interfaces[0])
|
|
4181
|
+
InterfaceVDCAssignment.objects.create(virtual_device_context=vdcs[1], interface=interfaces[1])
|
|
4182
|
+
InterfaceVDCAssignment.objects.create(virtual_device_context=vdcs[2], interface=interfaces[2])
|
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
from django.test import TestCase
|
|
2
2
|
|
|
3
3
|
from nautobot.core.testing.forms import FormTestCases
|
|
4
|
-
from nautobot.core.testing.mixins import NautobotTestCaseMixin
|
|
5
4
|
from nautobot.dcim.choices import DeviceFaceChoices, InterfaceModeChoices, InterfaceTypeChoices, RackWidthChoices
|
|
6
|
-
from nautobot.dcim.forms import
|
|
7
|
-
DeviceFilterForm,
|
|
8
|
-
DeviceForm,
|
|
9
|
-
InterfaceBulkEditForm,
|
|
10
|
-
InterfaceCreateForm,
|
|
11
|
-
InterfaceForm,
|
|
12
|
-
RackForm,
|
|
13
|
-
)
|
|
5
|
+
from nautobot.dcim.forms import DeviceFilterForm, DeviceForm, InterfaceCreateForm, InterfaceForm, RackForm
|
|
14
6
|
from nautobot.dcim.models import (
|
|
15
7
|
Device,
|
|
16
8
|
DeviceType,
|
|
@@ -328,7 +320,7 @@ class RackTestCase(TestCase):
|
|
|
328
320
|
self.assertTrue(form.is_valid())
|
|
329
321
|
|
|
330
322
|
|
|
331
|
-
class InterfaceTestCase(
|
|
323
|
+
class InterfaceTestCase(TestCase):
|
|
332
324
|
@classmethod
|
|
333
325
|
def setUpTestData(cls):
|
|
334
326
|
cls.device = Device.objects.first()
|
|
@@ -388,44 +380,3 @@ class InterfaceTestCase(NautobotTestCaseMixin, TestCase):
|
|
|
388
380
|
self.vlan.locations.clear()
|
|
389
381
|
form = InterfaceForm(data=self.data, instance=self.interface)
|
|
390
382
|
self.assertTrue(form.is_valid())
|
|
391
|
-
|
|
392
|
-
def test_untagged_vlans_dropdown_options_align_in_interface_edit_form_and_bulk_edit_form(self):
|
|
393
|
-
"""
|
|
394
|
-
Assert that untagged_vlans field dropdown are populated correctly in InterfaceForm and InterfaceBulkEditForm,
|
|
395
|
-
and that the queryset is the same for both forms.
|
|
396
|
-
"""
|
|
397
|
-
status = Status.objects.get_for_model(Interface).first()
|
|
398
|
-
location = Location.objects.filter(location_type=LocationType.objects.get(name="Campus")).first()
|
|
399
|
-
devices = Device.objects.all()[:3]
|
|
400
|
-
for device in devices:
|
|
401
|
-
device.location = location
|
|
402
|
-
device.save()
|
|
403
|
-
interfaces = (
|
|
404
|
-
Interface.objects.create(
|
|
405
|
-
device=devices[0],
|
|
406
|
-
name="Test Interface 1",
|
|
407
|
-
type=InterfaceTypeChoices.TYPE_2GFC_SFP,
|
|
408
|
-
status=status,
|
|
409
|
-
),
|
|
410
|
-
Interface.objects.create(
|
|
411
|
-
device=devices[1],
|
|
412
|
-
name="Test Interface 2",
|
|
413
|
-
type=InterfaceTypeChoices.TYPE_LAG,
|
|
414
|
-
status=status,
|
|
415
|
-
),
|
|
416
|
-
Interface.objects.create(
|
|
417
|
-
device=devices[2],
|
|
418
|
-
name="Test Interface 3",
|
|
419
|
-
type=InterfaceTypeChoices.TYPE_100ME_FIXED,
|
|
420
|
-
status=status,
|
|
421
|
-
),
|
|
422
|
-
)
|
|
423
|
-
edit_form = InterfaceForm(data=self.data, instance=interfaces[0])
|
|
424
|
-
bulk_edit_form = InterfaceBulkEditForm(
|
|
425
|
-
model=Interface,
|
|
426
|
-
data={"pks": [interface.pk for interface in interfaces]},
|
|
427
|
-
)
|
|
428
|
-
self.assertQuerysetEqualAndNotEmpty(
|
|
429
|
-
edit_form.fields["untagged_vlan"].queryset,
|
|
430
|
-
bulk_edit_form.fields["untagged_vlan"].queryset,
|
|
431
|
-
)
|
|
@@ -83,55 +83,3 @@ class GraphQLTestCase(TestCase):
|
|
|
83
83
|
self.assertEqual(
|
|
84
84
|
resp["data"]["devices"][0]["platform"]["network_driver_mappings"]["scrapli"], "cisco_iosxe"
|
|
85
85
|
)
|
|
86
|
-
|
|
87
|
-
with self.subTest("device serial number query"):
|
|
88
|
-
non_empty_serial_device = Device.objects.first()
|
|
89
|
-
non_empty_serial_device.serial = "1234567890abceFGHIJKL"
|
|
90
|
-
non_empty_serial_device.save()
|
|
91
|
-
|
|
92
|
-
# Test device serial query default behavior: serial__ie
|
|
93
|
-
query = 'query { devices (serial: " ") { name serial } }'
|
|
94
|
-
resp = execute_query(query, user=self.user).to_dict()
|
|
95
|
-
self.assertFalse(resp["data"].get("error"))
|
|
96
|
-
for device in resp["data"]["devices"]:
|
|
97
|
-
self.assertEqual(device["serial"], "")
|
|
98
|
-
|
|
99
|
-
# Test device serial default filter with non-empty serial number
|
|
100
|
-
query = 'query { devices (serial:"' + non_empty_serial_device.serial.lower() + '") { name serial } }'
|
|
101
|
-
resp = execute_query(query, user=self.user).to_dict()
|
|
102
|
-
self.assertFalse(resp["data"].get("error"))
|
|
103
|
-
self.assertEqual(resp["data"]["devices"][0]["serial"], non_empty_serial_device.serial)
|
|
104
|
-
|
|
105
|
-
# Test device serial iexact filter with non-empty serial number
|
|
106
|
-
query = 'query { devices (serial__ie:"' + non_empty_serial_device.serial.upper() + '") { name serial } }'
|
|
107
|
-
resp = execute_query(query, user=self.user).to_dict()
|
|
108
|
-
self.assertFalse(resp["data"].get("error"))
|
|
109
|
-
self.assertEqual(resp["data"]["devices"][0]["serial"], non_empty_serial_device.serial)
|
|
110
|
-
|
|
111
|
-
# Test device serial__nie filter with non-empty serial number
|
|
112
|
-
query = 'query { devices (serial__nie:"' + non_empty_serial_device.serial.lower() + '") { name serial } }'
|
|
113
|
-
resp = execute_query(query, user=self.user).to_dict()
|
|
114
|
-
self.assertFalse(resp["data"].get("error"))
|
|
115
|
-
for device in resp["data"]["devices"]:
|
|
116
|
-
self.assertNotEqual(device["serial"], non_empty_serial_device.serial)
|
|
117
|
-
|
|
118
|
-
# Test device serial__ie filter with empty serial number
|
|
119
|
-
query = 'query { devices (serial__ie:" ") { name serial } }'
|
|
120
|
-
resp = execute_query(query, user=self.user).to_dict()
|
|
121
|
-
self.assertFalse(resp["data"].get("error"))
|
|
122
|
-
for device in resp["data"]["devices"]:
|
|
123
|
-
self.assertEqual(device["serial"], "")
|
|
124
|
-
|
|
125
|
-
# Test device serial__nie filter with empty serial number
|
|
126
|
-
query = 'query { devices (serial__nie:" ") { name serial } }'
|
|
127
|
-
resp = execute_query(query, user=self.user).to_dict()
|
|
128
|
-
self.assertFalse(resp["data"].get("error"))
|
|
129
|
-
for device in resp["data"]["devices"]:
|
|
130
|
-
self.assertNotEqual(device["serial"], "")
|
|
131
|
-
|
|
132
|
-
# Test device serial__n filter with empty serial number
|
|
133
|
-
query = 'query { devices (serial__n:" ") { name serial } }'
|
|
134
|
-
resp = execute_query(query, user=self.user).to_dict()
|
|
135
|
-
self.assertFalse(resp["data"].get("error"))
|
|
136
|
-
for device in resp["data"]["devices"]:
|
|
137
|
-
self.assertNotEqual(device["serial"], "")
|