nautobot 2.4.0b1__py3-none-any.whl → 2.4.1__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/apps/__init__.py +1 -1
- nautobot/apps/api.py +8 -8
- nautobot/apps/change_logging.py +2 -2
- nautobot/apps/choices.py +4 -4
- nautobot/apps/events.py +3 -3
- nautobot/apps/factory.py +2 -2
- nautobot/apps/filters.py +1 -1
- nautobot/apps/forms.py +20 -20
- nautobot/apps/graphql.py +2 -2
- nautobot/apps/jobs.py +8 -8
- nautobot/apps/models.py +19 -19
- nautobot/apps/tables.py +1 -1
- nautobot/apps/testing.py +10 -10
- nautobot/apps/ui.py +2 -2
- nautobot/apps/utils.py +7 -7
- nautobot/apps/views.py +7 -7
- nautobot/circuits/api/serializers.py +1 -0
- nautobot/circuits/api/views.py +4 -8
- nautobot/circuits/tables.py +2 -1
- nautobot/circuits/templates/circuits/circuit_create.html +1 -7
- nautobot/circuits/views.py +3 -3
- nautobot/cloud/api/views.py +6 -10
- nautobot/cloud/models.py +1 -1
- nautobot/cloud/views.py +0 -16
- nautobot/core/api/constants.py +11 -0
- nautobot/core/api/fields.py +5 -5
- nautobot/core/api/filter_backends.py +3 -9
- nautobot/core/api/schema.py +13 -2
- nautobot/core/api/serializers.py +40 -34
- nautobot/core/api/views.py +56 -4
- nautobot/core/celery/log.py +4 -4
- nautobot/core/celery/schedulers.py +2 -2
- nautobot/core/choices.py +2 -2
- nautobot/core/events/__init__.py +3 -3
- nautobot/core/filters.py +67 -35
- nautobot/core/forms/__init__.py +19 -19
- nautobot/core/forms/fields.py +14 -11
- nautobot/core/forms/forms.py +33 -2
- nautobot/core/graphql/types.py +1 -1
- nautobot/core/jobs/__init__.py +28 -7
- nautobot/core/jobs/bulk_actions.py +285 -0
- nautobot/core/jobs/cleanup.py +48 -12
- nautobot/core/jobs/groups.py +1 -1
- nautobot/core/management/commands/validate_models.py +1 -1
- nautobot/core/models/__init__.py +3 -1
- nautobot/core/models/query_functions.py +2 -2
- nautobot/core/models/tree_queries.py +6 -3
- nautobot/core/settings.py +29 -2
- nautobot/core/settings.yaml +21 -0
- nautobot/core/tables.py +79 -61
- nautobot/core/templates/about.html +67 -0
- nautobot/core/templates/inc/media.html +3 -0
- nautobot/core/templates/inc/nav_menu.html +1 -0
- nautobot/core/templates/inc/tenancy_form_panel.html +9 -0
- nautobot/core/templates/inc/tenant_table_row.html +11 -0
- nautobot/core/templates/nautobot_config.py.j2 +13 -0
- nautobot/core/templates/search.html +7 -0
- nautobot/core/templates/utilities/render_jinja2.html +1 -1
- nautobot/core/templates/utilities/templatetags/tag.html +1 -1
- nautobot/core/templates/utilities/theme_preview.html +7 -0
- nautobot/core/templatetags/helpers.py +11 -2
- nautobot/core/testing/__init__.py +8 -8
- nautobot/core/testing/api.py +170 -15
- nautobot/core/testing/filters.py +45 -10
- nautobot/core/testing/forms.py +2 -0
- nautobot/core/testing/integration.py +86 -4
- nautobot/core/testing/mixins.py +7 -2
- nautobot/core/testing/views.py +44 -29
- nautobot/core/tests/integration/test_app_home.py +0 -1
- nautobot/core/tests/integration/test_app_navbar.py +0 -1
- nautobot/core/tests/integration/test_filters.py +0 -2
- nautobot/core/tests/integration/test_home.py +0 -1
- nautobot/core/tests/integration/test_navbar.py +0 -1
- nautobot/core/tests/integration/test_view_authentication.py +1 -0
- nautobot/core/tests/runner.py +1 -1
- nautobot/core/tests/test_api.py +98 -1
- nautobot/core/tests/test_csv.py +25 -3
- nautobot/core/tests/test_filters.py +209 -246
- nautobot/core/tests/test_forms.py +1 -0
- nautobot/core/tests/test_jobs.py +460 -1
- nautobot/core/tests/test_models.py +9 -0
- nautobot/core/tests/test_settings_schema.py +7 -0
- nautobot/core/tests/test_tables.py +100 -0
- nautobot/core/tests/test_utils.py +63 -1
- nautobot/core/tests/test_views.py +30 -3
- nautobot/core/ui/nav.py +1 -0
- nautobot/core/ui/object_detail.py +15 -1
- nautobot/core/urls.py +11 -0
- nautobot/core/utils/lookup.py +11 -8
- nautobot/core/utils/querysets.py +64 -0
- nautobot/core/utils/requests.py +24 -9
- nautobot/core/views/__init__.py +42 -0
- nautobot/core/views/generic.py +131 -197
- nautobot/core/views/mixins.py +126 -38
- nautobot/core/views/renderers.py +6 -6
- nautobot/dcim/api/serializers.py +56 -64
- nautobot/dcim/api/views.py +47 -113
- nautobot/dcim/constants.py +6 -13
- nautobot/dcim/factory.py +6 -1
- nautobot/dcim/filters/__init__.py +31 -2
- nautobot/dcim/forms.py +36 -17
- nautobot/dcim/graphql/types.py +2 -2
- nautobot/dcim/migrations/0067_controllermanageddevicegroup_tenant.py +25 -0
- nautobot/dcim/models/__init__.py +1 -1
- nautobot/dcim/models/device_component_templates.py +2 -2
- nautobot/dcim/models/device_components.py +22 -20
- nautobot/dcim/models/devices.py +10 -1
- nautobot/dcim/models/locations.py +3 -3
- nautobot/dcim/models/power.py +6 -5
- nautobot/dcim/models/racks.py +4 -4
- nautobot/dcim/tables/__init__.py +3 -3
- nautobot/dcim/tables/devices.py +7 -5
- nautobot/dcim/tables/devicetypes.py +2 -2
- nautobot/dcim/tables/racks.py +1 -1
- nautobot/dcim/templates/dcim/controller_create.html +1 -7
- nautobot/dcim/templates/dcim/controller_retrieve.html +1 -9
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +2 -0
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +5 -0
- nautobot/dcim/templates/dcim/device.html +1 -9
- nautobot/dcim/templates/dcim/device_edit.html +36 -37
- nautobot/dcim/templates/dcim/location.html +1 -9
- nautobot/dcim/templates/dcim/location_edit.html +1 -7
- nautobot/dcim/templates/dcim/rack.html +1 -9
- nautobot/dcim/templates/dcim/rack_edit.html +1 -7
- nautobot/dcim/templates/dcim/rackreservation.html +1 -9
- nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +1 -9
- nautobot/dcim/templates/dcim/virtualdevicecontext_update.html +1 -7
- nautobot/dcim/tests/integration/test_controller.py +62 -0
- nautobot/dcim/tests/integration/test_controller_managed_device_group.py +71 -0
- nautobot/dcim/tests/integration/test_device_bulk_delete.py +189 -0
- nautobot/dcim/tests/integration/test_device_bulk_edit.py +181 -0
- nautobot/dcim/tests/test_api.py +16 -5
- nautobot/dcim/tests/test_filters.py +33 -0
- nautobot/dcim/tests/test_forms.py +51 -2
- nautobot/dcim/tests/test_graphql.py +52 -0
- nautobot/dcim/tests/test_jobs.py +118 -0
- nautobot/dcim/tests/test_models.py +52 -9
- nautobot/dcim/tests/test_views.py +21 -83
- nautobot/dcim/views.py +1 -13
- nautobot/extras/api/customfields.py +2 -2
- nautobot/extras/api/serializers.py +90 -85
- nautobot/extras/api/views.py +22 -27
- nautobot/extras/constants.py +2 -0
- nautobot/extras/filters/__init__.py +8 -6
- nautobot/extras/forms/base.py +2 -2
- nautobot/extras/forms/forms.py +139 -31
- nautobot/extras/forms/mixins.py +14 -6
- nautobot/extras/group_sync.py +3 -3
- nautobot/extras/health_checks.py +1 -2
- nautobot/extras/jobs.py +85 -18
- nautobot/extras/managers.py +3 -1
- nautobot/extras/migrations/0018_joblog_data_migration.py +7 -9
- nautobot/extras/migrations/0120_job_is_singleton_job_is_singleton_override.py +22 -0
- nautobot/extras/migrations/0121_alter_team_contacts.py +17 -0
- nautobot/extras/models/__init__.py +1 -1
- nautobot/extras/models/contacts.py +1 -1
- nautobot/extras/models/customfields.py +12 -11
- nautobot/extras/models/groups.py +11 -9
- nautobot/extras/models/jobs.py +23 -4
- nautobot/extras/models/models.py +2 -2
- nautobot/extras/plugins/__init__.py +13 -2
- nautobot/extras/plugins/marketplace_manifest.yml +84 -79
- nautobot/extras/plugins/tables.py +16 -14
- nautobot/extras/plugins/views.py +65 -69
- nautobot/extras/registry.py +1 -1
- nautobot/extras/secrets/__init__.py +2 -2
- nautobot/extras/tables.py +7 -5
- nautobot/extras/templates/extras/dynamicgroup.html +1 -9
- nautobot/extras/templates/extras/job_detail.html +16 -0
- nautobot/extras/templates/extras/job_edit.html +1 -0
- nautobot/extras/templates/extras/jobqueue_retrieve.html +1 -9
- nautobot/extras/templates/extras/marketplace.html +29 -11
- nautobot/extras/templates/extras/plugin_detail.html +32 -15
- nautobot/extras/templates/extras/plugins_tiles.html +21 -10
- nautobot/extras/templatetags/job_buttons.py +4 -4
- 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 +3 -1
- 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/singleton.py +16 -0
- 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 +0 -2
- nautobot/extras/tests/test_api.py +13 -13
- nautobot/extras/tests/test_customfields.py +1 -1
- nautobot/extras/tests/test_datasources.py +2 -1
- nautobot/extras/tests/test_dynamicgroups.py +1 -1
- nautobot/extras/tests/test_filters.py +6 -6
- nautobot/extras/tests/test_forms.py +33 -1
- nautobot/extras/tests/test_jobs.py +178 -32
- nautobot/extras/tests/test_models.py +16 -10
- nautobot/extras/tests/test_plugins.py +62 -9
- nautobot/extras/tests/test_relationships.py +120 -9
- nautobot/extras/tests/test_views.py +56 -194
- nautobot/extras/utils.py +3 -2
- nautobot/extras/views.py +30 -98
- nautobot/ipam/api/fields.py +3 -3
- nautobot/ipam/api/serializers.py +41 -33
- nautobot/ipam/api/views.py +68 -117
- nautobot/ipam/factory.py +1 -1
- nautobot/ipam/filters.py +3 -2
- nautobot/ipam/lookups.py +101 -62
- nautobot/ipam/models.py +66 -16
- nautobot/ipam/querysets.py +2 -2
- nautobot/ipam/tables.py +23 -7
- nautobot/ipam/templates/ipam/ipaddress.html +1 -9
- nautobot/ipam/templates/ipam/ipaddress_bulk_add.html +1 -7
- nautobot/ipam/templates/ipam/ipaddress_edit.html +1 -7
- nautobot/ipam/templates/ipam/prefix.html +1 -9
- nautobot/ipam/templates/ipam/prefix_edit.html +1 -7
- nautobot/ipam/templates/ipam/vlan.html +1 -9
- nautobot/ipam/templates/ipam/vlan_edit.html +1 -7
- nautobot/ipam/templates/ipam/vrf_edit.html +1 -7
- nautobot/ipam/tests/test_api.py +436 -3
- nautobot/ipam/tests/test_forms.py +49 -47
- nautobot/ipam/tests/test_migrations.py +30 -30
- nautobot/ipam/tests/test_models.py +95 -34
- nautobot/ipam/tests/test_querysets.py +63 -1
- nautobot/ipam/tests/test_views.py +3 -0
- nautobot/ipam/utils/__init__.py +36 -6
- nautobot/ipam/views.py +61 -87
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.css.map +1 -1
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.min.css.map +1 -1
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css +40 -2
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css.map +1 -1
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css +1 -1
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css.map +1 -1
- nautobot/project-static/docs/404.html +46 -4
- nautobot/project-static/docs/apps/index.html +46 -4
- nautobot/project-static/docs/apps/nautobot-apps.html +47 -6
- nautobot/project-static/docs/assets/_mkdocstrings.css +25 -1
- nautobot/project-static/docs/assets/javascripts/{bundle.83f73b43.min.js → bundle.88dd0f4e.min.js} +2 -2
- nautobot/project-static/docs/assets/javascripts/{bundle.83f73b43.min.js.map → bundle.88dd0f4e.min.js.map} +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +62 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +59 -7
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +374 -122
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +90 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +95 -21
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +53 -6
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +52 -5
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +79 -17
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +102 -28
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +108 -21
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +131 -38
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +239 -65
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +581 -165
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +109 -36
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +453 -167
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +493 -211
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +60 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +71 -15
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +407 -55
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +620 -205
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +858 -412
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +59 -7
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +448 -186
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +365 -147
- nautobot/project-static/docs/development/apps/api/configuration-view.html +46 -4
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +46 -4
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +46 -4
- nautobot/project-static/docs/development/apps/api/models/global-search.html +46 -4
- nautobot/project-static/docs/development/apps/api/models/graphql.html +46 -4
- nautobot/project-static/docs/development/apps/api/models/index.html +46 -4
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +46 -4
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +46 -4
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +46 -4
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +46 -4
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +46 -4
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +46 -4
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +46 -4
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +46 -4
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +46 -4
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +68 -7
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +46 -4
- nautobot/project-static/docs/development/apps/api/prometheus.html +46 -4
- nautobot/project-static/docs/development/apps/api/setup.html +46 -4
- nautobot/project-static/docs/development/apps/api/testing.html +46 -4
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +46 -4
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +46 -4
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +46 -4
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +46 -4
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +46 -4
- nautobot/project-static/docs/development/apps/api/views/base-template.html +46 -4
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +46 -4
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +46 -4
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +46 -4
- nautobot/project-static/docs/development/apps/api/views/index.html +46 -4
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +46 -4
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +46 -4
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +46 -4
- nautobot/project-static/docs/development/apps/api/views/notes.html +46 -4
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +52 -6
- nautobot/project-static/docs/development/apps/api/views/urls.html +46 -4
- nautobot/project-static/docs/development/apps/index.html +46 -4
- nautobot/project-static/docs/development/apps/migration/code-updates.html +46 -4
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +46 -4
- nautobot/project-static/docs/development/apps/migration/from-v1.html +46 -4
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +46 -4
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +46 -4
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +46 -4
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +46 -4
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +50 -8
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +46 -4
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +211 -14
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +46 -4
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +46 -4
- nautobot/project-static/docs/development/core/application-registry.html +46 -4
- nautobot/project-static/docs/development/core/best-practices.html +46 -4
- nautobot/project-static/docs/development/core/bootstrap-ui.html +46 -4
- nautobot/project-static/docs/development/core/caching.html +46 -4
- nautobot/project-static/docs/development/core/controllers.html +46 -4
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +73 -74
- nautobot/project-static/docs/development/core/generic-views.html +46 -4
- nautobot/project-static/docs/development/core/getting-started.html +249 -224
- nautobot/project-static/docs/development/core/homepage.html +49 -7
- nautobot/project-static/docs/development/core/index.html +46 -4
- nautobot/project-static/docs/development/core/{local-k8s.html → minikube-dev-environment-for-k8s-jobs.html} +469 -168
- nautobot/project-static/docs/development/core/model-checklist.html +56 -12
- nautobot/project-static/docs/development/core/model-features.html +46 -4
- nautobot/project-static/docs/development/core/natural-keys.html +46 -4
- nautobot/project-static/docs/development/core/navigation-menu.html +46 -4
- nautobot/project-static/docs/development/core/release-checklist.html +49 -7
- nautobot/project-static/docs/development/core/role-internals.html +46 -4
- nautobot/project-static/docs/development/core/settings.html +46 -4
- nautobot/project-static/docs/development/core/style-guide.html +49 -7
- nautobot/project-static/docs/development/core/templates.html +46 -4
- nautobot/project-static/docs/development/core/testing.html +46 -4
- nautobot/project-static/docs/development/core/ui-component-framework.html +369 -273
- nautobot/project-static/docs/development/core/user-preferences.html +46 -4
- nautobot/project-static/docs/development/index.html +46 -4
- nautobot/project-static/docs/development/jobs/index.html +216 -122
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +46 -4
- nautobot/project-static/docs/index.html +54 -23
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_edit.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_edit_button.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_list_nav.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_list_view.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue_add.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue_config.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_completed.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_nav.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_pending.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_run_form.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_nautobot_login.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_run_job.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_run_scheduled_job_form.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_scheduled_job_result.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/buttons-example.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/cluster-type-before-after-example.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/object-fields-panel-example_2.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/stats-panel-example-code.png +0 -0
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +47 -7
- nautobot/project-static/docs/overview/design_philosophy.html +46 -4
- nautobot/project-static/docs/release-notes/index.html +52 -12
- nautobot/project-static/docs/release-notes/version-1.0.html +234 -193
- nautobot/project-static/docs/release-notes/version-1.1.html +231 -190
- nautobot/project-static/docs/release-notes/version-1.2.html +306 -265
- nautobot/project-static/docs/release-notes/version-1.3.html +332 -291
- nautobot/project-static/docs/release-notes/version-1.4.html +417 -377
- nautobot/project-static/docs/release-notes/version-1.5.html +605 -566
- nautobot/project-static/docs/release-notes/version-1.6.html +904 -447
- nautobot/project-static/docs/release-notes/version-2.0.html +528 -489
- nautobot/project-static/docs/release-notes/version-2.1.html +363 -324
- nautobot/project-static/docs/release-notes/version-2.2.html +356 -317
- nautobot/project-static/docs/release-notes/version-2.3.html +997 -352
- nautobot/project-static/docs/release-notes/version-2.4.html +525 -101
- nautobot/project-static/docs/requirements.txt +2 -2
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +295 -287
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +46 -4
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +46 -4
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +48 -6
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +46 -4
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +46 -4
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +110 -8
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +46 -4
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +46 -4
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +46 -4
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +46 -4
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +46 -4
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +46 -4
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +46 -4
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +46 -4
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +48 -6
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +46 -4
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +46 -4
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +46 -4
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +66 -8
- nautobot/project-static/docs/user-guide/administration/installation/index.html +46 -4
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +47 -5
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +46 -4
- nautobot/project-static/docs/user-guide/administration/installation/services.html +46 -4
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +46 -4
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +46 -4
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +46 -4
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +46 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +46 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +46 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +46 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +46 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +46 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +49 -8
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +46 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +46 -4
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +50 -12
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +49 -7
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +46 -4
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +46 -4
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +46 -4
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +46 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +46 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +46 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +46 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +46 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +46 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +46 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +46 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +46 -4
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +46 -4
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +51 -7
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +46 -4
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/central-mode.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/device-group-add.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/device-group-create-1.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/device-group-create-2.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/radio-profile-add.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/radio-profile-create.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/supported-data-rate-add.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/supported-data-rate-create.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-controller-add.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-controller-create-1.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-controller-create-2.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-network-add.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-network-create.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +46 -4
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +46 -4
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +49 -7
- nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +9444 -0
- nautobot/project-static/docs/user-guide/index.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +50 -8
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +50 -7
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +49 -7
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +9722 -0
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +47 -5
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +94 -25
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +74 -5
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +46 -4
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +46 -4
- nautobot/project-static/js/forms.js +1 -1
- nautobot/tenancy/api/views.py +9 -13
- nautobot/tenancy/views.py +4 -2
- nautobot/users/admin.py +1 -1
- nautobot/users/api/serializers.py +5 -4
- nautobot/users/api/views.py +3 -3
- nautobot/virtualization/api/serializers.py +4 -4
- nautobot/virtualization/api/views.py +5 -24
- nautobot/virtualization/filters.py +20 -3
- nautobot/virtualization/models.py +1 -1
- nautobot/virtualization/tables.py +2 -2
- nautobot/virtualization/templates/virtualization/cluster_edit.html +1 -7
- nautobot/virtualization/templates/virtualization/virtualmachine.html +1 -9
- nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +2 -8
- nautobot/virtualization/tests/test_filters.py +17 -0
- nautobot/wireless/filters.py +2 -2
- nautobot/wireless/forms.py +1 -1
- nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +1 -9
- nautobot/wireless/tests/integration/__init__.py +0 -0
- nautobot/wireless/tests/integration/test_radio_profile.py +42 -0
- nautobot/wireless/tests/test_filters.py +29 -1
- nautobot/wireless/tests/test_views.py +22 -1
- nautobot/wireless/views.py +0 -10
- {nautobot-2.4.0b1.dist-info → nautobot-2.4.1.dist-info}/METADATA +6 -6
- {nautobot-2.4.0b1.dist-info → nautobot-2.4.1.dist-info}/RECORD +600 -550
- {nautobot-2.4.0b1.dist-info → nautobot-2.4.1.dist-info}/WHEEL +1 -1
- nautobot/core/fixtures/user-data.json +0 -59
- {nautobot-2.4.0b1.dist-info → nautobot-2.4.1.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.4.0b1.dist-info → nautobot-2.4.1.dist-info}/NOTICE +0 -0
- {nautobot-2.4.0b1.dist-info → nautobot-2.4.1.dist-info}/entry_points.txt +0 -0
nautobot/core/testing/views.py
CHANGED
|
@@ -21,17 +21,19 @@ from nautobot.core.models.tree_queries import TreeModel
|
|
|
21
21
|
from nautobot.core.templatetags import helpers
|
|
22
22
|
from nautobot.core.testing import mixins, utils
|
|
23
23
|
from nautobot.core.utils import lookup
|
|
24
|
+
from nautobot.dcim.models.device_components import ComponentModel
|
|
24
25
|
from nautobot.extras import choices as extras_choices, models as extras_models, querysets as extras_querysets
|
|
25
26
|
from nautobot.extras.forms import CustomFieldModelFormMixin, RelationshipModelFormMixin
|
|
26
27
|
from nautobot.extras.models import CustomFieldModel, RelationshipModel
|
|
28
|
+
from nautobot.extras.models.jobs import JobResult
|
|
27
29
|
from nautobot.extras.models.mixins import NotesMixin
|
|
28
30
|
from nautobot.ipam.models import Prefix
|
|
29
31
|
from nautobot.users import models as users_models
|
|
30
32
|
|
|
31
33
|
__all__ = (
|
|
32
|
-
"TestCase",
|
|
33
34
|
"ModelTestCase",
|
|
34
35
|
"ModelViewTestCase",
|
|
36
|
+
"TestCase",
|
|
35
37
|
"ViewTestCases",
|
|
36
38
|
)
|
|
37
39
|
|
|
@@ -1019,6 +1021,17 @@ class ViewTestCases:
|
|
|
1019
1021
|
for instance in self._get_queryset().filter(pk__in=pk_list):
|
|
1020
1022
|
self.assertInstanceEqual(instance, self.bulk_edit_data)
|
|
1021
1023
|
|
|
1024
|
+
def validate_redirect_to_job_result(self, response):
|
|
1025
|
+
# Get the last Bulk Edit Objects JobResult created
|
|
1026
|
+
job_result = JobResult.objects.filter(name="Bulk Edit Objects").first()
|
|
1027
|
+
# Assert redirect to Job Results
|
|
1028
|
+
self.assertRedirects(
|
|
1029
|
+
response,
|
|
1030
|
+
reverse("extras:jobresult", args=[job_result.pk]),
|
|
1031
|
+
status_code=302,
|
|
1032
|
+
target_status_code=200,
|
|
1033
|
+
)
|
|
1034
|
+
|
|
1022
1035
|
def test_bulk_edit_objects_without_permission(self):
|
|
1023
1036
|
pk_list = list(self._get_queryset().values_list("pk", flat=True)[:3])
|
|
1024
1037
|
data = {
|
|
@@ -1044,9 +1057,8 @@ class ViewTestCases:
|
|
|
1044
1057
|
# Assign model-level permission
|
|
1045
1058
|
self.add_permissions(f"{self.model._meta.app_label}.change_{self.model._meta.model_name}")
|
|
1046
1059
|
|
|
1047
|
-
|
|
1048
|
-
self.
|
|
1049
|
-
self.validate_object_data_after_bulk_edit(pk_list)
|
|
1060
|
+
response = self.client.post(self._get_url("bulk_edit"), data)
|
|
1061
|
+
self.validate_redirect_to_job_result(response)
|
|
1050
1062
|
|
|
1051
1063
|
@override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
|
|
1052
1064
|
def test_bulk_edit_form_contains_all_pks(self):
|
|
@@ -1071,7 +1083,7 @@ class ViewTestCases:
|
|
|
1071
1083
|
for pk in pk_list:
|
|
1072
1084
|
self.assertNotIn(str(pk), response_body)
|
|
1073
1085
|
self.assertInHTML(
|
|
1074
|
-
'<input type="hidden" name="_all" value="True" class="form-control"
|
|
1086
|
+
'<input type="hidden" name="_all" value="True" class="form-control" placeholder="None" id="id__all">',
|
|
1075
1087
|
response_body,
|
|
1076
1088
|
)
|
|
1077
1089
|
|
|
@@ -1107,7 +1119,7 @@ class ViewTestCases:
|
|
|
1107
1119
|
self.assertNotIn(str(third_pk), response_body)
|
|
1108
1120
|
self.assertIn("Editing 2 ", response_body)
|
|
1109
1121
|
self.assertInHTML(
|
|
1110
|
-
'<input type="hidden" name="_all" value="True" class="form-control"
|
|
1122
|
+
'<input type="hidden" name="_all" value="True" class="form-control" placeholder="None" id="id__all">',
|
|
1111
1123
|
response_body,
|
|
1112
1124
|
)
|
|
1113
1125
|
|
|
@@ -1147,21 +1159,9 @@ class ViewTestCases:
|
|
|
1147
1159
|
|
|
1148
1160
|
# Attempt to bulk edit permitted objects into a non-permitted state
|
|
1149
1161
|
response = self.client.post(self._get_url("bulk_edit"), data)
|
|
1150
|
-
#
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
for instance in self._get_queryset().filter(pk__in=pk_list):
|
|
1154
|
-
self.assertIn(field.value_from_object(instance), values)
|
|
1155
|
-
self.assertNotEqual(field.value_from_object(instance), self.bulk_edit_data[attr_name])
|
|
1156
|
-
|
|
1157
|
-
# Update permission constraints to permit all objects
|
|
1158
|
-
obj_perm.constraints = {"pk__gt": 0}
|
|
1159
|
-
obj_perm.save()
|
|
1160
|
-
|
|
1161
|
-
# Bulk edit permitted objects and expect a redirect back to the list view
|
|
1162
|
-
self.assertHttpStatus(self.client.post(self._get_url("bulk_edit"), data), 302)
|
|
1163
|
-
# Assert that the objects were all updated correctly
|
|
1164
|
-
self.validate_object_data_after_bulk_edit(pk_list)
|
|
1162
|
+
# NOTE: There is no way of testing constrained failure as bulk edit is a system Job;
|
|
1163
|
+
# and can only be tested by checking JobLogs.
|
|
1164
|
+
self.validate_redirect_to_job_result(response)
|
|
1165
1165
|
|
|
1166
1166
|
class BulkDeleteObjectsViewTestCase(ModelViewTestCase):
|
|
1167
1167
|
"""
|
|
@@ -1193,7 +1193,6 @@ class ViewTestCases:
|
|
|
1193
1193
|
@override_settings(EXEMPT_VIEW_PERMISSIONS=[])
|
|
1194
1194
|
def test_bulk_delete_objects_with_permission(self):
|
|
1195
1195
|
pk_list = self.get_deletable_object_pks()
|
|
1196
|
-
initial_count = self._get_queryset().count()
|
|
1197
1196
|
data = {
|
|
1198
1197
|
"pk": pk_list,
|
|
1199
1198
|
"confirm": True,
|
|
@@ -1201,11 +1200,18 @@ class ViewTestCases:
|
|
|
1201
1200
|
}
|
|
1202
1201
|
|
|
1203
1202
|
# Assign unconstrained permission
|
|
1204
|
-
self.add_permissions(
|
|
1203
|
+
self.add_permissions(
|
|
1204
|
+
f"{self.model._meta.app_label}.delete_{self.model._meta.model_name}", "extras.view_jobresult"
|
|
1205
|
+
)
|
|
1205
1206
|
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
self.
|
|
1207
|
+
response = self.client.post(self._get_url("bulk_delete"), data)
|
|
1208
|
+
job_result = JobResult.objects.filter(name="Bulk Delete Objects").first()
|
|
1209
|
+
self.assertRedirects(
|
|
1210
|
+
response,
|
|
1211
|
+
reverse("extras:jobresult", args=[job_result.pk]),
|
|
1212
|
+
status_code=302,
|
|
1213
|
+
target_status_code=200,
|
|
1214
|
+
)
|
|
1209
1215
|
|
|
1210
1216
|
@override_settings(EXEMPT_VIEW_PERMISSIONS=[])
|
|
1211
1217
|
def test_bulk_delete_form_contains_all_objects(self):
|
|
@@ -1289,9 +1295,16 @@ class ViewTestCases:
|
|
|
1289
1295
|
obj_perm.constraints = {"pk__isnull": False} # Match a non-existent pk (i.e., allow all)
|
|
1290
1296
|
obj_perm.save()
|
|
1291
1297
|
|
|
1292
|
-
#
|
|
1293
|
-
self.
|
|
1294
|
-
self.
|
|
1298
|
+
# User would be redirected to Job Result therefore user needs to have permission to view Job Result
|
|
1299
|
+
self.add_permissions("extras.view_jobresult")
|
|
1300
|
+
response = self.client.post(self._get_url("bulk_delete"), data)
|
|
1301
|
+
job_result = JobResult.objects.filter(name="Bulk Delete Objects").first()
|
|
1302
|
+
self.assertRedirects(
|
|
1303
|
+
response,
|
|
1304
|
+
reverse("extras:jobresult", args=[job_result.pk]),
|
|
1305
|
+
status_code=302,
|
|
1306
|
+
target_status_code=200,
|
|
1307
|
+
)
|
|
1295
1308
|
|
|
1296
1309
|
class BulkRenameObjectsViewTestCase(ModelViewTestCase):
|
|
1297
1310
|
"""
|
|
@@ -1441,6 +1454,8 @@ class ViewTestCases:
|
|
|
1441
1454
|
maxDiff = None
|
|
1442
1455
|
bulk_add_data = None
|
|
1443
1456
|
"""Used for bulk-add (distinct from bulk-create) view testing; self.bulk_create_data will be used if unset."""
|
|
1457
|
+
selected_objects: list[ComponentModel]
|
|
1458
|
+
selected_objects_parent_name: str
|
|
1444
1459
|
|
|
1445
1460
|
@override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
|
|
1446
1461
|
def test_bulk_add_component(self):
|
|
@@ -9,7 +9,6 @@ from example_app.models import ExampleModel
|
|
|
9
9
|
class AppHomeTestCase(SeleniumTestCase):
|
|
10
10
|
"""Integration test the Example App homepage extensions."""
|
|
11
11
|
|
|
12
|
-
fixtures = ["user-data.json"] # bob/bob
|
|
13
12
|
layout = {
|
|
14
13
|
"Organization": {
|
|
15
14
|
"Locations": {"model": Location, "permission": "dcim.view_location"},
|
|
@@ -11,8 +11,6 @@ from nautobot.extras.models import CustomField, CustomFieldChoice, Status
|
|
|
11
11
|
class ListViewFilterTestCase(SeleniumTestCase):
|
|
12
12
|
"""Integration test for the list view filter ui."""
|
|
13
13
|
|
|
14
|
-
fixtures = ["user-data.json"]
|
|
15
|
-
|
|
16
14
|
def setUp(self):
|
|
17
15
|
super().setUp()
|
|
18
16
|
self.login(self.user.username, self.password)
|
|
@@ -7,7 +7,6 @@ from nautobot.tenancy.models import Tenant
|
|
|
7
7
|
class HomeTestCase(SeleniumTestCase):
|
|
8
8
|
"""Integration tests against the home page."""
|
|
9
9
|
|
|
10
|
-
fixtures = ["user-data.json"] # bob/bob
|
|
11
10
|
layout = {
|
|
12
11
|
"Organization": {
|
|
13
12
|
"Locations": {"model": Location, "permission": "dcim.view_location"},
|
nautobot/core/tests/runner.py
CHANGED
|
@@ -142,7 +142,7 @@ class NautobotTestRunner(DiscoverRunner):
|
|
|
142
142
|
# branches/releases of Nautobot in separate files.
|
|
143
143
|
hexdigest = hashlib.shake_128(
|
|
144
144
|
",".join(
|
|
145
|
-
sorted(f"{m.app}.{m.name}" for m in MigrationRecorder.Migration.objects.all())
|
|
145
|
+
sorted(f"{m.app}.{m.name}" for m in MigrationRecorder.Migration.objects.all()) # pylint: disable=no-member
|
|
146
146
|
).encode("utf-8")
|
|
147
147
|
).hexdigest(10)
|
|
148
148
|
command += ["--fixture-file", f"development/factory_dump.{hexdigest}.json"]
|
nautobot/core/tests/test_api.py
CHANGED
|
@@ -3,6 +3,7 @@ from io import BytesIO, StringIO
|
|
|
3
3
|
import json
|
|
4
4
|
import os
|
|
5
5
|
from unittest import skip
|
|
6
|
+
import uuid
|
|
6
7
|
|
|
7
8
|
from constance import config
|
|
8
9
|
from constance.test import override_config
|
|
@@ -14,6 +15,7 @@ from django.urls import reverse
|
|
|
14
15
|
from rest_framework import status
|
|
15
16
|
from rest_framework.exceptions import ParseError
|
|
16
17
|
from rest_framework.settings import api_settings
|
|
18
|
+
from rest_framework.test import APIRequestFactory, force_authenticate
|
|
17
19
|
import yaml
|
|
18
20
|
|
|
19
21
|
from nautobot.circuits.models import Provider
|
|
@@ -22,13 +24,14 @@ from nautobot.core.api.parsers import NautobotCSVParser
|
|
|
22
24
|
from nautobot.core.api.renderers import NautobotCSVRenderer
|
|
23
25
|
from nautobot.core.api.utils import get_serializer_for_model, get_view_name
|
|
24
26
|
from nautobot.core.api.versioning import NautobotAPIVersioning
|
|
27
|
+
from nautobot.core.api.views import ModelViewSet
|
|
25
28
|
from nautobot.core.constants import COMPOSITE_KEY_SEPARATOR
|
|
26
29
|
from nautobot.core.templatetags.helpers import humanize_speed
|
|
27
30
|
from nautobot.core.utils.lookup import get_route_for_model
|
|
28
31
|
from nautobot.dcim import models as dcim_models
|
|
29
32
|
from nautobot.dcim.api import serializers as dcim_serializers
|
|
30
33
|
from nautobot.extras import choices, models as extras_models
|
|
31
|
-
from nautobot.ipam import models as ipam_models
|
|
34
|
+
from nautobot.ipam import filters as ipam_filters, models as ipam_models
|
|
32
35
|
from nautobot.ipam.api import serializers as ipam_serializers, views as ipam_api_views
|
|
33
36
|
from nautobot.tenancy import models as tenancy_models
|
|
34
37
|
|
|
@@ -381,6 +384,7 @@ class GenerateLookupValueDomElementViewTestCase(testing.APITestCase):
|
|
|
381
384
|
(
|
|
382
385
|
'<select name="role" class="form-control nautobot-select2-api" data-multiple="1" '
|
|
383
386
|
'data-query-param-content_types="["dcim.device", "virtualization.virtualmachine"]" '
|
|
387
|
+
'data-query-param-exclude_m2m="["true"]" '
|
|
384
388
|
'display-field="display" value-field="name" data-depth="0" data-url="/api/extras/roles/" id="id_for_role" '
|
|
385
389
|
"multiple>\n</select>"
|
|
386
390
|
),
|
|
@@ -516,6 +520,80 @@ class NautobotCSVRendererTest(TestCase):
|
|
|
516
520
|
self.assertEqual(read_data["parent__name"], location_type.parent.name)
|
|
517
521
|
|
|
518
522
|
|
|
523
|
+
class ModelViewSetMixinTest(testing.APITestCase):
|
|
524
|
+
"""Unit tests for ModelViewSetMixin, base class for ModelViewSet/ReadOnlyModelViewSet classes."""
|
|
525
|
+
|
|
526
|
+
class SimpleIPAddressViewSet(ModelViewSet):
|
|
527
|
+
queryset = ipam_models.IPAddress.objects.all() # no explicit optimizations
|
|
528
|
+
serializer_class = ipam_serializers.IPAddressSerializer
|
|
529
|
+
filterset_class = ipam_filters.IPAddressFilterSet
|
|
530
|
+
|
|
531
|
+
def test_get_queryset_optimizations(self):
|
|
532
|
+
"""Test that the queryset is appropriately optimized based on request parameters."""
|
|
533
|
+
self.user.is_superuser = True
|
|
534
|
+
self.user.save()
|
|
535
|
+
|
|
536
|
+
# Default behavior - m2m fields included
|
|
537
|
+
view = self.SimpleIPAddressViewSet()
|
|
538
|
+
view.action_map = {"get": "list"}
|
|
539
|
+
request = APIRequestFactory().get(reverse("ipam-api:ipaddress-list"), headers=self.header)
|
|
540
|
+
force_authenticate(request, user=self.user)
|
|
541
|
+
request = view.initialize_request(request)
|
|
542
|
+
view.setup(request)
|
|
543
|
+
view.initial(request)
|
|
544
|
+
|
|
545
|
+
queryset = view.get_queryset()
|
|
546
|
+
with self.assertNumQueries(5): # IPAddress plus four prefetches
|
|
547
|
+
instance = queryset.first()
|
|
548
|
+
# FK related objects should have been auto-selected
|
|
549
|
+
with self.assertNumQueries(0):
|
|
550
|
+
instance.status
|
|
551
|
+
instance.role
|
|
552
|
+
instance.parent
|
|
553
|
+
instance.tenant
|
|
554
|
+
instance.nat_inside
|
|
555
|
+
# Reverse relations should have been auto-prefetched
|
|
556
|
+
with self.assertNumQueries(0):
|
|
557
|
+
list(instance.nat_outside_list.all())
|
|
558
|
+
# Many-to-many relations should have been auto-prefetched
|
|
559
|
+
with self.assertNumQueries(0):
|
|
560
|
+
list(instance.interfaces.all())
|
|
561
|
+
list(instance.vm_interfaces.all())
|
|
562
|
+
list(instance.tags.all())
|
|
563
|
+
|
|
564
|
+
# With exclude_m2m query parameter
|
|
565
|
+
view = self.SimpleIPAddressViewSet()
|
|
566
|
+
view.action_map = {"get": "list"}
|
|
567
|
+
request = APIRequestFactory().get(
|
|
568
|
+
reverse("ipam-api:ipaddress-list"), headers=self.header, data={"exclude_m2m": True}
|
|
569
|
+
)
|
|
570
|
+
force_authenticate(request, user=self.user)
|
|
571
|
+
request = view.initialize_request(request)
|
|
572
|
+
view.setup(request)
|
|
573
|
+
view.initial(request)
|
|
574
|
+
|
|
575
|
+
queryset = view.get_queryset()
|
|
576
|
+
with self.assertNumQueries(1): # IPAddress only, no prefetches
|
|
577
|
+
instance = queryset.first()
|
|
578
|
+
# FK related objects should still have been auto-selected
|
|
579
|
+
with self.assertNumQueries(0):
|
|
580
|
+
instance.status
|
|
581
|
+
instance.role
|
|
582
|
+
instance.parent
|
|
583
|
+
instance.tenant
|
|
584
|
+
instance.nat_inside
|
|
585
|
+
# Reverse relations should NOT have been auto-prefetched
|
|
586
|
+
with self.assertNumQueries(1):
|
|
587
|
+
list(instance.nat_outside_list.all())
|
|
588
|
+
# Many-to-many relations should NOT have been auto-prefetched
|
|
589
|
+
with self.assertNumQueries(1):
|
|
590
|
+
list(instance.interfaces.all())
|
|
591
|
+
with self.assertNumQueries(1):
|
|
592
|
+
list(instance.vm_interfaces.all())
|
|
593
|
+
with self.assertNumQueries(1):
|
|
594
|
+
list(instance.tags.all())
|
|
595
|
+
|
|
596
|
+
|
|
519
597
|
class WritableNestedSerializerTest(testing.APITestCase):
|
|
520
598
|
"""
|
|
521
599
|
Test the operation of WritableNestedSerializer using VLANSerializer as our test subject.
|
|
@@ -688,6 +766,25 @@ class WritableNestedSerializerTest(testing.APITestCase):
|
|
|
688
766
|
self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
|
|
689
767
|
self.assertEqual(ipam_models.VLAN.objects.filter(name="Test VLAN 100").count(), 0)
|
|
690
768
|
|
|
769
|
+
def test_create_with_specified_id(self):
|
|
770
|
+
data = {
|
|
771
|
+
"id": str(uuid.uuid4()),
|
|
772
|
+
"vid": 400,
|
|
773
|
+
"name": "Test VLAN 400",
|
|
774
|
+
"status": self.statuses.first().pk,
|
|
775
|
+
"vlan_group": self.vlan_group1.pk,
|
|
776
|
+
}
|
|
777
|
+
url = reverse("ipam-api:vlan-list")
|
|
778
|
+
self.add_permissions("ipam.add_vlan")
|
|
779
|
+
|
|
780
|
+
response = self.client.post(url, data, format="json", **self.header)
|
|
781
|
+
self.assertHttpStatus(response, status.HTTP_201_CREATED)
|
|
782
|
+
self.assertEqual(str(response.data["vlan_group"]["url"]), self.absolute_api_url(self.vlan_group1))
|
|
783
|
+
self.assertEqual(str(response.data["id"]), data["id"])
|
|
784
|
+
vlan = ipam_models.VLAN.objects.get(pk=response.data["id"])
|
|
785
|
+
self.assertEqual(vlan.status, self.statuses.first())
|
|
786
|
+
self.assertEqual(vlan.vlan_group, self.vlan_group1)
|
|
787
|
+
|
|
691
788
|
|
|
692
789
|
class APIOrderingTestCase(testing.APITestCase):
|
|
693
790
|
"""
|
nautobot/core/tests/test_csv.py
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import csv
|
|
2
|
+
import io
|
|
3
|
+
|
|
1
4
|
from django.contrib.contenttypes.models import ContentType
|
|
2
5
|
from django.test import override_settings, RequestFactory, TestCase
|
|
3
6
|
from django.urls import reverse
|
|
@@ -261,9 +264,28 @@ class CSVParsingRelatedTestCase(TestCase):
|
|
|
261
264
|
self.assertEqual(response.status_code, 200)
|
|
262
265
|
response_data = response.content.decode(response.charset)
|
|
263
266
|
|
|
264
|
-
#
|
|
265
|
-
|
|
266
|
-
|
|
267
|
+
# parse the csv data
|
|
268
|
+
csv_reader = csv.DictReader(response_data.splitlines())
|
|
269
|
+
# remove the 'id' column so that all the items are imported new
|
|
270
|
+
fieldnames = [field for field in csv_reader.fieldnames if field != "id"]
|
|
271
|
+
# read all entries into a list
|
|
272
|
+
response_csv = list(csv_reader)
|
|
273
|
+
|
|
274
|
+
# mutate our data for testing purposes
|
|
275
|
+
for row in response_csv:
|
|
276
|
+
if row["name"] == "TestDevice1":
|
|
277
|
+
row["name"] = "TestDevice3"
|
|
278
|
+
elif row["name"] == "TestDevice2":
|
|
279
|
+
row["name"] = ""
|
|
280
|
+
|
|
281
|
+
# prep our data to write out
|
|
282
|
+
with io.StringIO() as import_csv:
|
|
283
|
+
writer = csv.DictWriter(import_csv, fieldnames=fieldnames)
|
|
284
|
+
writer.writeheader()
|
|
285
|
+
for row in response_csv:
|
|
286
|
+
filtered_row = {key: row[key] for key in fieldnames}
|
|
287
|
+
writer.writerow(filtered_row)
|
|
288
|
+
data = {"csv_data": import_csv.getvalue()}
|
|
267
289
|
url = reverse("dcim:device_import")
|
|
268
290
|
response = self.client.post(url, data)
|
|
269
291
|
self.assertEqual(response.status_code, 200)
|