nautobot 2.3.15b1__py3-none-any.whl → 2.4.0__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/__init__.py +1 -1
- nautobot/apps/api.py +8 -10
- nautobot/apps/change_logging.py +2 -2
- nautobot/apps/choices.py +4 -4
- nautobot/apps/config.py +32 -3
- nautobot/apps/events.py +19 -0
- nautobot/apps/exceptions.py +0 -2
- 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 +44 -9
- nautobot/apps/utils.py +7 -15
- nautobot/apps/views.py +8 -6
- nautobot/circuits/api/serializers.py +1 -0
- nautobot/circuits/api/views.py +4 -8
- nautobot/circuits/navigation.py +0 -57
- nautobot/circuits/templates/circuits/circuit_create.html +1 -7
- 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/api/views.py +6 -10
- nautobot/cloud/factory.py +4 -1
- nautobot/cloud/models.py +1 -1
- nautobot/cloud/tests/test_filters.py +5 -4
- 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/metadata.py +28 -256
- nautobot/core/api/pagination.py +3 -2
- nautobot/core/api/renderers.py +3 -0
- nautobot/core/api/schema.py +13 -2
- nautobot/core/api/serializers.py +54 -268
- nautobot/core/api/urls.py +3 -4
- nautobot/core/api/utils.py +0 -62
- nautobot/core/api/views.py +102 -159
- nautobot/core/apps/__init__.py +22 -575
- nautobot/core/celery/__init__.py +13 -0
- nautobot/core/celery/schedulers.py +48 -3
- nautobot/core/choices.py +2 -2
- 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 +19 -16
- nautobot/core/forms/__init__.py +19 -19
- nautobot/core/forms/fields.py +62 -14
- nautobot/core/forms/forms.py +33 -2
- 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 +28 -7
- nautobot/core/jobs/bulk_actions.py +248 -0
- nautobot/core/jobs/cleanup.py +2 -2
- 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 +2 -2
- nautobot/core/settings.py +71 -4
- nautobot/core/settings.yaml +107 -0
- nautobot/core/tables.py +15 -51
- nautobot/core/tasks.py +1 -1
- nautobot/core/templates/about.html +67 -0
- 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 +3 -0
- nautobot/core/templates/inc/nav_menu.html +2 -1
- nautobot/core/templates/inc/relationships_panel.html +1 -1
- 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 +16 -0
- nautobot/core/templates/panel_table.html +12 -0
- nautobot/core/templates/utilities/render_jinja2.html +117 -0
- nautobot/core/templates/utilities/templatetags/tag.html +1 -1
- nautobot/core/templates/utilities/theme_preview.html +7 -0
- nautobot/core/templatetags/helpers.py +104 -6
- nautobot/core/templatetags/ui_framework.py +40 -0
- nautobot/core/testing/__init__.py +8 -8
- nautobot/core/testing/api.py +187 -137
- nautobot/core/testing/context.py +18 -0
- nautobot/core/testing/filters.py +44 -34
- nautobot/core/testing/forms.py +2 -0
- nautobot/core/testing/views.py +68 -146
- 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 +2 -1
- nautobot/core/tests/nautobot_config.py +198 -0
- nautobot/core/tests/runner.py +3 -3
- nautobot/core/tests/test_api.py +154 -176
- nautobot/core/tests/test_events.py +214 -0
- nautobot/core/tests/test_forms.py +1 -0
- nautobot/core/tests/test_jinja_filters.py +1 -0
- nautobot/core/tests/test_jobs.py +387 -14
- nautobot/core/tests/test_navigations.py +7 -241
- nautobot/core/tests/test_settings_schema.py +7 -0
- nautobot/core/tests/test_tables.py +100 -0
- nautobot/core/tests/test_templatetags_helpers.py +16 -0
- nautobot/core/tests/test_ui.py +150 -0
- nautobot/core/tests/test_utils.py +55 -18
- nautobot/core/tests/test_views.py +153 -5
- 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 +280 -0
- nautobot/core/ui/object_detail.py +1855 -0
- nautobot/core/ui/utils.py +36 -0
- nautobot/core/urls.py +15 -0
- nautobot/core/utils/config.py +30 -3
- nautobot/core/utils/lookup.py +12 -2
- nautobot/core/utils/querysets.py +64 -0
- nautobot/core/utils/requests.py +24 -9
- nautobot/core/views/__init__.py +48 -1
- nautobot/core/views/generic.py +82 -177
- nautobot/core/views/mixins.py +98 -38
- nautobot/core/views/paginator.py +8 -5
- nautobot/core/views/renderers.py +9 -9
- nautobot/core/views/utils.py +11 -0
- nautobot/core/wsgi.py +3 -3
- nautobot/dcim/api/serializers.py +82 -189
- nautobot/dcim/api/urls.py +5 -0
- nautobot/dcim/api/views.py +57 -110
- nautobot/dcim/apps.py +1 -0
- nautobot/dcim/choices.py +28 -0
- nautobot/dcim/factory.py +58 -0
- nautobot/dcim/filters/__init__.py +204 -2
- nautobot/dcim/forms.py +221 -9
- 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/migrations/0067_controllermanageddevicegroup_tenant.py +25 -0
- nautobot/dcim/models/__init__.py +5 -1
- nautobot/dcim/models/device_component_templates.py +2 -2
- nautobot/dcim/models/device_components.py +22 -20
- nautobot/dcim/models/devices.py +181 -3
- nautobot/dcim/models/locations.py +3 -3
- nautobot/dcim/models/power.py +6 -5
- 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 +103 -7
- nautobot/dcim/tables/devicetypes.py +2 -2
- nautobot/dcim/tables/racks.py +1 -1
- nautobot/dcim/templates/dcim/controller/base.html +10 -0
- nautobot/dcim/templates/dcim/controller_create.html +2 -7
- nautobot/dcim/templates/dcim/controller_retrieve.html +6 -10
- nautobot/dcim/templates/dcim/controller_wirelessnetworks.html +25 -0
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +68 -0
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +51 -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 +4 -10
- nautobot/dcim/templates/dcim/device_edit.html +36 -37
- nautobot/dcim/templates/dcim/interface.html +1 -0
- nautobot/dcim/templates/dcim/interface_edit.html +1 -0
- nautobot/dcim/templates/dcim/location.html +1 -9
- nautobot/dcim/templates/dcim/location_edit.html +1 -7
- nautobot/dcim/templates/dcim/locationtype.html +0 -107
- nautobot/dcim/templates/dcim/locationtype_retrieve.html +8 -0
- 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 +68 -0
- nautobot/dcim/templates/dcim/virtualdevicecontext_update.html +28 -0
- nautobot/dcim/tests/integration/test_controller.py +62 -0
- nautobot/dcim/tests/integration/test_controller_managed_device_group.py +71 -0
- nautobot/dcim/tests/test_api.py +188 -64
- nautobot/dcim/tests/test_filters.py +172 -76
- nautobot/dcim/tests/test_graphql.py +52 -0
- nautobot/dcim/tests/test_jobs.py +118 -0
- nautobot/dcim/tests/test_models.py +159 -5
- nautobot/dcim/tests/test_signals.py +1 -0
- nautobot/dcim/tests/test_views.py +118 -88
- nautobot/dcim/urls.py +72 -27
- nautobot/dcim/utils.py +2 -2
- nautobot/dcim/views.py +357 -62
- nautobot/extras/api/customfields.py +2 -2
- nautobot/extras/api/serializers.py +111 -87
- nautobot/extras/api/urls.py +4 -0
- nautobot/extras/api/views.py +93 -35
- nautobot/extras/choices.py +13 -0
- nautobot/extras/constants.py +2 -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 +66 -5
- nautobot/extras/forms/base.py +2 -2
- nautobot/extras/forms/forms.py +262 -59
- nautobot/extras/forms/mixins.py +3 -3
- nautobot/extras/graphql/types.py +25 -1
- nautobot/extras/health_checks.py +1 -2
- nautobot/extras/jobs.py +114 -20
- 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 +3 -1
- nautobot/extras/migrations/0018_joblog_data_migration.py +7 -9
- 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/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 +5 -1
- nautobot/extras/models/change_logging.py +7 -3
- 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 +237 -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 +54 -19
- nautobot/extras/plugins/marketplace_manifest.yml +455 -0
- nautobot/extras/plugins/tables.py +16 -14
- nautobot/extras/plugins/urls.py +1 -0
- nautobot/extras/plugins/views.py +104 -61
- nautobot/extras/registry.py +1 -1
- nautobot/extras/secrets/__init__.py +2 -2
- nautobot/extras/signals.py +39 -1
- nautobot/extras/tables.py +42 -6
- nautobot/extras/templates/extras/dynamicgroup.html +1 -9
- 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 +52 -6
- nautobot/extras/templates/extras/job_edit.html +6 -2
- nautobot/extras/templates/extras/job_list.html +2 -7
- nautobot/extras/templates/extras/jobqueue_retrieve.html +36 -0
- nautobot/extras/templates/extras/marketplace.html +296 -0
- nautobot/extras/templates/extras/plugin_detail.html +32 -15
- nautobot/extras/templates/extras/plugins_list.html +35 -1
- nautobot/extras/templates/extras/plugins_tiles.html +90 -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 +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 +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 +2 -1
- nautobot/extras/tests/test_dynamicgroups.py +1 -1
- nautobot/extras/tests/test_filters.py +219 -535
- nautobot/extras/tests/test_forms.py +20 -1
- nautobot/extras/tests/test_job_variables.py +73 -152
- nautobot/extras/tests/test_jobs.py +192 -62
- nautobot/extras/tests/test_models.py +71 -16
- nautobot/extras/tests/test_plugins.py +62 -9
- nautobot/extras/tests/test_relationships.py +124 -10
- nautobot/extras/tests/test_utils.py +23 -2
- nautobot/extras/tests/test_views.py +162 -161
- nautobot/extras/tests/test_webhooks.py +2 -1
- nautobot/extras/urls.py +2 -20
- nautobot/extras/utils.py +119 -4
- nautobot/extras/views.py +188 -141
- nautobot/extras/webhooks.py +5 -2
- nautobot/ipam/api/fields.py +3 -3
- nautobot/ipam/api/serializers.py +44 -137
- nautobot/ipam/api/views.py +68 -110
- nautobot/ipam/factory.py +1 -1
- nautobot/ipam/filters.py +3 -2
- nautobot/ipam/models.py +10 -12
- nautobot/ipam/navigation.py +0 -90
- nautobot/ipam/querysets.py +2 -2
- nautobot/ipam/tables.py +3 -1
- 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/routetarget.html +0 -28
- nautobot/ipam/templates/ipam/vlan.html +1 -9
- nautobot/ipam/templates/ipam/vlan_edit.html +1 -7
- nautobot/ipam/templates/ipam/vrf.html +0 -47
- nautobot/ipam/templates/ipam/vrf_edit.html +1 -7
- nautobot/ipam/tests/test_api.py +19 -6
- nautobot/ipam/tests/test_filters.py +39 -119
- nautobot/ipam/tests/test_forms.py +49 -47
- nautobot/ipam/tests/test_migrations.py +30 -30
- nautobot/ipam/tests/test_models.py +56 -36
- nautobot/ipam/tests/test_querysets.py +14 -0
- nautobot/ipam/tests/test_views.py +3 -0
- nautobot/ipam/urls.py +3 -69
- nautobot/ipam/utils/__init__.py +16 -10
- nautobot/ipam/views.py +91 -162
- 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/css/base.css +38 -3
- nautobot/project-static/docs/404.html +463 -19
- nautobot/project-static/docs/apps/index.html +463 -19
- nautobot/project-static/docs/apps/nautobot-apps.html +464 -21
- nautobot/project-static/docs/assets/_mkdocstrings.css +25 -1
- nautobot/project-static/docs/assets/extra.css +5 -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 +479 -25
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +476 -22
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +792 -291
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +507 -33
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +512 -36
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +473 -22
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +469 -20
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +499 -35
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +9883 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +525 -77
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +548 -53
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +672 -96
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +1033 -180
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +526 -51
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +876 -190
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +957 -237
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +477 -23
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +488 -30
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +663 -101
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +949 -481
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +6427 -1236
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +476 -22
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +879 -346
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +830 -173
- nautobot/project-static/docs/development/apps/api/configuration-view.html +463 -19
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +463 -19
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +463 -19
- nautobot/project-static/docs/development/apps/api/models/global-search.html +463 -19
- nautobot/project-static/docs/development/apps/api/models/graphql.html +463 -19
- nautobot/project-static/docs/development/apps/api/models/index.html +463 -19
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +463 -19
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +463 -19
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +463 -19
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +463 -19
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +463 -19
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +463 -19
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +463 -19
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +463 -19
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +463 -19
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +463 -19
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +463 -19
- nautobot/project-static/docs/development/apps/api/prometheus.html +463 -19
- nautobot/project-static/docs/development/apps/api/setup.html +467 -155
- nautobot/project-static/docs/development/apps/api/testing.html +463 -19
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +463 -19
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +463 -19
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +463 -19
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +463 -19
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +743 -130
- nautobot/project-static/docs/development/apps/api/views/base-template.html +463 -19
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +463 -19
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +463 -19
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +463 -19
- nautobot/project-static/docs/development/apps/api/views/index.html +465 -20
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +467 -19
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +493 -19
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +463 -19
- nautobot/project-static/docs/development/apps/api/views/notes.html +463 -19
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +469 -21
- nautobot/project-static/docs/development/apps/api/views/urls.html +463 -19
- nautobot/project-static/docs/development/apps/index.html +463 -19
- nautobot/project-static/docs/development/apps/migration/code-updates.html +464 -52
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +464 -20
- nautobot/project-static/docs/development/apps/migration/from-v1.html +463 -19
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +463 -19
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +463 -19
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +463 -19
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +466 -22
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +9261 -0
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +9375 -0
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +9671 -0
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +9559 -0
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +466 -22
- nautobot/project-static/docs/development/core/application-registry.html +463 -19
- nautobot/project-static/docs/development/core/best-practices.html +463 -19
- nautobot/project-static/docs/development/core/bootstrap-ui.html +463 -19
- nautobot/project-static/docs/development/core/caching.html +463 -19
- nautobot/project-static/docs/development/core/controllers.html +465 -19
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +491 -90
- nautobot/project-static/docs/development/core/generic-views.html +463 -19
- nautobot/project-static/docs/development/core/getting-started.html +541 -129
- nautobot/project-static/docs/development/core/homepage.html +474 -30
- nautobot/project-static/docs/development/core/index.html +463 -19
- nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +9754 -0
- nautobot/project-static/docs/development/core/model-checklist.html +473 -27
- nautobot/project-static/docs/development/core/model-features.html +463 -19
- nautobot/project-static/docs/development/core/natural-keys.html +463 -19
- nautobot/project-static/docs/development/core/navigation-menu.html +480 -26
- nautobot/project-static/docs/development/core/release-checklist.html +480 -48
- nautobot/project-static/docs/development/core/role-internals.html +463 -19
- nautobot/project-static/docs/development/core/settings.html +463 -19
- nautobot/project-static/docs/development/core/style-guide.html +466 -22
- nautobot/project-static/docs/development/core/templates.html +473 -22
- nautobot/project-static/docs/development/core/testing.html +463 -19
- nautobot/project-static/docs/development/core/ui-component-framework.html +11116 -0
- nautobot/project-static/docs/development/core/user-preferences.html +466 -22
- nautobot/project-static/docs/development/index.html +463 -19
- nautobot/project-static/docs/development/jobs/index.html +501 -21
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +463 -19
- nautobot/project-static/docs/index.html +471 -38
- 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/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/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/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/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/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 +469 -23
- nautobot/project-static/docs/overview/design_philosophy.html +463 -19
- nautobot/project-static/docs/release-notes/index.html +485 -22
- nautobot/project-static/docs/release-notes/version-1.0.html +651 -208
- nautobot/project-static/docs/release-notes/version-1.1.html +648 -205
- nautobot/project-static/docs/release-notes/version-1.2.html +723 -280
- nautobot/project-static/docs/release-notes/version-1.3.html +749 -306
- nautobot/project-static/docs/release-notes/version-1.4.html +834 -392
- nautobot/project-static/docs/release-notes/version-1.5.html +1022 -581
- nautobot/project-static/docs/release-notes/version-1.6.html +942 -518
- nautobot/project-static/docs/release-notes/version-2.0.html +945 -504
- nautobot/project-static/docs/release-notes/version-2.1.html +780 -339
- nautobot/project-static/docs/release-notes/version-2.2.html +773 -332
- nautobot/project-static/docs/release-notes/version-2.3.html +1142 -448
- nautobot/project-static/docs/release-notes/version-2.4.html +10323 -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 +342 -270
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +463 -19
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +463 -19
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +463 -19
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +475 -32
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +463 -19
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +894 -180
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +463 -19
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +463 -19
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +476 -29
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +463 -19
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +463 -19
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +463 -19
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +463 -19
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +463 -19
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +465 -21
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +463 -19
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +463 -19
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +463 -19
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +483 -23
- nautobot/project-static/docs/user-guide/administration/installation/index.html +468 -20
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +464 -20
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +463 -19
- nautobot/project-static/docs/user-guide/administration/installation/services.html +463 -19
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +463 -19
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +484 -41
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +477 -66
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +477 -66
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +463 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +463 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +463 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +463 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +463 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +466 -23
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +463 -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 +463 -19
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +469 -21
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +499 -20
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +489 -22
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +9375 -0
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +470 -30
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +466 -22
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +463 -19
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +466 -22
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +9313 -0
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +9217 -0
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +9211 -0
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +9277 -0
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +463 -19
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +463 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +463 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +463 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +463 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +463 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +463 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +463 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +463 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +463 -19
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +463 -19
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +468 -22
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +463 -19
- 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 +463 -19
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +463 -19
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +466 -22
- nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +9444 -0
- nautobot/project-static/docs/user-guide/index.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +466 -22
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +467 -23
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +9617 -0
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +466 -22
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +472 -23
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +466 -22
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +466 -22
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +9224 -0
- 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 +466 -22
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +467 -23
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +9292 -0
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +511 -40
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +494 -23
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +466 -22
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +531 -56
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +463 -19
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +463 -19
- nautobot/project-static/img/jinja_logo.svg +97 -0
- nautobot/project-static/js/forms.js +6 -1
- nautobot/project-static/js/nav_menu.js +2 -1
- nautobot/tenancy/api/serializers.py +0 -2
- nautobot/tenancy/api/views.py +9 -13
- 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 +35 -24
- nautobot/users/admin.py +3 -1
- nautobot/users/api/serializers.py +4 -4
- nautobot/users/api/views.py +3 -3
- 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/api/views.py +5 -24
- nautobot/virtualization/filters.py +1 -2
- nautobot/virtualization/models.py +1 -1
- nautobot/virtualization/navigation.py +0 -48
- nautobot/virtualization/tables.py +2 -2
- nautobot/virtualization/templates/virtualization/cluster_edit.html +1 -7
- nautobot/virtualization/templates/virtualization/clustertype.html +0 -39
- nautobot/virtualization/templates/virtualization/virtualmachine.html +1 -9
- nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +2 -8
- nautobot/virtualization/tests/test_filters.py +57 -166
- 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 +56 -0
- nautobot/wireless/tests/__init__.py +0 -0
- nautobot/wireless/tests/integration/__init__.py +0 -0
- nautobot/wireless/tests/integration/test_radio_profile.py +42 -0
- nautobot/wireless/tests/test_api.py +247 -0
- nautobot/wireless/tests/test_filters.py +82 -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 +119 -0
- {nautobot-2.3.15b1.dist-info → nautobot-2.4.0.dist-info}/METADATA +11 -13
- {nautobot-2.3.15b1.dist-info → nautobot-2.4.0.dist-info}/RECORD +783 -613
- {nautobot-2.3.15b1.dist-info → nautobot-2.4.0.dist-info}/WHEEL +1 -1
- nautobot/core/fixtures/user-data.json +0 -59
- nautobot/core/utils/navigation.py +0 -54
- {nautobot-2.3.15b1.dist-info → nautobot-2.4.0.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.3.15b1.dist-info → nautobot-2.4.0.dist-info}/NOTICE +0 -0
- {nautobot-2.3.15b1.dist-info → nautobot-2.4.0.dist-info}/entry_points.txt +0 -0
nautobot/extras/views.py
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from urllib.parse import parse_qs
|
|
3
3
|
|
|
4
|
-
from celery import chain
|
|
5
|
-
from django.conf import settings
|
|
6
4
|
from django.contrib import messages
|
|
7
5
|
from django.contrib.contenttypes.models import ContentType
|
|
8
6
|
from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
|
@@ -18,21 +16,21 @@ from django.utils import timezone
|
|
|
18
16
|
from django.utils.encoding import iri_to_uri
|
|
19
17
|
from django.utils.html import format_html
|
|
20
18
|
from django.utils.http import url_has_allowed_host_and_scheme
|
|
19
|
+
from django.utils.timezone import get_current_timezone
|
|
21
20
|
from django.views.generic import View
|
|
22
21
|
from django_tables2 import RequestConfig
|
|
23
22
|
from jsonschema.validators import Draft7Validator
|
|
24
23
|
from rest_framework.decorators import action
|
|
25
24
|
from rest_framework.permissions import IsAuthenticated
|
|
26
25
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
except ImportError: # python 3.8
|
|
30
|
-
from backports.zoneinfo import ZoneInfo
|
|
31
|
-
|
|
26
|
+
from nautobot.core.constants import PAGINATE_COUNT_DEFAULT
|
|
27
|
+
from nautobot.core.events import publish_event
|
|
32
28
|
from nautobot.core.forms import restrict_form_fields
|
|
33
29
|
from nautobot.core.models.querysets import count_related
|
|
34
|
-
from nautobot.core.models.utils import pretty_print_query
|
|
30
|
+
from nautobot.core.models.utils import pretty_print_query, serialize_object_v2
|
|
35
31
|
from nautobot.core.tables import ButtonsColumn
|
|
32
|
+
from nautobot.core.ui import object_detail
|
|
33
|
+
from nautobot.core.ui.choices import SectionChoices
|
|
36
34
|
from nautobot.core.utils.config import get_settings_or_config
|
|
37
35
|
from nautobot.core.utils.lookup import (
|
|
38
36
|
get_filterset_for_model,
|
|
@@ -45,6 +43,7 @@ from nautobot.core.utils.requests import normalize_querydict
|
|
|
45
43
|
from nautobot.core.views import generic, viewsets
|
|
46
44
|
from nautobot.core.views.mixins import (
|
|
47
45
|
GetReturnURLMixin,
|
|
46
|
+
ObjectBulkCreateViewMixin,
|
|
48
47
|
ObjectBulkDestroyViewMixin,
|
|
49
48
|
ObjectBulkUpdateViewMixin,
|
|
50
49
|
ObjectChangeLogViewMixin,
|
|
@@ -52,18 +51,23 @@ from nautobot.core.views.mixins import (
|
|
|
52
51
|
ObjectDetailViewMixin,
|
|
53
52
|
ObjectEditViewMixin,
|
|
54
53
|
ObjectListViewMixin,
|
|
54
|
+
ObjectNotesViewMixin,
|
|
55
55
|
ObjectPermissionRequiredMixin,
|
|
56
56
|
)
|
|
57
57
|
from nautobot.core.views.paginator import EnhancedPaginator, get_paginate_count
|
|
58
58
|
from nautobot.core.views.utils import prepare_cloned_fields
|
|
59
59
|
from nautobot.core.views.viewsets import NautobotUIViewSet
|
|
60
|
-
from nautobot.dcim.models import Controller, Device, Interface, Module, Rack
|
|
61
|
-
from nautobot.dcim.tables import
|
|
62
|
-
|
|
60
|
+
from nautobot.dcim.models import Controller, Device, Interface, Module, Rack, VirtualDeviceContext
|
|
61
|
+
from nautobot.dcim.tables import (
|
|
62
|
+
ControllerTable,
|
|
63
|
+
DeviceTable,
|
|
64
|
+
InterfaceTable,
|
|
65
|
+
ModuleTable,
|
|
66
|
+
RackTable,
|
|
67
|
+
VirtualDeviceContextTable,
|
|
68
|
+
)
|
|
63
69
|
from nautobot.extras.context_managers import deferred_change_logging_for_bulk_operation
|
|
64
|
-
from nautobot.extras.
|
|
65
|
-
from nautobot.extras.tasks import delete_custom_field_data
|
|
66
|
-
from nautobot.extras.utils import get_base_template, get_worker_count
|
|
70
|
+
from nautobot.extras.utils import get_base_template, get_job_queue, get_worker_count
|
|
67
71
|
from nautobot.ipam.models import IPAddress, Prefix, VLAN
|
|
68
72
|
from nautobot.ipam.tables import IPAddressTable, PrefixTable, VLANTable
|
|
69
73
|
from nautobot.virtualization.models import VirtualMachine, VMInterface
|
|
@@ -71,7 +75,13 @@ from nautobot.virtualization.tables import VirtualMachineTable, VMInterfaceTable
|
|
|
71
75
|
|
|
72
76
|
from . import filters, forms, tables
|
|
73
77
|
from .api import serializers
|
|
74
|
-
from .choices import
|
|
78
|
+
from .choices import (
|
|
79
|
+
DynamicGroupTypeChoices,
|
|
80
|
+
JobExecutionType,
|
|
81
|
+
JobQueueTypeChoices,
|
|
82
|
+
JobResultStatusChoices,
|
|
83
|
+
LogLevelChoices,
|
|
84
|
+
)
|
|
75
85
|
from .datasources import (
|
|
76
86
|
enqueue_git_repository_diff_origin_and_local,
|
|
77
87
|
enqueue_pull_git_repository_and_refresh_data,
|
|
@@ -96,6 +106,7 @@ from .models import (
|
|
|
96
106
|
JobButton,
|
|
97
107
|
JobHook,
|
|
98
108
|
JobLogEntry,
|
|
109
|
+
JobQueue,
|
|
99
110
|
JobResult,
|
|
100
111
|
MetadataType,
|
|
101
112
|
Note,
|
|
@@ -643,37 +654,7 @@ class CustomFieldBulkDeleteView(generic.BulkDeleteView):
|
|
|
643
654
|
queryset = CustomField.objects.all()
|
|
644
655
|
table = tables.CustomFieldTable
|
|
645
656
|
filterset = filters.CustomFieldFilterSet
|
|
646
|
-
|
|
647
|
-
def construct_custom_field_delete_tasks(self, queryset):
|
|
648
|
-
"""
|
|
649
|
-
Helper method to construct a list of celery tasks to execute when bulk deleting custom fields.
|
|
650
|
-
"""
|
|
651
|
-
change_context = change_context_state.get()
|
|
652
|
-
if change_context is None:
|
|
653
|
-
context = None
|
|
654
|
-
else:
|
|
655
|
-
context = change_context.as_dict(queryset)
|
|
656
|
-
context["context_detail"] = "bulk delete custom field data"
|
|
657
|
-
tasks = [
|
|
658
|
-
delete_custom_field_data.si(obj.key, set(obj.content_types.values_list("pk", flat=True)), context)
|
|
659
|
-
for obj in queryset
|
|
660
|
-
]
|
|
661
|
-
return tasks
|
|
662
|
-
|
|
663
|
-
def perform_pre_delete(self, request, queryset):
|
|
664
|
-
"""
|
|
665
|
-
Remove all Custom Field Keys/Values from _custom_field_data of the related ContentType in the background.
|
|
666
|
-
"""
|
|
667
|
-
if not get_worker_count():
|
|
668
|
-
messages.error(
|
|
669
|
-
request, "Celery worker process not running. Object custom fields may fail to reflect this deletion."
|
|
670
|
-
)
|
|
671
|
-
return
|
|
672
|
-
tasks = self.construct_custom_field_delete_tasks(queryset)
|
|
673
|
-
# Executing the tasks in the background sequentially using chain() aligns with how a single
|
|
674
|
-
# CustomField object is deleted. We decided to not check the result because it needs at least one worker
|
|
675
|
-
# to be active and comes with extra performance penalty.
|
|
676
|
-
chain(*tasks).apply_async()
|
|
657
|
+
form = forms.CustomFieldBulkDeleteForm
|
|
677
658
|
|
|
678
659
|
|
|
679
660
|
#
|
|
@@ -1006,6 +987,27 @@ class ExternalIntegrationUIViewSet(NautobotUIViewSet):
|
|
|
1006
987
|
serializer_class = serializers.ExternalIntegrationSerializer
|
|
1007
988
|
table_class = tables.ExternalIntegrationTable
|
|
1008
989
|
|
|
990
|
+
object_detail_content = object_detail.ObjectDetailContent(
|
|
991
|
+
panels=(
|
|
992
|
+
object_detail.ObjectFieldsPanel(
|
|
993
|
+
section=SectionChoices.LEFT_HALF,
|
|
994
|
+
weight=100,
|
|
995
|
+
# Default ordering with __all__ leaves something to be desired
|
|
996
|
+
fields=[
|
|
997
|
+
"name",
|
|
998
|
+
"remote_url",
|
|
999
|
+
"http_method",
|
|
1000
|
+
"headers",
|
|
1001
|
+
"verify_ssl",
|
|
1002
|
+
"ca_file_path",
|
|
1003
|
+
"secrets_group",
|
|
1004
|
+
"timeout",
|
|
1005
|
+
"extra_config",
|
|
1006
|
+
],
|
|
1007
|
+
),
|
|
1008
|
+
),
|
|
1009
|
+
)
|
|
1010
|
+
|
|
1009
1011
|
|
|
1010
1012
|
#
|
|
1011
1013
|
# Git repositories
|
|
@@ -1060,10 +1062,10 @@ class GitRepositoryEditView(generic.ObjectEditView):
|
|
|
1060
1062
|
obj.user = request.user
|
|
1061
1063
|
return super().alter_obj(obj, request, url_args, url_kwargs)
|
|
1062
1064
|
|
|
1063
|
-
def get_return_url(self, request, obj):
|
|
1065
|
+
def get_return_url(self, request, obj=None, default_return_url=None):
|
|
1064
1066
|
if request.method == "POST":
|
|
1065
1067
|
return reverse("extras:gitrepository_result", kwargs={"pk": obj.pk})
|
|
1066
|
-
return super().get_return_url(request, obj)
|
|
1068
|
+
return super().get_return_url(request, obj=obj, default_return_url=default_return_url)
|
|
1067
1069
|
|
|
1068
1070
|
|
|
1069
1071
|
class GitRepositoryDeleteView(generic.ObjectDeleteView):
|
|
@@ -1211,27 +1213,27 @@ class ImageAttachmentEditView(generic.ObjectEditView):
|
|
|
1211
1213
|
return get_object_or_404(self.queryset, pk=kwargs["pk"])
|
|
1212
1214
|
return self.queryset.model()
|
|
1213
1215
|
|
|
1214
|
-
def alter_obj(self,
|
|
1215
|
-
if not
|
|
1216
|
+
def alter_obj(self, obj, request, url_args, url_kwargs):
|
|
1217
|
+
if not obj.present_in_database:
|
|
1216
1218
|
# Assign the parent object based on URL kwargs
|
|
1217
|
-
model =
|
|
1218
|
-
if "object_id" in
|
|
1219
|
-
|
|
1220
|
-
elif "slug" in
|
|
1221
|
-
|
|
1219
|
+
model = url_kwargs.get("model")
|
|
1220
|
+
if "object_id" in url_kwargs:
|
|
1221
|
+
obj.parent = get_object_or_404(model, pk=url_kwargs["object_id"])
|
|
1222
|
+
elif "slug" in url_kwargs:
|
|
1223
|
+
obj.parent = get_object_or_404(model, slug=url_kwargs["slug"])
|
|
1222
1224
|
else:
|
|
1223
1225
|
raise RuntimeError("Neither object_id nor slug were provided?")
|
|
1224
|
-
return
|
|
1226
|
+
return obj
|
|
1225
1227
|
|
|
1226
|
-
def get_return_url(self, request,
|
|
1227
|
-
return
|
|
1228
|
+
def get_return_url(self, request, obj=None, default_return_url=None):
|
|
1229
|
+
return obj.parent.get_absolute_url()
|
|
1228
1230
|
|
|
1229
1231
|
|
|
1230
1232
|
class ImageAttachmentDeleteView(generic.ObjectDeleteView):
|
|
1231
1233
|
queryset = ImageAttachment.objects.all()
|
|
1232
1234
|
|
|
1233
|
-
def get_return_url(self, request,
|
|
1234
|
-
return
|
|
1235
|
+
def get_return_url(self, request, obj=None, default_return_url=None):
|
|
1236
|
+
return obj.parent.get_absolute_url()
|
|
1235
1237
|
|
|
1236
1238
|
|
|
1237
1239
|
#
|
|
@@ -1319,10 +1321,18 @@ class JobRunView(ObjectPermissionRequiredMixin, View):
|
|
|
1319
1321
|
# for example "?kwargs_from_job_result=<UUID>&integervar=22"
|
|
1320
1322
|
explicit_initial = initial
|
|
1321
1323
|
initial = job_result.task_kwargs.copy()
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1324
|
+
job_queue = job_result.celery_kwargs.get("queue", None)
|
|
1325
|
+
jq = None
|
|
1326
|
+
if job_queue is not None:
|
|
1327
|
+
try:
|
|
1328
|
+
jq = JobQueue.objects.get(name=job_queue, queue_type=JobQueueTypeChoices.TYPE_CELERY)
|
|
1329
|
+
except JobQueue.DoesNotExist:
|
|
1330
|
+
pass
|
|
1331
|
+
initial["_job_queue"] = jq
|
|
1325
1332
|
initial["_profile"] = job_result.celery_kwargs.get("nautobot_job_profile", False)
|
|
1333
|
+
initial["_ignore_singleton_lock"] = job_result.celery_kwargs.get(
|
|
1334
|
+
"nautobot_job_ignore_singleton_lock", False
|
|
1335
|
+
)
|
|
1326
1336
|
initial.update(explicit_initial)
|
|
1327
1337
|
except JobResult.DoesNotExist:
|
|
1328
1338
|
messages.warning(
|
|
@@ -1337,7 +1347,9 @@ class JobRunView(ObjectPermissionRequiredMixin, View):
|
|
|
1337
1347
|
get_template(job_class.template_name)
|
|
1338
1348
|
template_name = job_class.template_name
|
|
1339
1349
|
except TemplateDoesNotExist as err:
|
|
1340
|
-
messages.error(
|
|
1350
|
+
messages.error(
|
|
1351
|
+
request, f'Unable to render requested custom job template "{job_class.template_name}": {err}'
|
|
1352
|
+
)
|
|
1341
1353
|
except RuntimeError as err:
|
|
1342
1354
|
messages.error(request, f"Unable to run or schedule '{job_model}': {err}")
|
|
1343
1355
|
return redirect("extras:job_list")
|
|
@@ -1360,7 +1372,7 @@ class JobRunView(ObjectPermissionRequiredMixin, View):
|
|
|
1360
1372
|
job_class = get_job(job_model.class_path, reload=True)
|
|
1361
1373
|
job_form = job_class.as_form(request.POST, request.FILES) if job_class is not None else None
|
|
1362
1374
|
schedule_form = forms.JobScheduleForm(request.POST)
|
|
1363
|
-
|
|
1375
|
+
job_queue = request.POST.get("_job_queue")
|
|
1364
1376
|
|
|
1365
1377
|
return_url = request.POST.get("_return_url")
|
|
1366
1378
|
if return_url is not None and url_has_allowed_host_and_scheme(url=return_url, allowed_hosts=request.get_host()):
|
|
@@ -1368,8 +1380,11 @@ class JobRunView(ObjectPermissionRequiredMixin, View):
|
|
|
1368
1380
|
else:
|
|
1369
1381
|
return_url = None
|
|
1370
1382
|
|
|
1371
|
-
|
|
1372
|
-
if
|
|
1383
|
+
queue = get_job_queue(job_queue)
|
|
1384
|
+
if queue is None:
|
|
1385
|
+
queue = job_model.default_job_queue
|
|
1386
|
+
# Allow execution only if a worker process is running on a celery queue and the job is runnable.
|
|
1387
|
+
if queue.queue_type == JobQueueTypeChoices.TYPE_CELERY and not get_worker_count(queue=job_queue):
|
|
1373
1388
|
messages.error(request, "Unable to run or schedule job: Celery worker process not running.")
|
|
1374
1389
|
elif not job_model.installed or job_class is None:
|
|
1375
1390
|
messages.error(request, "Unable to run or schedule job: Job is not presently installed.")
|
|
@@ -1388,10 +1403,21 @@ class JobRunView(ObjectPermissionRequiredMixin, View):
|
|
|
1388
1403
|
"One of these two flags must be removed before this job can be scheduled or run.",
|
|
1389
1404
|
)
|
|
1390
1405
|
elif job_form is not None and job_form.is_valid() and schedule_form.is_valid():
|
|
1391
|
-
|
|
1406
|
+
job_queue = job_form.cleaned_data.pop("_job_queue", None)
|
|
1407
|
+
jq = None
|
|
1408
|
+
if job_queue is not None:
|
|
1409
|
+
try:
|
|
1410
|
+
jq = JobQueue.objects.get(pk=job_queue)
|
|
1411
|
+
except (ValidationError, JobQueue.DoesNotExist):
|
|
1412
|
+
try:
|
|
1413
|
+
jq = JobQueue.objects.get(name=job_queue)
|
|
1414
|
+
except JobQueue.DoesNotExist:
|
|
1415
|
+
pass
|
|
1416
|
+
|
|
1392
1417
|
dryrun = job_form.cleaned_data.get("dryrun", False)
|
|
1393
1418
|
# Run the job. A new JobResult is created.
|
|
1394
1419
|
profile = job_form.cleaned_data.pop("_profile")
|
|
1420
|
+
ignore_singleton_lock = job_form.cleaned_data.pop("_ignore_singleton_lock", False)
|
|
1395
1421
|
schedule_type = schedule_form.cleaned_data["_schedule_type"]
|
|
1396
1422
|
|
|
1397
1423
|
if (not dryrun and job_model.approval_required) or schedule_type in JobExecutionType.SCHEDULE_CHOICES:
|
|
@@ -1403,8 +1429,9 @@ class JobRunView(ObjectPermissionRequiredMixin, View):
|
|
|
1403
1429
|
interval=schedule_type,
|
|
1404
1430
|
crontab=schedule_form.cleaned_data.get("_recurrence_custom_time"),
|
|
1405
1431
|
approval_required=job_model.approval_required,
|
|
1406
|
-
task_queue=
|
|
1432
|
+
task_queue=jq.name if jq else None,
|
|
1407
1433
|
profile=profile,
|
|
1434
|
+
ignore_singleton_lock=ignore_singleton_lock,
|
|
1408
1435
|
**job_class.serialize_data(job_form.cleaned_data),
|
|
1409
1436
|
)
|
|
1410
1437
|
|
|
@@ -1422,7 +1449,8 @@ class JobRunView(ObjectPermissionRequiredMixin, View):
|
|
|
1422
1449
|
job_model,
|
|
1423
1450
|
request.user,
|
|
1424
1451
|
profile=profile,
|
|
1425
|
-
|
|
1452
|
+
ignore_singleton_lock=ignore_singleton_lock,
|
|
1453
|
+
task_queue=jq.name if jq else None,
|
|
1426
1454
|
**job_class.serialize_data(job_kwargs),
|
|
1427
1455
|
)
|
|
1428
1456
|
|
|
@@ -1447,7 +1475,9 @@ class JobRunView(ObjectPermissionRequiredMixin, View):
|
|
|
1447
1475
|
get_template(job_class.template_name)
|
|
1448
1476
|
template_name = job_class.template_name
|
|
1449
1477
|
except TemplateDoesNotExist as err:
|
|
1450
|
-
messages.error(
|
|
1478
|
+
messages.error(
|
|
1479
|
+
request, f'Unable to render requested custom job template "{job_class.template_name}": {err}'
|
|
1480
|
+
)
|
|
1451
1481
|
|
|
1452
1482
|
return render(
|
|
1453
1483
|
request,
|
|
@@ -1478,23 +1508,6 @@ class JobBulkEditView(generic.BulkEditView):
|
|
|
1478
1508
|
form = forms.JobBulkEditForm
|
|
1479
1509
|
template_name = "extras/job_bulk_edit.html"
|
|
1480
1510
|
|
|
1481
|
-
def extra_post_save_action(self, obj, form):
|
|
1482
|
-
cleaned_data = form.cleaned_data
|
|
1483
|
-
|
|
1484
|
-
# Handle text related fields
|
|
1485
|
-
for overridable_field in JOB_OVERRIDABLE_FIELDS:
|
|
1486
|
-
override_field = overridable_field + "_override"
|
|
1487
|
-
clear_override_field = "clear_" + overridable_field + "_override"
|
|
1488
|
-
reset_override = cleaned_data.get(clear_override_field, False)
|
|
1489
|
-
override_value = cleaned_data.get(overridable_field)
|
|
1490
|
-
if reset_override:
|
|
1491
|
-
setattr(obj, override_field, False)
|
|
1492
|
-
elif not reset_override and override_value not in [None, ""]:
|
|
1493
|
-
setattr(obj, override_field, True)
|
|
1494
|
-
setattr(obj, overridable_field, override_value)
|
|
1495
|
-
|
|
1496
|
-
obj.validated_save()
|
|
1497
|
-
|
|
1498
1511
|
|
|
1499
1512
|
class JobDeleteView(generic.ObjectDeleteView):
|
|
1500
1513
|
queryset = JobModel.objects.all()
|
|
@@ -1534,7 +1547,7 @@ class JobApprovalRequestView(generic.ObjectView):
|
|
|
1534
1547
|
if job_class is not None:
|
|
1535
1548
|
# Render the form with all fields disabled
|
|
1536
1549
|
initial = instance.kwargs
|
|
1537
|
-
initial["
|
|
1550
|
+
initial["_job_queue"] = instance.queue
|
|
1538
1551
|
initial["_profile"] = instance.celery_kwargs.get("profile", False)
|
|
1539
1552
|
job_form = job_class().as_form(initial=initial, approval_view=True)
|
|
1540
1553
|
else:
|
|
@@ -1593,12 +1606,15 @@ class JobApprovalRequestView(generic.ObjectView):
|
|
|
1593
1606
|
messages.error(request, "You do not have permission to deny this request.")
|
|
1594
1607
|
else:
|
|
1595
1608
|
# Delete the scheduled_job instance
|
|
1609
|
+
publish_event_payload = {"data": serialize_object_v2(scheduled_job)}
|
|
1596
1610
|
scheduled_job.delete()
|
|
1597
1611
|
if request.user == scheduled_job.user:
|
|
1598
1612
|
messages.error(request, f"Approval request for {scheduled_job.name} was revoked")
|
|
1599
1613
|
else:
|
|
1600
1614
|
messages.error(request, f"Approval of {scheduled_job.name} was denied")
|
|
1601
1615
|
|
|
1616
|
+
publish_event(topic="nautobot.jobs.approval.denied", payload=publish_event_payload)
|
|
1617
|
+
|
|
1602
1618
|
return redirect("extras:scheduledjob_approval_queue_list")
|
|
1603
1619
|
|
|
1604
1620
|
elif approve or force_approve:
|
|
@@ -1620,6 +1636,9 @@ class JobApprovalRequestView(generic.ObjectView):
|
|
|
1620
1636
|
scheduled_job.approved_at = timezone.now()
|
|
1621
1637
|
scheduled_job.save()
|
|
1622
1638
|
|
|
1639
|
+
publish_event_payload = {"data": serialize_object_v2(scheduled_job)}
|
|
1640
|
+
publish_event(topic="nautobot.jobs.approval.approved", payload=publish_event_payload)
|
|
1641
|
+
|
|
1623
1642
|
messages.success(request, f"{scheduled_job.name} was approved and will now begin execution")
|
|
1624
1643
|
|
|
1625
1644
|
return redirect("extras:scheduledjob_approval_queue_list")
|
|
@@ -1634,6 +1653,28 @@ class JobApprovalRequestView(generic.ObjectView):
|
|
|
1634
1653
|
)
|
|
1635
1654
|
|
|
1636
1655
|
|
|
1656
|
+
class JobQueueUIViewSet(NautobotUIViewSet):
|
|
1657
|
+
bulk_update_form_class = forms.JobQueueBulkEditForm
|
|
1658
|
+
filterset_form_class = forms.JobQueueFilterForm
|
|
1659
|
+
queryset = JobQueue.objects.all()
|
|
1660
|
+
form_class = forms.JobQueueForm
|
|
1661
|
+
filterset_class = filters.JobQueueFilterSet
|
|
1662
|
+
serializer_class = serializers.JobQueueSerializer
|
|
1663
|
+
table_class = tables.JobQueueTable
|
|
1664
|
+
|
|
1665
|
+
def get_extra_context(self, request, instance):
|
|
1666
|
+
context = super().get_extra_context(request, instance)
|
|
1667
|
+
|
|
1668
|
+
if self.action == "retrieve":
|
|
1669
|
+
jobs = instance.jobs.restrict(request.user, "view")
|
|
1670
|
+
jobs_table = tables.JobTable(jobs, orderable=False)
|
|
1671
|
+
paginate = {"paginator_class": EnhancedPaginator, "per_page": get_paginate_count(request)}
|
|
1672
|
+
RequestConfig(request, paginate).configure(jobs_table)
|
|
1673
|
+
context["jobs_table"] = jobs_table
|
|
1674
|
+
|
|
1675
|
+
return context
|
|
1676
|
+
|
|
1677
|
+
|
|
1637
1678
|
#
|
|
1638
1679
|
# Saved Views
|
|
1639
1680
|
#
|
|
@@ -1833,7 +1874,7 @@ class SavedViewUIViewSet(
|
|
|
1833
1874
|
if derived_instance and derived_instance.config.get("pagination_count", None):
|
|
1834
1875
|
pagination_count = derived_instance.config["pagination_count"]
|
|
1835
1876
|
else:
|
|
1836
|
-
pagination_count = get_settings_or_config("PAGINATE_COUNT")
|
|
1877
|
+
pagination_count = get_settings_or_config("PAGINATE_COUNT", fallback=PAGINATE_COUNT_DEFAULT)
|
|
1837
1878
|
sv.config["pagination_count"] = int(pagination_count)
|
|
1838
1879
|
sort_order = param_dict.get("sort", [])
|
|
1839
1880
|
if not sort_order:
|
|
@@ -1927,7 +1968,7 @@ class ScheduledJobView(generic.ObjectView):
|
|
|
1927
1968
|
return {
|
|
1928
1969
|
"labels": labels,
|
|
1929
1970
|
"job_class_found": (job_class is not None),
|
|
1930
|
-
"default_time_zone":
|
|
1971
|
+
"default_time_zone": get_current_timezone(),
|
|
1931
1972
|
**super().get_extra_context(request, instance),
|
|
1932
1973
|
}
|
|
1933
1974
|
|
|
@@ -1986,6 +2027,9 @@ def get_annotated_jobresult_queryset():
|
|
|
1986
2027
|
debug_log_count=count_related(
|
|
1987
2028
|
JobLogEntry, "job_result", filter_dict={"log_level": LogLevelChoices.LOG_DEBUG}
|
|
1988
2029
|
),
|
|
2030
|
+
success_log_count=count_related(
|
|
2031
|
+
JobLogEntry, "job_result", filter_dict={"log_level": LogLevelChoices.LOG_SUCCESS}
|
|
2032
|
+
),
|
|
1989
2033
|
info_log_count=count_related(
|
|
1990
2034
|
JobLogEntry, "job_result", filter_dict={"log_level": LogLevelChoices.LOG_INFO}
|
|
1991
2035
|
),
|
|
@@ -2465,6 +2509,12 @@ class RoleUIViewSet(viewsets.NautobotUIViewSet):
|
|
|
2465
2509
|
module_table.columns.hide("role")
|
|
2466
2510
|
RequestConfig(request, paginate).configure(module_table)
|
|
2467
2511
|
context["module_table"] = module_table
|
|
2512
|
+
if ContentType.objects.get_for_model(VirtualDeviceContext) in context["content_types"]:
|
|
2513
|
+
vdcs = instance.virtual_device_contexts.restrict(request.user, "view")
|
|
2514
|
+
vdc_table = VirtualDeviceContextTable(vdcs)
|
|
2515
|
+
vdc_table.columns.hide("role")
|
|
2516
|
+
RequestConfig(request, paginate).configure(vdc_table)
|
|
2517
|
+
context["vdc_table"] = vdc_table
|
|
2468
2518
|
return context
|
|
2469
2519
|
|
|
2470
2520
|
|
|
@@ -2473,38 +2523,56 @@ class RoleUIViewSet(viewsets.NautobotUIViewSet):
|
|
|
2473
2523
|
#
|
|
2474
2524
|
|
|
2475
2525
|
|
|
2476
|
-
class
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2526
|
+
class SecretUIViewSet(
|
|
2527
|
+
ObjectDetailViewMixin,
|
|
2528
|
+
ObjectListViewMixin,
|
|
2529
|
+
ObjectEditViewMixin,
|
|
2530
|
+
ObjectDestroyViewMixin,
|
|
2531
|
+
ObjectBulkCreateViewMixin, # 3.0 TODO: remove, unused
|
|
2532
|
+
ObjectBulkDestroyViewMixin,
|
|
2533
|
+
# no ObjectBulkUpdateViewMixin here yet
|
|
2534
|
+
ObjectChangeLogViewMixin,
|
|
2535
|
+
ObjectNotesViewMixin,
|
|
2536
|
+
):
|
|
2484
2537
|
queryset = Secret.objects.all()
|
|
2538
|
+
form_class = forms.SecretForm
|
|
2539
|
+
filterset_class = filters.SecretFilterSet
|
|
2540
|
+
filterset_form_class = forms.SecretFilterForm
|
|
2541
|
+
table_class = tables.SecretTable
|
|
2542
|
+
|
|
2543
|
+
object_detail_content = object_detail.ObjectDetailContent(
|
|
2544
|
+
panels=[
|
|
2545
|
+
object_detail.ObjectFieldsPanel(
|
|
2546
|
+
weight=100, section=SectionChoices.LEFT_HALF, fields="__all__", exclude_fields=["parameters"]
|
|
2547
|
+
),
|
|
2548
|
+
object_detail.KeyValueTablePanel(
|
|
2549
|
+
weight=200, section=SectionChoices.LEFT_HALF, label="Parameters", context_data_key="parameters"
|
|
2550
|
+
),
|
|
2551
|
+
object_detail.ObjectsTablePanel(
|
|
2552
|
+
weight=100,
|
|
2553
|
+
section=SectionChoices.RIGHT_HALF,
|
|
2554
|
+
table_title="Groups containing this secret",
|
|
2555
|
+
table_class=tables.SecretsGroupTable,
|
|
2556
|
+
table_attribute="secrets_groups",
|
|
2557
|
+
footer_content_template_path=None,
|
|
2558
|
+
),
|
|
2559
|
+
],
|
|
2560
|
+
extra_buttons=[
|
|
2561
|
+
object_detail.Button(
|
|
2562
|
+
weight=100,
|
|
2563
|
+
label="Check Secret",
|
|
2564
|
+
icon="mdi-test-tube",
|
|
2565
|
+
javascript_template_path="extras/secret_check.js",
|
|
2566
|
+
attributes={"onClick": "checkSecret()"},
|
|
2567
|
+
),
|
|
2568
|
+
],
|
|
2569
|
+
)
|
|
2485
2570
|
|
|
2486
2571
|
def get_extra_context(self, request, instance):
|
|
2487
|
-
|
|
2488
|
-
if
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
request.user.set_config("extras.configcontext.format", format_, commit=True)
|
|
2492
|
-
elif request.user.is_authenticated:
|
|
2493
|
-
format_ = request.user.get_config("extras.configcontext.format", "json")
|
|
2494
|
-
else:
|
|
2495
|
-
format_ = "json"
|
|
2496
|
-
|
|
2497
|
-
provider = registry["secrets_providers"].get(instance.provider)
|
|
2498
|
-
|
|
2499
|
-
groups = instance.secrets_groups.distinct()
|
|
2500
|
-
groups_table = tables.SecretsGroupTable(groups, orderable=False)
|
|
2501
|
-
|
|
2502
|
-
return {
|
|
2503
|
-
"format": format_,
|
|
2504
|
-
"provider_name": provider.name if provider else instance.provider,
|
|
2505
|
-
"groups_table": groups_table,
|
|
2506
|
-
**super().get_extra_context(request, instance),
|
|
2507
|
-
}
|
|
2572
|
+
ctx = super().get_extra_context(request, instance)
|
|
2573
|
+
if self.action == "retrieve":
|
|
2574
|
+
ctx["parameters"] = instance.parameters
|
|
2575
|
+
return ctx
|
|
2508
2576
|
|
|
2509
2577
|
|
|
2510
2578
|
class SecretProviderParametersFormView(generic.GenericView):
|
|
@@ -2523,27 +2591,6 @@ class SecretProviderParametersFormView(generic.GenericView):
|
|
|
2523
2591
|
)
|
|
2524
2592
|
|
|
2525
2593
|
|
|
2526
|
-
class SecretEditView(generic.ObjectEditView):
|
|
2527
|
-
queryset = Secret.objects.all()
|
|
2528
|
-
model_form = forms.SecretForm
|
|
2529
|
-
template_name = "extras/secret_edit.html"
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
class SecretDeleteView(generic.ObjectDeleteView):
|
|
2533
|
-
queryset = Secret.objects.all()
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
class SecretBulkImportView(generic.BulkImportView): # 3.0 TODO: remove, unused
|
|
2537
|
-
queryset = Secret.objects.all()
|
|
2538
|
-
table = tables.SecretTable
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
class SecretBulkDeleteView(generic.BulkDeleteView):
|
|
2542
|
-
queryset = Secret.objects.all()
|
|
2543
|
-
filterset = filters.SecretFilterSet
|
|
2544
|
-
table = tables.SecretTable
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
2594
|
class SecretsGroupListView(generic.ObjectListView):
|
|
2548
2595
|
queryset = SecretsGroup.objects.all()
|
|
2549
2596
|
filterset = filters.SecretsGroupFilterSet
|
nautobot/extras/webhooks.py
CHANGED
|
@@ -6,12 +6,13 @@ from nautobot.extras.registry import registry
|
|
|
6
6
|
from nautobot.extras.tasks import process_webhook
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
def enqueue_webhooks(object_change, webhook_queryset=None):
|
|
9
|
+
def enqueue_webhooks(object_change, snapshots=None, webhook_queryset=None):
|
|
10
10
|
"""
|
|
11
11
|
Find Webhook(s) assigned to this instance + action and enqueue them to be processed.
|
|
12
12
|
|
|
13
13
|
Args:
|
|
14
14
|
object_change (ObjectChange): The change that may trigger Webhooks to be sent.
|
|
15
|
+
snapshots (list): The before/after data snapshots corresponding to the object_change.
|
|
15
16
|
webhook_queryset (QuerySet): Previously retrieved set of Webhooks to potentially send.
|
|
16
17
|
|
|
17
18
|
Returns:
|
|
@@ -34,6 +35,8 @@ def enqueue_webhooks(object_change, webhook_queryset=None):
|
|
|
34
35
|
webhook_queryset = Webhook.objects.filter(content_types=content_type, enabled=True, **{action_flag: True})
|
|
35
36
|
|
|
36
37
|
if webhook_queryset: # not .exists() as we *want* to populate the queryset cache
|
|
38
|
+
if snapshots is None:
|
|
39
|
+
snapshots = object_change.get_snapshots()
|
|
37
40
|
# fall back to object_data if object_data_v2 is not available
|
|
38
41
|
serialized_data = object_change.object_data_v2
|
|
39
42
|
if serialized_data is None:
|
|
@@ -49,7 +52,7 @@ def enqueue_webhooks(object_change, webhook_queryset=None):
|
|
|
49
52
|
str(timezone.now()),
|
|
50
53
|
object_change.user_name,
|
|
51
54
|
object_change.request_id,
|
|
52
|
-
|
|
55
|
+
snapshots,
|
|
53
56
|
]
|
|
54
57
|
process_webhook.apply_async(args=args)
|
|
55
58
|
|
nautobot/ipam/api/fields.py
CHANGED
|
@@ -7,11 +7,11 @@ class IPFieldSerializer(serializers.CharField):
|
|
|
7
7
|
"""Convert internal (IPNetwork) representation to API (string) representation."""
|
|
8
8
|
return str(value)
|
|
9
9
|
|
|
10
|
-
def to_internal_value(self,
|
|
10
|
+
def to_internal_value(self, data):
|
|
11
11
|
"""Convert API (string) representation to internal (IPNetwork) representation."""
|
|
12
12
|
try:
|
|
13
|
-
return netaddr.IPNetwork(
|
|
13
|
+
return netaddr.IPNetwork(data)
|
|
14
14
|
except netaddr.AddrFormatError:
|
|
15
|
-
raise serializers.ValidationError(f"Invalid IP address format: {
|
|
15
|
+
raise serializers.ValidationError(f"Invalid IP address format: {data}")
|
|
16
16
|
except (TypeError, ValueError) as e:
|
|
17
17
|
raise serializers.ValidationError(e)
|