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
|
@@ -66,6 +66,8 @@ from nautobot.extras.models import (
|
|
|
66
66
|
JobButton,
|
|
67
67
|
JobHook,
|
|
68
68
|
JobLogEntry,
|
|
69
|
+
JobQueue,
|
|
70
|
+
JobQueueAssignment,
|
|
69
71
|
JobResult,
|
|
70
72
|
MetadataChoice,
|
|
71
73
|
MetadataType,
|
|
@@ -212,13 +214,13 @@ class ContactSerializer(NautobotModelSerializer):
|
|
|
212
214
|
"phone": {"default": ""},
|
|
213
215
|
}
|
|
214
216
|
|
|
215
|
-
def validate(self,
|
|
216
|
-
|
|
217
|
-
|
|
217
|
+
def validate(self, data):
|
|
218
|
+
attrs = data.copy()
|
|
219
|
+
attrs.pop("teams", None)
|
|
218
220
|
validator = UniqueTogetherValidator(queryset=Contact.objects.all(), fields=("name", "phone", "email"))
|
|
219
|
-
validator(
|
|
220
|
-
super().validate(
|
|
221
|
-
return
|
|
221
|
+
validator(attrs, self)
|
|
222
|
+
super().validate(attrs)
|
|
223
|
+
return data
|
|
222
224
|
|
|
223
225
|
|
|
224
226
|
class ContactAssociationSerializer(NautobotModelSerializer):
|
|
@@ -233,18 +235,18 @@ class ContactAssociationSerializer(NautobotModelSerializer):
|
|
|
233
235
|
"team": {"required": False},
|
|
234
236
|
}
|
|
235
237
|
|
|
236
|
-
def validate(self,
|
|
238
|
+
def validate(self, data):
|
|
237
239
|
# Validate uniqueness of (associated object, associated object type, contact/team, role)
|
|
238
240
|
unique_together_fields = None
|
|
239
241
|
|
|
240
|
-
if
|
|
242
|
+
if data.get("contact") and data.get("role"):
|
|
241
243
|
unique_together_fields = (
|
|
242
244
|
"associated_object_type",
|
|
243
245
|
"associated_object_id",
|
|
244
246
|
"contact",
|
|
245
247
|
"role",
|
|
246
248
|
)
|
|
247
|
-
elif
|
|
249
|
+
elif data.get("team") and data.get("role"):
|
|
248
250
|
unique_together_fields = (
|
|
249
251
|
"associated_object_type",
|
|
250
252
|
"associated_object_id",
|
|
@@ -257,11 +259,11 @@ class ContactAssociationSerializer(NautobotModelSerializer):
|
|
|
257
259
|
queryset=ContactAssociation.objects.all(),
|
|
258
260
|
fields=unique_together_fields,
|
|
259
261
|
)
|
|
260
|
-
validator(
|
|
262
|
+
validator(data, self)
|
|
261
263
|
|
|
262
|
-
super().validate(
|
|
264
|
+
super().validate(data)
|
|
263
265
|
|
|
264
|
-
return
|
|
266
|
+
return data
|
|
265
267
|
|
|
266
268
|
|
|
267
269
|
#
|
|
@@ -270,7 +272,6 @@ class ContactAssociationSerializer(NautobotModelSerializer):
|
|
|
270
272
|
|
|
271
273
|
|
|
272
274
|
class ContentTypeSerializer(BaseModelSerializer):
|
|
273
|
-
id = serializers.IntegerField(read_only=True)
|
|
274
275
|
url = serializers.HyperlinkedIdentityField(view_name="extras-api:contenttype-detail")
|
|
275
276
|
display = serializers.SerializerMethodField()
|
|
276
277
|
|
|
@@ -279,8 +280,8 @@ class ContentTypeSerializer(BaseModelSerializer):
|
|
|
279
280
|
fields = "__all__"
|
|
280
281
|
|
|
281
282
|
@extend_schema_field(serializers.CharField)
|
|
282
|
-
def get_display(self,
|
|
283
|
-
return
|
|
283
|
+
def get_display(self, obj):
|
|
284
|
+
return obj.app_labeled_name
|
|
284
285
|
|
|
285
286
|
|
|
286
287
|
#
|
|
@@ -501,17 +502,17 @@ class ImageAttachmentSerializer(ValidatedModelSerializer):
|
|
|
501
502
|
model = ImageAttachment
|
|
502
503
|
fields = "__all__"
|
|
503
504
|
|
|
504
|
-
def validate(self,
|
|
505
|
+
def validate(self, data):
|
|
505
506
|
# Validate that the parent object exists
|
|
506
507
|
try:
|
|
507
|
-
|
|
508
|
+
data["content_type"].get_object_for_this_type(id=data["object_id"])
|
|
508
509
|
except ObjectDoesNotExist:
|
|
509
|
-
raise serializers.ValidationError(f"Invalid parent object: {
|
|
510
|
+
raise serializers.ValidationError(f"Invalid parent object: {data['content_type']} ID {data['object_id']}")
|
|
510
511
|
|
|
511
512
|
# Enforce model validation
|
|
512
|
-
super().validate(
|
|
513
|
+
super().validate(data)
|
|
513
514
|
|
|
514
|
-
return
|
|
515
|
+
return data
|
|
515
516
|
|
|
516
517
|
@extend_schema_field(
|
|
517
518
|
PolymorphicProxySerializer(
|
|
@@ -535,28 +536,44 @@ class ImageAttachmentSerializer(ValidatedModelSerializer):
|
|
|
535
536
|
|
|
536
537
|
|
|
537
538
|
class JobSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
|
|
539
|
+
# task_queues and task_queues_override are added to maintain backward compatibility with versions pre v2.4.
|
|
540
|
+
task_queues = serializers.JSONField(read_only=True, required=False)
|
|
541
|
+
task_queues_override = serializers.BooleanField(read_only=True, required=False)
|
|
542
|
+
|
|
538
543
|
class Meta:
|
|
539
544
|
model = Job
|
|
540
545
|
fields = "__all__"
|
|
541
546
|
|
|
542
|
-
def validate(self,
|
|
547
|
+
def validate(self, data):
|
|
543
548
|
# note no validation for on creation of jobs because we do not support user creation of Job records via API
|
|
544
549
|
if self.instance:
|
|
545
|
-
has_sensitive_variables =
|
|
546
|
-
approval_required =
|
|
550
|
+
has_sensitive_variables = data.get("has_sensitive_variables", self.instance.has_sensitive_variables)
|
|
551
|
+
approval_required = data.get("approval_required", self.instance.approval_required)
|
|
547
552
|
|
|
548
553
|
if approval_required and has_sensitive_variables:
|
|
549
554
|
error_message = "A job with sensitive variables cannot also be marked as requiring approval"
|
|
550
555
|
errors = {}
|
|
551
556
|
|
|
552
|
-
if "approval_required" in
|
|
557
|
+
if "approval_required" in data:
|
|
553
558
|
errors["approval_required"] = [error_message]
|
|
554
|
-
if "has_sensitive_variables" in
|
|
559
|
+
if "has_sensitive_variables" in data:
|
|
555
560
|
errors["has_sensitive_variables"] = [error_message]
|
|
556
561
|
|
|
557
562
|
raise serializers.ValidationError(errors)
|
|
558
563
|
|
|
559
|
-
return super().validate(
|
|
564
|
+
return super().validate(data)
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
class JobQueueSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
|
|
568
|
+
class Meta:
|
|
569
|
+
model = JobQueue
|
|
570
|
+
fields = "__all__"
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
class JobQueueAssignmentSerializer(ValidatedModelSerializer):
|
|
574
|
+
class Meta:
|
|
575
|
+
model = JobQueueAssignment
|
|
576
|
+
fields = "__all__"
|
|
560
577
|
|
|
561
578
|
|
|
562
579
|
class JobVariableSerializer(serializers.Serializer):
|
|
@@ -583,6 +600,8 @@ class JobVariableSerializer(serializers.Serializer):
|
|
|
583
600
|
|
|
584
601
|
class ScheduledJobSerializer(BaseModelSerializer):
|
|
585
602
|
# start_time = serializers.DateTimeField(format=None, required=False)
|
|
603
|
+
# queue is added to maintain backward compatibility with versions pre v2.4.
|
|
604
|
+
queue = serializers.CharField(read_only=True, required=False)
|
|
586
605
|
time_zone = TimeZoneSerializerField(required=False)
|
|
587
606
|
|
|
588
607
|
class Meta:
|
|
@@ -668,22 +687,22 @@ class JobHookSerializer(NautobotModelSerializer):
|
|
|
668
687
|
model = JobHook
|
|
669
688
|
fields = "__all__"
|
|
670
689
|
|
|
671
|
-
def validate(self,
|
|
672
|
-
|
|
690
|
+
def validate(self, data):
|
|
691
|
+
validated_data = super().validate(data)
|
|
673
692
|
|
|
674
693
|
conflicts = JobHook.check_for_conflicts(
|
|
675
694
|
instance=self.instance,
|
|
676
|
-
content_types=
|
|
677
|
-
job=
|
|
678
|
-
type_create=
|
|
679
|
-
type_update=
|
|
680
|
-
type_delete=
|
|
695
|
+
content_types=data.get("content_types"),
|
|
696
|
+
job=data.get("job"),
|
|
697
|
+
type_create=data.get("type_create"),
|
|
698
|
+
type_update=data.get("type_update"),
|
|
699
|
+
type_delete=data.get("type_delete"),
|
|
681
700
|
)
|
|
682
701
|
|
|
683
702
|
if conflicts:
|
|
684
703
|
raise serializers.ValidationError(conflicts)
|
|
685
704
|
|
|
686
|
-
return
|
|
705
|
+
return validated_data
|
|
687
706
|
|
|
688
707
|
|
|
689
708
|
class JobCreationSerializer(BaseModelSerializer):
|
|
@@ -702,15 +721,15 @@ class JobCreationSerializer(BaseModelSerializer):
|
|
|
702
721
|
model = ScheduledJob
|
|
703
722
|
fields = ["url", "name", "start_time", "interval", "crontab"]
|
|
704
723
|
|
|
705
|
-
def validate(self,
|
|
706
|
-
|
|
724
|
+
def validate(self, data):
|
|
725
|
+
data = super().validate(data)
|
|
707
726
|
|
|
708
|
-
if
|
|
709
|
-
if "name" not in
|
|
727
|
+
if data["interval"] in choices.JobExecutionType.SCHEDULE_CHOICES:
|
|
728
|
+
if "name" not in data:
|
|
710
729
|
raise serializers.ValidationError({"name": "Please provide a name for the job schedule."})
|
|
711
730
|
|
|
712
|
-
if ("start_time" not in
|
|
713
|
-
"start_time" in
|
|
731
|
+
if ("start_time" not in data and data["interval"] != choices.JobExecutionType.TYPE_CUSTOM) or (
|
|
732
|
+
"start_time" in data and data["start_time"] < models.ScheduledJob.earliest_possible_time()
|
|
714
733
|
):
|
|
715
734
|
raise serializers.ValidationError(
|
|
716
735
|
{
|
|
@@ -718,21 +737,22 @@ class JobCreationSerializer(BaseModelSerializer):
|
|
|
718
737
|
}
|
|
719
738
|
)
|
|
720
739
|
|
|
721
|
-
if
|
|
722
|
-
if
|
|
740
|
+
if data["interval"] == choices.JobExecutionType.TYPE_CUSTOM:
|
|
741
|
+
if data.get("crontab") is None:
|
|
723
742
|
raise serializers.ValidationError({"crontab": "Please enter a valid crontab."})
|
|
724
743
|
try:
|
|
725
|
-
models.ScheduledJob.get_crontab(
|
|
744
|
+
models.ScheduledJob.get_crontab(data["crontab"])
|
|
726
745
|
except Exception as e:
|
|
727
746
|
raise serializers.ValidationError({"crontab": e})
|
|
728
747
|
|
|
729
|
-
return
|
|
748
|
+
return data
|
|
730
749
|
|
|
731
750
|
|
|
732
751
|
class JobInputSerializer(serializers.Serializer):
|
|
733
752
|
data = serializers.JSONField(required=False, default=dict)
|
|
734
753
|
schedule = JobCreationSerializer(required=False)
|
|
735
754
|
task_queue = serializers.CharField(required=False, allow_blank=True)
|
|
755
|
+
job_queue = serializers.CharField(required=False, allow_blank=True)
|
|
736
756
|
|
|
737
757
|
|
|
738
758
|
class JobMultiPartInputSerializer(serializers.Serializer):
|
|
@@ -743,19 +763,17 @@ class JobMultiPartInputSerializer(serializers.Serializer):
|
|
|
743
763
|
_schedule_interval = ChoiceField(choices=JobExecutionType, required=False)
|
|
744
764
|
_schedule_crontab = serializers.CharField(required=False, allow_blank=True)
|
|
745
765
|
_task_queue = serializers.CharField(required=False, allow_blank=True)
|
|
766
|
+
_job_queue = serializers.CharField(required=False, allow_blank=True)
|
|
746
767
|
|
|
747
|
-
def validate(self,
|
|
748
|
-
|
|
768
|
+
def validate(self, data):
|
|
769
|
+
data = super().validate(data)
|
|
749
770
|
|
|
750
|
-
if "_schedule_interval" in
|
|
751
|
-
if "_schedule_name" not in
|
|
771
|
+
if "_schedule_interval" in data and data["_schedule_interval"] != JobExecutionType.TYPE_IMMEDIATELY:
|
|
772
|
+
if "_schedule_name" not in data:
|
|
752
773
|
raise serializers.ValidationError({"_schedule_name": "Please provide a name for the job schedule."})
|
|
753
774
|
|
|
754
|
-
if (
|
|
755
|
-
"_schedule_start_time"
|
|
756
|
-
) or (
|
|
757
|
-
"_schedule_start_time" in attrs
|
|
758
|
-
and attrs["_schedule_start_time"] < ScheduledJob.earliest_possible_time()
|
|
775
|
+
if ("_schedule_start_time" not in data and data["_schedule_interval"] != JobExecutionType.TYPE_CUSTOM) or (
|
|
776
|
+
"_schedule_start_time" in data and data["_schedule_start_time"] < ScheduledJob.earliest_possible_time()
|
|
759
777
|
):
|
|
760
778
|
raise serializers.ValidationError(
|
|
761
779
|
{
|
|
@@ -763,15 +781,15 @@ class JobMultiPartInputSerializer(serializers.Serializer):
|
|
|
763
781
|
}
|
|
764
782
|
)
|
|
765
783
|
|
|
766
|
-
if
|
|
767
|
-
if
|
|
784
|
+
if data["_schedule_interval"] == JobExecutionType.TYPE_CUSTOM:
|
|
785
|
+
if data.get("_schedule_crontab") is None:
|
|
768
786
|
raise serializers.ValidationError({"_schedule_crontab": "Please enter a valid crontab."})
|
|
769
787
|
try:
|
|
770
|
-
ScheduledJob.get_crontab(
|
|
788
|
+
ScheduledJob.get_crontab(data["_schedule_crontab"])
|
|
771
789
|
except Exception as e:
|
|
772
790
|
raise serializers.ValidationError({"_schedule_crontab": e})
|
|
773
791
|
|
|
774
|
-
return
|
|
792
|
+
return data
|
|
775
793
|
|
|
776
794
|
|
|
777
795
|
class JobLogEntrySerializer(BaseModelSerializer):
|
|
@@ -862,7 +880,6 @@ class NoteSerializer(BaseModelSerializer):
|
|
|
862
880
|
class Meta:
|
|
863
881
|
model = Note
|
|
864
882
|
fields = "__all__"
|
|
865
|
-
list_display_fields = ["note", "assigned_object_type", "assigned_object_id", "user"]
|
|
866
883
|
|
|
867
884
|
@extend_schema_field(
|
|
868
885
|
PolymorphicProxySerializer(
|
|
@@ -902,7 +919,6 @@ class ObjectChangeSerializer(BaseModelSerializer):
|
|
|
902
919
|
class Meta:
|
|
903
920
|
model = ObjectChange
|
|
904
921
|
fields = "__all__"
|
|
905
|
-
list_display_fields = ["changed_object_id", "related_object_id", "related_object_type", "user"]
|
|
906
922
|
|
|
907
923
|
@extend_schema_field(
|
|
908
924
|
PolymorphicProxySerializer(
|
|
@@ -1057,18 +1073,18 @@ class TagSerializer(NautobotModelSerializer):
|
|
|
1057
1073
|
"color": {"help_text": "RGB color in hexadecimal (e.g. 00ff00)"},
|
|
1058
1074
|
}
|
|
1059
1075
|
|
|
1060
|
-
def validate(self,
|
|
1061
|
-
|
|
1076
|
+
def validate(self, data):
|
|
1077
|
+
data = super().validate(data)
|
|
1062
1078
|
|
|
1063
1079
|
# check if tag is assigned to any of the removed content_types
|
|
1064
|
-
if self.instance is not None and self.instance.present_in_database and "content_types" in
|
|
1065
|
-
content_types_id = [content_type.id for content_type in
|
|
1080
|
+
if self.instance is not None and self.instance.present_in_database and "content_types" in data:
|
|
1081
|
+
content_types_id = [content_type.id for content_type in data["content_types"]]
|
|
1066
1082
|
errors = self.instance.validate_content_types_removal(content_types_id)
|
|
1067
1083
|
|
|
1068
1084
|
if errors:
|
|
1069
1085
|
raise serializers.ValidationError(errors)
|
|
1070
1086
|
|
|
1071
|
-
return
|
|
1087
|
+
return data
|
|
1072
1088
|
|
|
1073
1089
|
|
|
1074
1090
|
#
|
|
@@ -1090,10 +1106,10 @@ class TeamSerializer(NautobotModelSerializer):
|
|
|
1090
1106
|
# https://www.django-rest-framework.org/api-guide/validators/#optional-fields
|
|
1091
1107
|
validators = []
|
|
1092
1108
|
|
|
1093
|
-
def validate(self,
|
|
1109
|
+
def validate(self, data):
|
|
1094
1110
|
validator = UniqueTogetherValidator(queryset=Team.objects.all(), fields=("name", "phone", "email"))
|
|
1095
|
-
validator(
|
|
1096
|
-
return super().validate(
|
|
1111
|
+
validator(data, self)
|
|
1112
|
+
return super().validate(data)
|
|
1097
1113
|
|
|
1098
1114
|
|
|
1099
1115
|
#
|
|
@@ -1111,19 +1127,19 @@ class WebhookSerializer(ValidatedModelSerializer, NotesSerializerMixin):
|
|
|
1111
1127
|
model = Webhook
|
|
1112
1128
|
fields = "__all__"
|
|
1113
1129
|
|
|
1114
|
-
def validate(self,
|
|
1115
|
-
|
|
1130
|
+
def validate(self, data):
|
|
1131
|
+
validated_data = super().validate(data)
|
|
1116
1132
|
|
|
1117
1133
|
conflicts = Webhook.check_for_conflicts(
|
|
1118
1134
|
instance=self.instance,
|
|
1119
|
-
content_types=
|
|
1120
|
-
payload_url=
|
|
1121
|
-
type_create=
|
|
1122
|
-
type_update=
|
|
1123
|
-
type_delete=
|
|
1135
|
+
content_types=data.get("content_types"),
|
|
1136
|
+
payload_url=data.get("payload_url"),
|
|
1137
|
+
type_create=data.get("type_create"),
|
|
1138
|
+
type_update=data.get("type_update"),
|
|
1139
|
+
type_delete=data.get("type_delete"),
|
|
1124
1140
|
)
|
|
1125
1141
|
|
|
1126
1142
|
if conflicts:
|
|
1127
1143
|
raise serializers.ValidationError(conflicts)
|
|
1128
1144
|
|
|
1129
|
-
return
|
|
1145
|
+
return validated_data
|
nautobot/extras/api/urls.py
CHANGED
|
@@ -69,6 +69,10 @@ router.register("job-hooks", views.JobHooksViewSet)
|
|
|
69
69
|
# Job Log Entries
|
|
70
70
|
router.register("job-logs", views.JobLogEntryViewSet)
|
|
71
71
|
|
|
72
|
+
# Job Queues
|
|
73
|
+
router.register("job-queues", views.JobQueueViewSet)
|
|
74
|
+
router.register("job-queue-assignments", views.JobQueueAssignmentViewSet)
|
|
75
|
+
|
|
72
76
|
# Job Results
|
|
73
77
|
router.register("job-results", views.JobResultViewSet)
|
|
74
78
|
|
nautobot/extras/api/views.py
CHANGED
|
@@ -17,7 +17,6 @@ from rest_framework.permissions import IsAuthenticated
|
|
|
17
17
|
from rest_framework.response import Response
|
|
18
18
|
|
|
19
19
|
from nautobot.core.api.authentication import TokenPermissions
|
|
20
|
-
from nautobot.core.api.parsers import NautobotCSVParser
|
|
21
20
|
from nautobot.core.api.utils import get_serializer_for_model
|
|
22
21
|
from nautobot.core.api.views import (
|
|
23
22
|
BulkDestroyModelMixin,
|
|
@@ -27,11 +26,13 @@ from nautobot.core.api.views import (
|
|
|
27
26
|
NautobotAPIVersionMixin,
|
|
28
27
|
ReadOnlyModelViewSet,
|
|
29
28
|
)
|
|
29
|
+
from nautobot.core.events import publish_event
|
|
30
30
|
from nautobot.core.exceptions import CeleryWorkerNotRunningException
|
|
31
31
|
from nautobot.core.graphql import execute_saved_query
|
|
32
32
|
from nautobot.core.models.querysets import count_related
|
|
33
|
+
from nautobot.core.models.utils import serialize_object_v2
|
|
33
34
|
from nautobot.extras import filters
|
|
34
|
-
from nautobot.extras.choices import JobExecutionType
|
|
35
|
+
from nautobot.extras.choices import JobExecutionType, JobQueueTypeChoices
|
|
35
36
|
from nautobot.extras.filters import RoleFilterSet
|
|
36
37
|
from nautobot.extras.jobs import get_job
|
|
37
38
|
from nautobot.extras.models import (
|
|
@@ -55,6 +56,8 @@ from nautobot.extras.models import (
|
|
|
55
56
|
JobButton,
|
|
56
57
|
JobHook,
|
|
57
58
|
JobLogEntry,
|
|
59
|
+
JobQueue,
|
|
60
|
+
JobQueueAssignment,
|
|
58
61
|
JobResult,
|
|
59
62
|
MetadataChoice,
|
|
60
63
|
MetadataType,
|
|
@@ -78,7 +81,7 @@ from nautobot.extras.models import (
|
|
|
78
81
|
Webhook,
|
|
79
82
|
)
|
|
80
83
|
from nautobot.extras.secrets.exceptions import SecretError
|
|
81
|
-
from nautobot.extras.utils import get_worker_count
|
|
84
|
+
from nautobot.extras.utils import get_job_queue, get_worker_count
|
|
82
85
|
|
|
83
86
|
from . import serializers
|
|
84
87
|
|
|
@@ -485,7 +488,6 @@ class ImageAttachmentViewSet(ModelViewSet):
|
|
|
485
488
|
queryset = ImageAttachment.objects.all()
|
|
486
489
|
serializer_class = serializers.ImageAttachmentSerializer
|
|
487
490
|
filterset_class = filters.ImageAttachmentFilterSet
|
|
488
|
-
parser_classes = [JSONParser, NautobotCSVParser, MultiPartParser]
|
|
489
491
|
|
|
490
492
|
|
|
491
493
|
#
|
|
@@ -601,9 +603,8 @@ class JobViewSetBase(
|
|
|
601
603
|
)
|
|
602
604
|
|
|
603
605
|
valid_queues = job_model.task_queues if job_model.task_queues else [settings.CELERY_TASK_DEFAULT_QUEUE]
|
|
604
|
-
#
|
|
605
|
-
|
|
606
|
-
default_valid_queue = valid_queues[0]
|
|
606
|
+
# default queue should be specified on the default_job_queue.
|
|
607
|
+
default_valid_queue = job_model.default_job_queue.name
|
|
607
608
|
|
|
608
609
|
# We need to call request.data for both cases as this is what pulls and caches the request data
|
|
609
610
|
data = request.data
|
|
@@ -624,7 +625,23 @@ class JobViewSetBase(
|
|
|
624
625
|
input_serializer = serializers.JobMultiPartInputSerializer(data=data, context={"request": request})
|
|
625
626
|
input_serializer.is_valid(raise_exception=True)
|
|
626
627
|
|
|
627
|
-
|
|
628
|
+
# TODO remove _task_queue related code in 3.0
|
|
629
|
+
# _task_queue and _job_queue are both valid arguments in v2.4
|
|
630
|
+
task_queue = input_serializer.validated_data.get(
|
|
631
|
+
"_task_queue", None
|
|
632
|
+
) or input_serializer.validated_data.get("_job_queue", None)
|
|
633
|
+
if not task_queue:
|
|
634
|
+
task_queue = default_valid_queue
|
|
635
|
+
|
|
636
|
+
# Log a warning if _task_queue and _job_queue fields are both specified out
|
|
637
|
+
if input_serializer.validated_data.get("_task_queue", None) and input_serializer.validated_data.get(
|
|
638
|
+
"_job_queue", None
|
|
639
|
+
):
|
|
640
|
+
raise ValidationError(
|
|
641
|
+
{
|
|
642
|
+
"_task_queue": "_task_queue and _job_queue are both specified. Please specifiy only one or another."
|
|
643
|
+
}
|
|
644
|
+
)
|
|
628
645
|
|
|
629
646
|
# JobMultiPartInputSerializer only has keys for executing job (task_queue, etc),
|
|
630
647
|
# everything else is a candidate for the job form's data.
|
|
@@ -652,7 +669,21 @@ class JobViewSetBase(
|
|
|
652
669
|
input_serializer.is_valid(raise_exception=True)
|
|
653
670
|
|
|
654
671
|
data = input_serializer.validated_data.get("data", {})
|
|
655
|
-
|
|
672
|
+
# TODO remove _task_queue related code in 3.0
|
|
673
|
+
# _task_queue and _job_queue are both valid arguments in v2.4
|
|
674
|
+
task_queue = input_serializer.validated_data.get("task_queue", None) or input_serializer.validated_data.get(
|
|
675
|
+
"job_queue", None
|
|
676
|
+
)
|
|
677
|
+
if not task_queue:
|
|
678
|
+
task_queue = default_valid_queue
|
|
679
|
+
|
|
680
|
+
# Log a warning if _task_queue and _job_queue fields are both specified out
|
|
681
|
+
if input_serializer.validated_data.get("task_queue", None) and input_serializer.validated_data.get(
|
|
682
|
+
"job_queue", None
|
|
683
|
+
):
|
|
684
|
+
raise ValidationError(
|
|
685
|
+
{"task_queue": "task_queue and job_queue are both specified. Please specifiy only one or another."}
|
|
686
|
+
)
|
|
656
687
|
schedule_data = input_serializer.validated_data.get("schedule", None)
|
|
657
688
|
|
|
658
689
|
if task_queue not in valid_queues:
|
|
@@ -669,7 +700,10 @@ class JobViewSetBase(
|
|
|
669
700
|
# of errors under messages
|
|
670
701
|
return Response({"errors": e.message_dict if hasattr(e, "error_dict") else e.messages}, status=400)
|
|
671
702
|
|
|
672
|
-
|
|
703
|
+
queue = get_job_queue(task_queue)
|
|
704
|
+
if queue is None:
|
|
705
|
+
queue = job_model.default_job_queue
|
|
706
|
+
if queue.queue_type == JobQueueTypeChoices.TYPE_CELERY and not get_worker_count(queue=task_queue):
|
|
673
707
|
raise CeleryWorkerNotRunningException(queue=task_queue)
|
|
674
708
|
|
|
675
709
|
# Default to a null JobResult.
|
|
@@ -700,7 +734,7 @@ class JobViewSetBase(
|
|
|
700
734
|
interval=schedule_data.get("interval"),
|
|
701
735
|
crontab=schedule_data.get("crontab", ""),
|
|
702
736
|
approval_required=approval_required,
|
|
703
|
-
task_queue=
|
|
737
|
+
task_queue=task_queue,
|
|
704
738
|
**job_class.serialize_data(cleaned_data),
|
|
705
739
|
)
|
|
706
740
|
else:
|
|
@@ -732,13 +766,13 @@ class JobViewSet(
|
|
|
732
766
|
):
|
|
733
767
|
lookup_value_regex = r"[-0-9a-fA-F]+"
|
|
734
768
|
|
|
735
|
-
def perform_destroy(self,
|
|
736
|
-
if
|
|
769
|
+
def perform_destroy(self, obj):
|
|
770
|
+
if obj.module_name.startswith("nautobot."):
|
|
737
771
|
raise ProtectedError(
|
|
738
|
-
f"Unable to delete Job {
|
|
772
|
+
f"Unable to delete Job {obj}. System Job cannot be deleted",
|
|
739
773
|
[],
|
|
740
774
|
)
|
|
741
|
-
super().perform_destroy(
|
|
775
|
+
super().perform_destroy(obj)
|
|
742
776
|
|
|
743
777
|
|
|
744
778
|
@extend_schema_view(
|
|
@@ -784,6 +818,31 @@ class JobHooksViewSet(NautobotModelViewSet):
|
|
|
784
818
|
filterset_class = filters.JobHookFilterSet
|
|
785
819
|
|
|
786
820
|
|
|
821
|
+
#
|
|
822
|
+
# Job Queues
|
|
823
|
+
#
|
|
824
|
+
|
|
825
|
+
|
|
826
|
+
class JobQueueViewSet(NautobotModelViewSet):
|
|
827
|
+
"""
|
|
828
|
+
Manage job queues through DELETE, GET, POST, PUT, and PATCH requests.
|
|
829
|
+
"""
|
|
830
|
+
|
|
831
|
+
queryset = JobQueue.objects.all()
|
|
832
|
+
serializer_class = serializers.JobQueueSerializer
|
|
833
|
+
filterset_class = filters.JobQueueFilterSet
|
|
834
|
+
|
|
835
|
+
|
|
836
|
+
class JobQueueAssignmentViewSet(NautobotModelViewSet):
|
|
837
|
+
"""
|
|
838
|
+
Manage job queue assignments through DELETE, GET, POST, PUT, and PATCH requests.
|
|
839
|
+
"""
|
|
840
|
+
|
|
841
|
+
queryset = JobQueueAssignment.objects.select_related("job", "job_queue")
|
|
842
|
+
serializer_class = serializers.JobQueueAssignmentSerializer
|
|
843
|
+
filterset_class = filters.JobQueueAssignmentFilterSet
|
|
844
|
+
|
|
845
|
+
|
|
787
846
|
#
|
|
788
847
|
# Job Results
|
|
789
848
|
#
|
|
@@ -912,6 +971,8 @@ class ScheduledJobViewSet(ReadOnlyModelViewSet):
|
|
|
912
971
|
scheduled_job.approved_by_user = request.user
|
|
913
972
|
scheduled_job.approved_at = timezone.now()
|
|
914
973
|
scheduled_job.save()
|
|
974
|
+
publish_event_payload = {"data": serialize_object_v2(scheduled_job)}
|
|
975
|
+
publish_event(topic="nautobot.jobs.approval.approved", payload=publish_event_payload)
|
|
915
976
|
serializer = serializers.ScheduledJobSerializer(scheduled_job, context={"request": request})
|
|
916
977
|
|
|
917
978
|
return Response(serializer.data)
|
|
@@ -936,6 +997,8 @@ class ScheduledJobViewSet(ReadOnlyModelViewSet):
|
|
|
936
997
|
if not Job.objects.check_perms(request.user, instance=scheduled_job.job_model, action="approve"):
|
|
937
998
|
raise PermissionDenied("You do not have permission to deny this request.")
|
|
938
999
|
|
|
1000
|
+
publish_event_payload = {"data": serialize_object_v2(scheduled_job)}
|
|
1001
|
+
publish_event(topic="nautobot.jobs.approval.denied", payload=publish_event_payload)
|
|
939
1002
|
scheduled_job.delete()
|
|
940
1003
|
|
|
941
1004
|
return Response(None)
|
nautobot/extras/choices.py
CHANGED
|
@@ -229,6 +229,16 @@ class JobExecutionType(ChoiceSet):
|
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
|
|
232
|
+
class JobQueueTypeChoices(ChoiceSet):
|
|
233
|
+
TYPE_CELERY = "celery"
|
|
234
|
+
TYPE_KUBERNETES = "kubernetes"
|
|
235
|
+
|
|
236
|
+
CHOICES = (
|
|
237
|
+
(TYPE_CELERY, "Celery"),
|
|
238
|
+
(TYPE_KUBERNETES, "Kubernetes"),
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
|
|
232
242
|
#
|
|
233
243
|
# Job results
|
|
234
244
|
#
|
|
@@ -295,6 +305,7 @@ class LogLevelChoices(ChoiceSet):
|
|
|
295
305
|
LOG_WARNING = "warning"
|
|
296
306
|
LOG_ERROR = "error"
|
|
297
307
|
LOG_CRITICAL = "critical"
|
|
308
|
+
LOG_SUCCESS = "success"
|
|
298
309
|
|
|
299
310
|
CHOICES = (
|
|
300
311
|
(LOG_DEBUG, "Debug"),
|
|
@@ -302,6 +313,7 @@ class LogLevelChoices(ChoiceSet):
|
|
|
302
313
|
(LOG_WARNING, "Warning"),
|
|
303
314
|
(LOG_ERROR, "Error"),
|
|
304
315
|
(LOG_CRITICAL, "Critical"),
|
|
316
|
+
(LOG_SUCCESS, "Success"),
|
|
305
317
|
)
|
|
306
318
|
|
|
307
319
|
CSS_CLASSES = {
|
|
@@ -310,6 +322,7 @@ class LogLevelChoices(ChoiceSet):
|
|
|
310
322
|
LOG_WARNING: "warning",
|
|
311
323
|
LOG_ERROR: "error",
|
|
312
324
|
LOG_CRITICAL: "critical",
|
|
325
|
+
LOG_SUCCESS: "success",
|
|
313
326
|
}
|
|
314
327
|
|
|
315
328
|
|