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
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
from collections.abc import Mapping
|
|
2
2
|
from datetime import datetime, timedelta
|
|
3
|
+
import json
|
|
3
4
|
import logging
|
|
4
5
|
from pathlib import Path
|
|
6
|
+
import sys
|
|
5
7
|
|
|
6
8
|
from celery import current_app
|
|
9
|
+
from celery.beat import _evaluate_entry_args, _evaluate_entry_kwargs, reraise, SchedulingError
|
|
10
|
+
from celery.result import AsyncResult
|
|
7
11
|
from django.conf import settings
|
|
8
12
|
from django_celery_beat.schedulers import DatabaseScheduler, ModelEntry
|
|
9
13
|
from kombu.utils.json import loads
|
|
10
14
|
|
|
11
|
-
from nautobot.extras.
|
|
15
|
+
from nautobot.extras.choices import JobQueueTypeChoices
|
|
16
|
+
from nautobot.extras.models import JobResult, ScheduledJob, ScheduledJobs
|
|
17
|
+
from nautobot.extras.utils import run_kubernetes_job_and_return_job_result
|
|
12
18
|
|
|
13
19
|
logger = logging.getLogger(__name__)
|
|
14
20
|
|
|
@@ -19,7 +25,7 @@ class NautobotScheduleEntry(ModelEntry):
|
|
|
19
25
|
nautobot.extras.models.ScheduledJob model
|
|
20
26
|
"""
|
|
21
27
|
|
|
22
|
-
def __init__(self, model, app=None):
|
|
28
|
+
def __init__(self, model, app=None): # pylint:disable=super-init-not-called # we must copy-and-paste from super
|
|
23
29
|
"""Initialize the model entry."""
|
|
24
30
|
# copy-paste from django_celery_beat.schedulers
|
|
25
31
|
self.app = app or current_app._get_current_object()
|
|
@@ -111,7 +117,46 @@ class NautobotDatabaseScheduler(DatabaseScheduler):
|
|
|
111
117
|
|
|
112
118
|
Ref: https://github.com/celery/django-celery-beat/issues/558#issuecomment-1162730008
|
|
113
119
|
"""
|
|
114
|
-
resp =
|
|
120
|
+
resp = None
|
|
121
|
+
entry = self.reserve(entry) if advance else entry
|
|
122
|
+
task = self.app.tasks.get(entry.task)
|
|
123
|
+
|
|
124
|
+
try:
|
|
125
|
+
entry_args = _evaluate_entry_args(entry.args)
|
|
126
|
+
entry_kwargs = _evaluate_entry_kwargs(entry.kwargs)
|
|
127
|
+
if task:
|
|
128
|
+
scheduled_job = entry.model
|
|
129
|
+
job_queue = scheduled_job.job_queue
|
|
130
|
+
# Distinguish between Celery and Kubernetes job queues
|
|
131
|
+
if job_queue.queue_type == JobQueueTypeChoices.TYPE_KUBERNETES:
|
|
132
|
+
job_result = JobResult.objects.create(
|
|
133
|
+
name=scheduled_job.job_model.name,
|
|
134
|
+
job_model=scheduled_job.job_model,
|
|
135
|
+
scheduled_job=scheduled_job,
|
|
136
|
+
user=scheduled_job.user,
|
|
137
|
+
task_name=scheduled_job.job_model.class_path,
|
|
138
|
+
celery_kwargs=entry.options,
|
|
139
|
+
)
|
|
140
|
+
job_result = run_kubernetes_job_and_return_job_result(
|
|
141
|
+
job_queue, job_result, json.dumps(entry_kwargs)
|
|
142
|
+
)
|
|
143
|
+
# Return an AsyncResult object to mimic the behavior of Celery tasks after the job is finished by Kubernetes Job Pod.
|
|
144
|
+
resp = AsyncResult(job_result.id)
|
|
145
|
+
else:
|
|
146
|
+
resp = task.apply_async(entry_args, entry_kwargs, producer=producer, **entry.options)
|
|
147
|
+
else:
|
|
148
|
+
resp = self.send_task(entry.task, entry_args, entry_kwargs, producer=producer, **entry.options)
|
|
149
|
+
except Exception as exc: # pylint: disable=broad-except
|
|
150
|
+
reraise(
|
|
151
|
+
SchedulingError,
|
|
152
|
+
SchedulingError(f"Couldn't apply scheduled task {entry.name}: {exc}"),
|
|
153
|
+
sys.exc_info()[2],
|
|
154
|
+
)
|
|
155
|
+
finally:
|
|
156
|
+
self._tasks_since_sync += 1
|
|
157
|
+
if self.should_sync():
|
|
158
|
+
self._do_sync()
|
|
159
|
+
|
|
115
160
|
if entry.total_run_count != entry.model.total_run_count:
|
|
116
161
|
entry.total_run_count = entry.model.total_run_count
|
|
117
162
|
entry.model.save()
|
nautobot/core/choices.py
CHANGED
|
@@ -182,14 +182,14 @@ class ButtonActionColorChoices(ChoiceSet):
|
|
|
182
182
|
Map standard button actions to Bootstrap color classes.
|
|
183
183
|
"""
|
|
184
184
|
|
|
185
|
-
ADD = "
|
|
185
|
+
ADD = "primary"
|
|
186
186
|
CANCEL = "default"
|
|
187
187
|
CLONE = "success"
|
|
188
188
|
CONFIGURE = "default"
|
|
189
189
|
CONNECT = "success"
|
|
190
190
|
DEFAULT = "default"
|
|
191
191
|
DELETE = "danger"
|
|
192
|
-
DISCONNECT = "
|
|
192
|
+
DISCONNECT = "danger"
|
|
193
193
|
EDIT = "warning"
|
|
194
194
|
EXPORT = "success"
|
|
195
195
|
IMPORT = "primary"
|
nautobot/core/cli/__init__.py
CHANGED
|
@@ -13,6 +13,7 @@ from django.core.management import CommandError, CommandParser, execute_from_com
|
|
|
13
13
|
from django.core.management.utils import get_random_secret_key
|
|
14
14
|
from jinja2 import BaseLoader, Environment
|
|
15
15
|
|
|
16
|
+
from nautobot.core.events import load_event_brokers
|
|
16
17
|
from nautobot.core.settings_funcs import is_truthy
|
|
17
18
|
from nautobot.extras.plugins.utils import load_plugins
|
|
18
19
|
|
|
@@ -44,6 +45,7 @@ def _preprocess_settings(settings, config_path):
|
|
|
44
45
|
- Set up 'job_logs' database mirror
|
|
45
46
|
- Handle our custom `STORAGE_BACKEND` setting.
|
|
46
47
|
- Load plugins based on settings.PLUGINS (potentially affecting INSTALLED_APPS, MIDDLEWARE, and CONSTANCE_CONFIG)
|
|
48
|
+
- Load event brokers based on settings.EVENT_BROKERS
|
|
47
49
|
"""
|
|
48
50
|
settings.SETTINGS_PATH = config_path
|
|
49
51
|
|
|
@@ -124,6 +126,12 @@ def _preprocess_settings(settings, config_path):
|
|
|
124
126
|
# passed in.
|
|
125
127
|
load_plugins(settings)
|
|
126
128
|
|
|
129
|
+
#
|
|
130
|
+
# Event Broker
|
|
131
|
+
#
|
|
132
|
+
|
|
133
|
+
load_event_brokers(settings.EVENT_BROKERS)
|
|
134
|
+
|
|
127
135
|
|
|
128
136
|
def load_settings(config_path):
|
|
129
137
|
"""Load nautobot_config.py or its equivalent into memory as a `nautobot_config` pseudo-module."""
|
nautobot/core/constants.py
CHANGED
|
@@ -110,6 +110,10 @@ CONFIG_SETTING_SEPARATOR = ","
|
|
|
110
110
|
|
|
111
111
|
CHARFIELD_MAX_LENGTH = 255
|
|
112
112
|
|
|
113
|
+
# Default values for pagination settings.
|
|
114
|
+
MAX_PAGE_SIZE_DEFAULT = 1000
|
|
115
|
+
PAGINATE_COUNT_DEFAULT = 50
|
|
116
|
+
|
|
113
117
|
# Models excluded from the global search list
|
|
114
118
|
GLOBAL_SEARCH_EXCLUDE_LIST = [
|
|
115
119
|
"anotherexamplemodel",
|
|
@@ -146,12 +150,15 @@ GLOBAL_SEARCH_EXCLUDE_LIST = [
|
|
|
146
150
|
"interfaceredundancygroup",
|
|
147
151
|
"interfaceredundancygroupassociation",
|
|
148
152
|
"interfacetemplate",
|
|
153
|
+
"interfacevdcassignment",
|
|
149
154
|
"inventoryitem",
|
|
150
155
|
"ipaddresstointerface",
|
|
151
156
|
"job",
|
|
152
157
|
"jobbutton",
|
|
153
158
|
"jobhook",
|
|
154
159
|
"joblogentry",
|
|
160
|
+
"jobqueue",
|
|
161
|
+
"jobqueueassignment",
|
|
155
162
|
"jobresult",
|
|
156
163
|
"locationtype",
|
|
157
164
|
"manufacturer",
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""Module providing for the publication of event notifications via mechanisms such as Redis, Kafka, syslog, etc."""
|
|
2
|
+
|
|
3
|
+
import fnmatch
|
|
4
|
+
import json
|
|
5
|
+
import logging
|
|
6
|
+
|
|
7
|
+
from django.utils.module_loading import import_string
|
|
8
|
+
|
|
9
|
+
from nautobot.core.celery import NautobotKombuJSONEncoder
|
|
10
|
+
from nautobot.core.events.exceptions import EventBrokerImproperlyConfigured, EventBrokerNotFound
|
|
11
|
+
|
|
12
|
+
from .base import EventBroker
|
|
13
|
+
from .redis_broker import RedisEventBroker
|
|
14
|
+
from .syslog_broker import SyslogEventBroker
|
|
15
|
+
|
|
16
|
+
_EVENT_BROKERS = []
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def load_event_brokers(event_broker_configs):
|
|
23
|
+
"""Process plugins and log errors if they can't be loaded."""
|
|
24
|
+
for broker_name, broker in event_broker_configs.items():
|
|
25
|
+
options = broker.get("OPTIONS", {})
|
|
26
|
+
topics = broker.get("TOPICS", {})
|
|
27
|
+
if not isinstance(topics, dict):
|
|
28
|
+
raise EventBrokerImproperlyConfigured(
|
|
29
|
+
f"{broker_name} Malformed Event Broker Settings: Expected `TOPICS` to be a 'dict', instead a '{type(topics).__name__}' was provided"
|
|
30
|
+
)
|
|
31
|
+
include_topics = topics.get("INCLUDE")
|
|
32
|
+
if include_topics and not isinstance(include_topics, (list, tuple)):
|
|
33
|
+
raise EventBrokerImproperlyConfigured(
|
|
34
|
+
f"{broker_name} Malformed Event Broker Settings: Expected `INCLUDE` to be a 'list' or 'tuple', instead a '{type(include_topics).__name__}' was provided"
|
|
35
|
+
)
|
|
36
|
+
exclude_topics = topics.get("EXCLUDE", [])
|
|
37
|
+
if exclude_topics and not isinstance(exclude_topics, (list, tuple)):
|
|
38
|
+
raise EventBrokerImproperlyConfigured(
|
|
39
|
+
f"{broker_name} Malformed Event Broker Settings: Expected `EXCLUDE` to be a 'list' or 'tuple', instead a '{type(exclude_topics).__name__}' was provided"
|
|
40
|
+
)
|
|
41
|
+
options.update({"include_topics": include_topics, "exclude_topics": exclude_topics})
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
event_broker_class = import_string(broker["CLASS"])
|
|
45
|
+
if not issubclass(event_broker_class, EventBroker):
|
|
46
|
+
raise EventBrokerImproperlyConfigured(
|
|
47
|
+
f"{broker_name} Malformed Event Broker Settings: Broker provided is not an EventBroker"
|
|
48
|
+
)
|
|
49
|
+
event_broker = event_broker_class(**options)
|
|
50
|
+
register_event_broker(event_broker)
|
|
51
|
+
except ImportError as err:
|
|
52
|
+
raise EventBrokerNotFound(f"Unable to import Event Broker {broker_name}.") from err
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def register_event_broker(event_broker):
|
|
56
|
+
"""
|
|
57
|
+
Register an `EventBroker` instance for use by Nautobot.
|
|
58
|
+
|
|
59
|
+
The `publish_event()` API will publish events to each registered broker.
|
|
60
|
+
The expectation/intent here, at least initially, is that a given deployment will instantiate zero or more
|
|
61
|
+
EventBrokers, then call `register_event_broker()` for each one, as part of Nautobot initial startup.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
event_broker (EventBroker): The initialized/configured EventBroker instance to register.
|
|
65
|
+
"""
|
|
66
|
+
if event_broker not in _EVENT_BROKERS:
|
|
67
|
+
_EVENT_BROKERS.append(event_broker)
|
|
68
|
+
logger.debug("Registered %s as an event broker", event_broker)
|
|
69
|
+
else:
|
|
70
|
+
logger.warning("Tried to register event broker %s but it was already registered", event_broker)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def deregister_event_broker(event_broker):
|
|
74
|
+
"""
|
|
75
|
+
Deregister a previously registered `EventBroker` instance so that it no longer receives published events.
|
|
76
|
+
"""
|
|
77
|
+
try:
|
|
78
|
+
_EVENT_BROKERS.remove(event_broker)
|
|
79
|
+
logger.debug("Deregistered event broker %s", event_broker)
|
|
80
|
+
except ValueError:
|
|
81
|
+
logger.warning("Tried to deregister event broker %s but it wasn't previously registered", event_broker)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def is_topic_match(topic, patterns):
|
|
85
|
+
return any(fnmatch.fnmatch(topic, pattern) for pattern in patterns)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def publish_event(*, topic, payload):
|
|
89
|
+
"""Publish the given event payload to the given topic via all registered `EventBroker` instances.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
topic (str): Topic identifier.
|
|
93
|
+
Convention is to use snake_case and use periods to delineate related groups of topics,
|
|
94
|
+
similar to Python logger naming. For example, you might use `nautobot.create.dcim.device`,
|
|
95
|
+
`nautobot.update.dcim.device`, `nautobot.delete.dcim.device`, `nautobot.create.dcim.interface`,
|
|
96
|
+
`nautobot.create.ipam.ipaddress`, etc.
|
|
97
|
+
payload (dict): JSON-serializable structured data to publish.
|
|
98
|
+
While not all EventBrokers may actually use JSON as their data format, it makes for a reasonable
|
|
99
|
+
lowest common denominator for serializability.
|
|
100
|
+
"""
|
|
101
|
+
for event_broker in _EVENT_BROKERS:
|
|
102
|
+
exclude_topics = event_broker.exclude_topics
|
|
103
|
+
include_topics = event_broker.include_topics
|
|
104
|
+
if is_topic_match(topic, include_topics) and not is_topic_match(topic, exclude_topics):
|
|
105
|
+
serialized_payload = json.dumps(payload, cls=NautobotKombuJSONEncoder)
|
|
106
|
+
event_broker.publish(topic=topic, payload=serialized_payload)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
__all__ = (
|
|
110
|
+
"EventBroker",
|
|
111
|
+
"RedisEventBroker",
|
|
112
|
+
"SyslogEventBroker",
|
|
113
|
+
"deregister_event_broker",
|
|
114
|
+
"publish_event",
|
|
115
|
+
"register_event_broker",
|
|
116
|
+
)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Base classes for Nautobot event notification framework."""
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class EventBroker(ABC):
|
|
7
|
+
"""Abstract base class for concrete implementations of event brokers such as syslog, Redis, Kafka, etc."""
|
|
8
|
+
|
|
9
|
+
def __init__(self, *args, include_topics=None, exclude_topics=None, **kwargs) -> None:
|
|
10
|
+
self.include_topics = include_topics or ["*"]
|
|
11
|
+
self.exclude_topics = exclude_topics or []
|
|
12
|
+
super().__init__(*args, **kwargs)
|
|
13
|
+
|
|
14
|
+
@abstractmethod
|
|
15
|
+
def publish(self, *, topic, payload):
|
|
16
|
+
"""
|
|
17
|
+
Possibly publish the given data `payload` to the given event `topic`.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
topic (str): Topic identifier.
|
|
21
|
+
Convention is to use snake_case and use periods to delineate related groups of topics,
|
|
22
|
+
similar to Python logger naming. For example, you might receive topics such as `create.dcim.device`,
|
|
23
|
+
`update.dcim.device`, `delete.dcim.device`, `create.dcim.interface`, `create.ipam.ipaddress`, etc.
|
|
24
|
+
payload (dict): JSON-serializable structured data to publish.
|
|
25
|
+
While not all EventBrokers may actually use JSON as their data format, it makes for a reasonable
|
|
26
|
+
lowest common denominator for serializability.
|
|
27
|
+
"""
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
class EventBrokerError(Exception):
|
|
2
|
+
"""Base exception for all event-broker-related errors."""
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class EventBrokerNotFound(EventBrokerError):
|
|
6
|
+
"""Raised when a specified event broker module cannot be found."""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class EventBrokerImproperlyConfigured(EventBrokerError):
|
|
10
|
+
"""Raised when a event is not properly configured."""
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Simple EventBroker for publishing events to Redis.
|
|
2
|
+
|
|
3
|
+
To verify that an instance of this broker is working, you can do the following in `nautobot-server nbshell`:
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
import json
|
|
7
|
+
|
|
8
|
+
import redis
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
connection = redis.StrictRedis(host="redis", port=6379, db=2, password="...", charset="utf-8", decode_responses=True)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def listen():
|
|
15
|
+
sub = connection.pubsub()
|
|
16
|
+
sub.psubscribe("nautobot.*")
|
|
17
|
+
for message in sub.listen():
|
|
18
|
+
if message["type"] == "pmessage":
|
|
19
|
+
print(f"Got a pmessage on channel {message['channel']}")
|
|
20
|
+
print(json.dumps(json.loads(message["data"]), indent=2))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
listen()
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Then perform any action that triggers an event, such as creating or updating a record through the Nautobot UI.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
import redis
|
|
30
|
+
|
|
31
|
+
from .base import EventBroker
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class RedisEventBroker(EventBroker):
|
|
35
|
+
"""EventBroker for publishing events to Redis."""
|
|
36
|
+
|
|
37
|
+
def __init__(self, *args, url, **kwargs):
|
|
38
|
+
"""Initialize and configure a RedisEventBroker.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
url (str): The Redis URL to connect to.
|
|
42
|
+
"""
|
|
43
|
+
self.url = url
|
|
44
|
+
self.connection = redis.StrictRedis.from_url(self.url)
|
|
45
|
+
super().__init__(*args, **kwargs)
|
|
46
|
+
|
|
47
|
+
def publish(self, *, topic, payload):
|
|
48
|
+
self.connection.publish(topic, payload)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Simple EventBroker that just emits syslogs."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
from .base import EventBroker
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SyslogEventBroker(EventBroker):
|
|
10
|
+
def __init__(self, *args, level=logging.INFO, **kwargs):
|
|
11
|
+
"""Initialize a SyslogEventBroker that emits logs at the given level."""
|
|
12
|
+
super().__init__(*args, **kwargs)
|
|
13
|
+
self.level = level
|
|
14
|
+
|
|
15
|
+
def publish(self, *, topic, payload):
|
|
16
|
+
logger = logging.getLogger(f"nautobot.events.{topic}")
|
|
17
|
+
# Add an indent of 4 to payload
|
|
18
|
+
payload = json.dumps(json.loads(payload), indent=4)
|
|
19
|
+
logger.log(self.level, "%s", payload)
|
nautobot/core/exceptions.py
CHANGED
nautobot/core/filters.py
CHANGED
|
@@ -668,7 +668,7 @@ class BaseFilterSet(django_filters.FilterSet):
|
|
|
668
668
|
the form `<field_name>__<lookup_expr>`
|
|
669
669
|
"""
|
|
670
670
|
magic_filters = {}
|
|
671
|
-
if filter_field.method is not None or filter_field.lookup_expr not in ["exact", "in"]:
|
|
671
|
+
if filter_field.method is not None or filter_field.lookup_expr not in ["exact", "in", "iexact"]:
|
|
672
672
|
return magic_filters
|
|
673
673
|
|
|
674
674
|
# Choose the lookup expression map based on the filter type
|
|
@@ -679,7 +679,7 @@ class BaseFilterSet(django_filters.FilterSet):
|
|
|
679
679
|
|
|
680
680
|
# Get properties of the existing filter for later use
|
|
681
681
|
field_name = filter_field.field_name
|
|
682
|
-
field = get_model_field(cls._meta.model, field_name)
|
|
682
|
+
field = get_model_field(cls._meta.model, field_name) # pylint: disable=no-member
|
|
683
683
|
|
|
684
684
|
# If there isn't a model field, return.
|
|
685
685
|
if field is None:
|
|
@@ -696,7 +696,7 @@ class BaseFilterSet(django_filters.FilterSet):
|
|
|
696
696
|
new_filter_name = f"{filter_name}__{lookup_name}"
|
|
697
697
|
|
|
698
698
|
try:
|
|
699
|
-
if filter_name in cls.declared_filters and lookup_expr not in {"isnull"}:
|
|
699
|
+
if filter_name in cls.declared_filters and lookup_expr not in {"isnull"}: # pylint: disable=no-member
|
|
700
700
|
# The filter field has been explicitly defined on the filterset class so we must manually
|
|
701
701
|
# create the new filter with the same type because there is no guarantee the defined type
|
|
702
702
|
# is the same as the default type for the field. This does not apply if the filter
|
|
@@ -727,7 +727,10 @@ class BaseFilterSet(django_filters.FilterSet):
|
|
|
727
727
|
# If the base filter_field has a custom label, django_filters won't adjust it for the new_filter lookup,
|
|
728
728
|
# so we have to do it.
|
|
729
729
|
if filter_field.label and filter_field.label != label_for_filter(
|
|
730
|
-
cls.
|
|
730
|
+
cls._meta.model, # pylint: disable=no-member
|
|
731
|
+
filter_field.field_name,
|
|
732
|
+
filter_field.lookup_expr,
|
|
733
|
+
filter_field.exclude,
|
|
731
734
|
):
|
|
732
735
|
# Lightly adjusted from label_for_filter() implementation:
|
|
733
736
|
verbose_expression = ["exclude", filter_field.label] if new_filter.exclude else [filter_field.label]
|
|
@@ -750,22 +753,22 @@ class BaseFilterSet(django_filters.FilterSet):
|
|
|
750
753
|
if not isinstance(new_filter_field, django_filters.Filter):
|
|
751
754
|
raise TypeError(f"Tried to add filter ({new_filter_name}) which is not an instance of Django Filter")
|
|
752
755
|
|
|
753
|
-
if new_filter_name in cls.base_filters:
|
|
756
|
+
if new_filter_name in cls.base_filters: # pylint: disable=no-member
|
|
754
757
|
raise AttributeError(
|
|
755
758
|
f"There was a conflict with filter `{new_filter_name}`, the custom filter was ignored."
|
|
756
759
|
)
|
|
757
760
|
|
|
758
|
-
cls.base_filters[new_filter_name] = new_filter_field
|
|
761
|
+
cls.base_filters[new_filter_name] = new_filter_field # pylint: disable=no-member
|
|
759
762
|
# django-filters has no concept of "abstract" filtersets, so we have to fake it
|
|
760
|
-
if cls._meta.model is not None:
|
|
761
|
-
cls.base_filters.update(
|
|
763
|
+
if cls._meta.model is not None: # pylint: disable=no-member
|
|
764
|
+
cls.base_filters.update( # pylint: disable=no-member
|
|
762
765
|
cls._generate_lookup_expression_filters(filter_name=new_filter_name, filter_field=new_filter_field)
|
|
763
766
|
)
|
|
764
767
|
|
|
765
768
|
@classmethod
|
|
766
769
|
def get_fields(cls):
|
|
767
770
|
fields = super().get_fields()
|
|
768
|
-
if "id" not in fields and (cls._meta.exclude is None or "id" not in cls._meta.exclude):
|
|
771
|
+
if "id" not in fields and (cls._meta.exclude is None or "id" not in cls._meta.exclude): # pylint: disable=no-member
|
|
769
772
|
# Add "id" as the first key in the `fields` dict
|
|
770
773
|
fields = {"id": [django_filters.conf.settings.DEFAULT_LOOKUP_EXPR], **fields}
|
|
771
774
|
return fields
|
|
@@ -782,7 +785,7 @@ class BaseFilterSet(django_filters.FilterSet):
|
|
|
782
785
|
if filter_name.startswith("_"):
|
|
783
786
|
del filters[filter_name]
|
|
784
787
|
|
|
785
|
-
if getattr(cls._meta.model, "is_contact_associable_model", False):
|
|
788
|
+
if getattr(cls._meta.model, "is_contact_associable_model", False): # pylint: disable=no-member
|
|
786
789
|
# Add "contacts" and "teams" filters
|
|
787
790
|
from nautobot.extras.models import Contact, Team
|
|
788
791
|
|
|
@@ -802,13 +805,13 @@ class BaseFilterSet(django_filters.FilterSet):
|
|
|
802
805
|
label="Teams (name or ID)",
|
|
803
806
|
)
|
|
804
807
|
|
|
805
|
-
if "dynamic_groups" not in filters and getattr(cls._meta.model, "is_dynamic_group_associable_model", False):
|
|
806
|
-
if not hasattr(cls._meta.model, "static_group_association_set"):
|
|
808
|
+
if "dynamic_groups" not in filters and getattr(cls._meta.model, "is_dynamic_group_associable_model", False): # pylint: disable=no-member
|
|
809
|
+
if not hasattr(cls._meta.model, "static_group_association_set"): # pylint: disable=no-member
|
|
807
810
|
logger.warning(
|
|
808
811
|
"Model %s has 'is_dynamic_group_associable_model = True' but lacks "
|
|
809
812
|
"a 'static_group_association_set' attribute. Perhaps this is due to it inheriting from "
|
|
810
813
|
"the deprecated DynamicGroupMixin class instead of the preferred DynamicGroupsModelMixin?",
|
|
811
|
-
cls._meta.model,
|
|
814
|
+
cls._meta.model, # pylint: disable=no-member
|
|
812
815
|
)
|
|
813
816
|
else:
|
|
814
817
|
# Add "dynamic_groups" field as the last key
|
|
@@ -818,14 +821,14 @@ class BaseFilterSet(django_filters.FilterSet):
|
|
|
818
821
|
queryset=DynamicGroup.objects.all(),
|
|
819
822
|
field_name="static_group_association_set__dynamic_group",
|
|
820
823
|
to_field_name="name",
|
|
821
|
-
query_params={"content_type": cls._meta.model._meta.label_lower},
|
|
824
|
+
query_params={"content_type": cls._meta.model._meta.label_lower}, # pylint: disable=no-member
|
|
822
825
|
label="Dynamic groups (name or ID)",
|
|
823
826
|
)
|
|
824
827
|
|
|
825
828
|
# django-filters has no concept of "abstract" filtersets, so we have to fake it
|
|
826
|
-
if cls._meta.model is not None:
|
|
829
|
+
if cls._meta.model is not None: # pylint: disable=no-member
|
|
827
830
|
if "tags" in filters and isinstance(filters["tags"], TagFilter):
|
|
828
|
-
filters["tags"].extra["query_params"] = {"content_types": [cls._meta.model._meta.label_lower]}
|
|
831
|
+
filters["tags"].extra["query_params"] = {"content_types": [cls._meta.model._meta.label_lower]} # pylint: disable=no-member
|
|
829
832
|
|
|
830
833
|
new_filters = {}
|
|
831
834
|
for existing_filter_name, existing_filter in filters.items():
|
nautobot/core/forms/__init__.py
CHANGED
|
@@ -76,24 +76,21 @@ from nautobot.core.forms.widgets import (
|
|
|
76
76
|
)
|
|
77
77
|
|
|
78
78
|
__all__ = (
|
|
79
|
-
"add_blank_choice",
|
|
80
|
-
"add_field_to_filter_form_class",
|
|
81
|
-
"AddressFieldMixin",
|
|
82
79
|
"ALPHANUMERIC_EXPANSION_PATTERN",
|
|
80
|
+
"BOOLEAN_CHOICES",
|
|
81
|
+
"BOOLEAN_WITH_BLANK_CHOICES",
|
|
82
|
+
"IP4_EXPANSION_PATTERN",
|
|
83
|
+
"IP6_EXPANSION_PATTERN",
|
|
84
|
+
"NUMERIC_EXPANSION_PATTERN",
|
|
83
85
|
"APISelect",
|
|
84
86
|
"APISelectMultiple",
|
|
87
|
+
"AddressFieldMixin",
|
|
85
88
|
"AutoPositionField",
|
|
86
89
|
"AutoPositionPatternField",
|
|
87
|
-
"BOOLEAN_CHOICES",
|
|
88
|
-
"BOOLEAN_WITH_BLANK_CHOICES",
|
|
89
90
|
"BootstrapMixin",
|
|
90
91
|
"BulkEditForm",
|
|
91
92
|
"BulkEditNullBooleanSelect",
|
|
92
93
|
"BulkRenameForm",
|
|
93
|
-
"ColorSelect",
|
|
94
|
-
"CommentField",
|
|
95
|
-
"ConfirmationForm",
|
|
96
|
-
"ContentTypeSelect",
|
|
97
94
|
"CSVChoiceField",
|
|
98
95
|
"CSVContentTypeField",
|
|
99
96
|
"CSVDataField",
|
|
@@ -102,34 +99,29 @@ __all__ = (
|
|
|
102
99
|
"CSVModelForm",
|
|
103
100
|
"CSVMultipleChoiceField",
|
|
104
101
|
"CSVMultipleContentTypeField",
|
|
102
|
+
"ColorSelect",
|
|
103
|
+
"CommentField",
|
|
104
|
+
"ConfirmationForm",
|
|
105
|
+
"ContentTypeSelect",
|
|
105
106
|
"DatePicker",
|
|
106
107
|
"DateTimePicker",
|
|
107
108
|
"DynamicFilterForm",
|
|
108
109
|
"DynamicModelChoiceField",
|
|
109
110
|
"DynamicModelMultipleChoiceField",
|
|
110
|
-
"expand_alphanumeric_pattern",
|
|
111
|
-
"expand_ipaddress_pattern",
|
|
112
111
|
"ExpandableIPAddressField",
|
|
113
112
|
"ExpandableNameField",
|
|
114
|
-
"form_from_model",
|
|
115
113
|
"ImportForm",
|
|
116
|
-
"IP4_EXPANSION_PATTERN",
|
|
117
|
-
"IP6_EXPANSION_PATTERN",
|
|
118
114
|
"JSONArrayFormField",
|
|
119
115
|
"JSONField",
|
|
120
116
|
"LaxURLField",
|
|
121
117
|
"MACAddressField",
|
|
122
118
|
"MultiMatchModelMultipleChoiceField",
|
|
123
|
-
"MultipleContentTypeField",
|
|
124
119
|
"MultiValueCharField",
|
|
125
120
|
"MultiValueCharInput",
|
|
121
|
+
"MultipleContentTypeField",
|
|
126
122
|
"NullableDateField",
|
|
127
|
-
"NUMERIC_EXPANSION_PATTERN",
|
|
128
123
|
"NumericArrayField",
|
|
129
|
-
"parse_alphanumeric_range",
|
|
130
|
-
"parse_numeric_range",
|
|
131
124
|
"PrefixFieldMixin",
|
|
132
|
-
"restrict_form_fields",
|
|
133
125
|
"ReturnURLForm",
|
|
134
126
|
"SearchForm",
|
|
135
127
|
"SelectWithDisabled",
|
|
@@ -142,4 +134,12 @@ __all__ = (
|
|
|
142
134
|
"TableConfigForm",
|
|
143
135
|
"TagFilterField",
|
|
144
136
|
"TimePicker",
|
|
137
|
+
"add_blank_choice",
|
|
138
|
+
"add_field_to_filter_form_class",
|
|
139
|
+
"expand_alphanumeric_pattern",
|
|
140
|
+
"expand_ipaddress_pattern",
|
|
141
|
+
"form_from_model",
|
|
142
|
+
"parse_alphanumeric_range",
|
|
143
|
+
"parse_numeric_range",
|
|
144
|
+
"restrict_form_fields",
|
|
145
145
|
)
|