nautobot 2.4.0__py3-none-any.whl → 2.4.0b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of nautobot might be problematic. Click here for more details.
- nautobot/apps/__init__.py +1 -1
- nautobot/apps/api.py +8 -8
- nautobot/apps/change_logging.py +2 -2
- nautobot/apps/choices.py +4 -4
- nautobot/apps/events.py +3 -3
- nautobot/apps/factory.py +2 -2
- nautobot/apps/filters.py +1 -1
- nautobot/apps/forms.py +20 -20
- nautobot/apps/graphql.py +2 -2
- nautobot/apps/jobs.py +8 -8
- nautobot/apps/models.py +19 -19
- nautobot/apps/tables.py +1 -1
- nautobot/apps/testing.py +10 -10
- nautobot/apps/ui.py +2 -2
- nautobot/apps/utils.py +7 -7
- nautobot/apps/views.py +7 -7
- nautobot/circuits/api/serializers.py +0 -1
- nautobot/circuits/api/views.py +8 -4
- nautobot/circuits/tables.py +1 -2
- nautobot/circuits/templates/circuits/circuit_create.html +7 -1
- nautobot/circuits/views.py +3 -3
- nautobot/cloud/api/views.py +10 -6
- nautobot/cloud/models.py +1 -1
- nautobot/cloud/views.py +16 -0
- nautobot/core/api/fields.py +5 -5
- nautobot/core/api/filter_backends.py +9 -3
- nautobot/core/api/schema.py +2 -13
- nautobot/core/api/serializers.py +34 -40
- nautobot/core/api/views.py +4 -56
- nautobot/core/celery/log.py +4 -4
- nautobot/core/celery/schedulers.py +1 -1
- nautobot/core/choices.py +2 -2
- nautobot/core/events/__init__.py +3 -3
- nautobot/core/filters.py +16 -21
- nautobot/core/fixtures/user-data.json +59 -0
- nautobot/core/forms/__init__.py +19 -19
- nautobot/core/forms/fields.py +11 -14
- nautobot/core/forms/forms.py +2 -33
- nautobot/core/graphql/types.py +1 -1
- nautobot/core/jobs/__init__.py +7 -28
- nautobot/core/jobs/cleanup.py +12 -48
- nautobot/core/jobs/groups.py +1 -1
- nautobot/core/management/commands/validate_models.py +1 -1
- nautobot/core/models/__init__.py +1 -1
- nautobot/core/models/query_functions.py +2 -2
- nautobot/core/models/tree_queries.py +3 -6
- nautobot/core/settings.py +2 -29
- nautobot/core/settings.yaml +0 -21
- nautobot/core/tables.py +60 -74
- nautobot/core/templates/inc/media.html +0 -3
- nautobot/core/templates/inc/nav_menu.html +0 -1
- nautobot/core/templates/nautobot_config.py.j2 +0 -13
- nautobot/core/templates/search.html +0 -7
- nautobot/core/templates/utilities/render_jinja2.html +1 -1
- nautobot/core/templates/utilities/templatetags/tag.html +1 -1
- nautobot/core/templates/utilities/theme_preview.html +0 -7
- nautobot/core/templatetags/helpers.py +2 -11
- nautobot/core/testing/__init__.py +8 -8
- nautobot/core/testing/api.py +15 -170
- nautobot/core/testing/filters.py +2 -25
- nautobot/core/testing/forms.py +0 -2
- nautobot/core/testing/mixins.py +2 -7
- nautobot/core/testing/views.py +29 -44
- nautobot/core/tests/integration/test_app_home.py +1 -0
- nautobot/core/tests/integration/test_app_navbar.py +1 -0
- nautobot/core/tests/integration/test_filters.py +2 -0
- nautobot/core/tests/integration/test_home.py +1 -0
- nautobot/core/tests/integration/test_navbar.py +1 -0
- nautobot/core/tests/integration/test_view_authentication.py +0 -1
- nautobot/core/tests/runner.py +1 -1
- nautobot/core/tests/test_api.py +1 -98
- nautobot/core/tests/test_csv.py +3 -25
- nautobot/core/tests/test_forms.py +0 -1
- nautobot/core/tests/test_jobs.py +1 -303
- nautobot/core/tests/test_settings_schema.py +0 -7
- nautobot/core/tests/test_tables.py +0 -100
- nautobot/core/tests/test_utils.py +1 -63
- nautobot/core/tests/test_views.py +3 -30
- nautobot/core/ui/nav.py +0 -1
- nautobot/core/ui/object_detail.py +1 -15
- nautobot/core/urls.py +0 -11
- nautobot/core/utils/lookup.py +8 -11
- nautobot/core/utils/requests.py +9 -24
- nautobot/core/views/__init__.py +0 -42
- nautobot/core/views/generic.py +176 -78
- nautobot/core/views/mixins.py +34 -94
- nautobot/core/views/renderers.py +6 -6
- nautobot/dcim/api/serializers.py +62 -54
- nautobot/dcim/api/views.py +113 -47
- nautobot/dcim/filters/__init__.py +2 -31
- nautobot/dcim/forms.py +17 -36
- nautobot/dcim/graphql/types.py +2 -2
- nautobot/dcim/models/__init__.py +1 -1
- nautobot/dcim/models/device_component_templates.py +2 -2
- nautobot/dcim/models/device_components.py +20 -22
- nautobot/dcim/models/devices.py +1 -10
- nautobot/dcim/models/locations.py +3 -3
- nautobot/dcim/models/power.py +5 -6
- nautobot/dcim/models/racks.py +4 -4
- nautobot/dcim/tables/__init__.py +3 -3
- nautobot/dcim/tables/devices.py +5 -7
- nautobot/dcim/tables/devicetypes.py +2 -2
- nautobot/dcim/tables/racks.py +1 -1
- nautobot/dcim/templates/dcim/controller_create.html +7 -1
- nautobot/dcim/templates/dcim/controller_retrieve.html +9 -1
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +0 -2
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +0 -5
- nautobot/dcim/templates/dcim/device.html +9 -1
- nautobot/dcim/templates/dcim/device_edit.html +37 -36
- nautobot/dcim/templates/dcim/location.html +9 -1
- nautobot/dcim/templates/dcim/location_edit.html +7 -1
- nautobot/dcim/templates/dcim/rack.html +9 -1
- nautobot/dcim/templates/dcim/rack_edit.html +7 -1
- nautobot/dcim/templates/dcim/rackreservation.html +9 -1
- nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +9 -1
- nautobot/dcim/templates/dcim/virtualdevicecontext_update.html +7 -1
- nautobot/dcim/tests/test_api.py +3 -16
- nautobot/dcim/tests/test_filters.py +0 -33
- nautobot/dcim/tests/test_forms.py +2 -51
- nautobot/dcim/tests/test_graphql.py +0 -52
- nautobot/dcim/tests/test_models.py +5 -34
- nautobot/dcim/tests/test_views.py +83 -21
- nautobot/dcim/views.py +13 -1
- nautobot/extras/api/customfields.py +2 -2
- nautobot/extras/api/serializers.py +85 -90
- nautobot/extras/api/views.py +27 -22
- nautobot/extras/constants.py +0 -2
- nautobot/extras/filters/__init__.py +6 -8
- nautobot/extras/forms/base.py +2 -2
- nautobot/extras/forms/forms.py +31 -139
- nautobot/extras/forms/mixins.py +5 -13
- nautobot/extras/group_sync.py +3 -3
- nautobot/extras/health_checks.py +2 -1
- nautobot/extras/jobs.py +12 -70
- nautobot/extras/managers.py +1 -3
- nautobot/extras/migrations/0018_joblog_data_migration.py +9 -7
- nautobot/extras/models/__init__.py +1 -1
- nautobot/extras/models/contacts.py +1 -1
- nautobot/extras/models/customfields.py +11 -12
- nautobot/extras/models/groups.py +9 -11
- nautobot/extras/models/jobs.py +4 -23
- nautobot/extras/models/models.py +2 -2
- nautobot/extras/plugins/__init__.py +2 -13
- nautobot/extras/plugins/marketplace_manifest.yml +79 -84
- nautobot/extras/plugins/tables.py +14 -16
- nautobot/extras/plugins/views.py +69 -65
- nautobot/extras/registry.py +1 -1
- nautobot/extras/secrets/__init__.py +2 -2
- nautobot/extras/tables.py +5 -7
- nautobot/extras/templates/extras/dynamicgroup.html +9 -1
- nautobot/extras/templates/extras/job_detail.html +0 -16
- nautobot/extras/templates/extras/job_edit.html +0 -1
- nautobot/extras/templates/extras/jobqueue_retrieve.html +9 -1
- nautobot/extras/templates/extras/marketplace.html +11 -29
- nautobot/extras/templates/extras/plugin_detail.html +15 -32
- nautobot/extras/templates/extras/plugins_tiles.html +10 -21
- nautobot/extras/test_jobs/api_test_job.py +1 -1
- nautobot/extras/test_jobs/atomic_transaction.py +2 -2
- nautobot/extras/test_jobs/dry_run.py +1 -1
- nautobot/extras/test_jobs/fail.py +5 -5
- nautobot/extras/test_jobs/file_output.py +1 -1
- nautobot/extras/test_jobs/file_upload_fail.py +1 -1
- nautobot/extras/test_jobs/file_upload_pass.py +1 -1
- nautobot/extras/test_jobs/ipaddress_vars.py +1 -3
- nautobot/extras/test_jobs/jobs_module/jobs_submodule/jobs.py +1 -1
- nautobot/extras/test_jobs/location_with_custom_field.py +1 -1
- nautobot/extras/test_jobs/log_redaction.py +1 -1
- nautobot/extras/test_jobs/log_skip_db_logging.py +1 -1
- nautobot/extras/test_jobs/modify_db.py +1 -1
- nautobot/extras/test_jobs/object_var_optional.py +1 -1
- nautobot/extras/test_jobs/object_var_required.py +1 -1
- nautobot/extras/test_jobs/object_vars.py +1 -1
- nautobot/extras/test_jobs/pass.py +3 -3
- nautobot/extras/test_jobs/profiling.py +1 -1
- nautobot/extras/test_jobs/relative_import.py +3 -3
- nautobot/extras/test_jobs/soft_time_limit_greater_than_time_limit.py +1 -1
- nautobot/extras/test_jobs/task_queues.py +1 -1
- nautobot/extras/tests/integration/test_plugin_banner.py +2 -0
- nautobot/extras/tests/test_api.py +13 -13
- nautobot/extras/tests/test_customfields.py +1 -1
- nautobot/extras/tests/test_datasources.py +1 -2
- nautobot/extras/tests/test_dynamicgroups.py +1 -1
- nautobot/extras/tests/test_filters.py +6 -6
- nautobot/extras/tests/test_forms.py +1 -20
- nautobot/extras/tests/test_jobs.py +19 -160
- nautobot/extras/tests/test_models.py +10 -10
- nautobot/extras/tests/test_plugins.py +9 -62
- nautobot/extras/tests/test_relationships.py +9 -120
- nautobot/extras/tests/test_views.py +191 -52
- nautobot/extras/utils.py +2 -3
- nautobot/extras/views.py +98 -30
- nautobot/ipam/api/fields.py +3 -3
- nautobot/ipam/api/serializers.py +33 -41
- nautobot/ipam/api/views.py +117 -68
- nautobot/ipam/factory.py +1 -1
- nautobot/ipam/filters.py +2 -3
- nautobot/ipam/lookups.py +62 -101
- nautobot/ipam/models.py +16 -66
- nautobot/ipam/querysets.py +2 -2
- nautobot/ipam/tables.py +7 -23
- nautobot/ipam/templates/ipam/ipaddress.html +9 -1
- nautobot/ipam/templates/ipam/ipaddress_bulk_add.html +7 -1
- nautobot/ipam/templates/ipam/ipaddress_edit.html +7 -1
- nautobot/ipam/templates/ipam/prefix.html +9 -1
- nautobot/ipam/templates/ipam/prefix_edit.html +7 -1
- nautobot/ipam/templates/ipam/vlan.html +9 -1
- nautobot/ipam/templates/ipam/vlan_edit.html +7 -1
- nautobot/ipam/templates/ipam/vrf_edit.html +7 -1
- nautobot/ipam/tests/test_api.py +3 -416
- nautobot/ipam/tests/test_forms.py +47 -49
- nautobot/ipam/tests/test_migrations.py +30 -30
- nautobot/ipam/tests/test_models.py +34 -95
- nautobot/ipam/tests/test_querysets.py +1 -63
- nautobot/ipam/tests/test_views.py +0 -3
- nautobot/ipam/utils/__init__.py +6 -36
- nautobot/ipam/views.py +87 -61
- 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 +2 -40
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css.map +1 -1
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css +1 -1
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css.map +1 -1
- nautobot/project-static/docs/404.html +4 -46
- nautobot/project-static/docs/apps/index.html +4 -46
- nautobot/project-static/docs/apps/nautobot-apps.html +6 -47
- nautobot/project-static/docs/assets/_mkdocstrings.css +1 -25
- nautobot/project-static/docs/assets/javascripts/{bundle.88dd0f4e.min.js → bundle.83f73b43.min.js} +2 -2
- nautobot/project-static/docs/assets/javascripts/{bundle.88dd0f4e.min.js.map → bundle.83f73b43.min.js.map} +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +10 -62
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +7 -59
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +122 -374
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +18 -90
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +21 -95
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +6 -53
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +5 -52
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +17 -79
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +28 -102
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +21 -108
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +38 -131
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +65 -239
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +165 -581
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +36 -109
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +167 -453
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +211 -493
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +8 -60
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +15 -71
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +55 -407
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +205 -585
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +412 -858
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +7 -59
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +186 -448
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +147 -365
- nautobot/project-static/docs/development/apps/api/configuration-view.html +4 -46
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +4 -46
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +4 -46
- nautobot/project-static/docs/development/apps/api/models/global-search.html +4 -46
- nautobot/project-static/docs/development/apps/api/models/graphql.html +4 -46
- nautobot/project-static/docs/development/apps/api/models/index.html +4 -46
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +4 -46
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +4 -46
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +4 -46
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +4 -46
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +4 -46
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +4 -46
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +4 -46
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +4 -46
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +4 -46
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +7 -68
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +4 -46
- nautobot/project-static/docs/development/apps/api/prometheus.html +4 -46
- nautobot/project-static/docs/development/apps/api/setup.html +4 -46
- nautobot/project-static/docs/development/apps/api/testing.html +4 -46
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +4 -46
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +4 -46
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +4 -46
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +4 -46
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +4 -46
- nautobot/project-static/docs/development/apps/api/views/base-template.html +4 -46
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +4 -46
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +4 -46
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +4 -46
- nautobot/project-static/docs/development/apps/api/views/index.html +4 -46
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +4 -46
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +4 -46
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +4 -46
- nautobot/project-static/docs/development/apps/api/views/notes.html +4 -46
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +6 -52
- nautobot/project-static/docs/development/apps/api/views/urls.html +4 -46
- nautobot/project-static/docs/development/apps/index.html +4 -46
- nautobot/project-static/docs/development/apps/migration/code-updates.html +4 -46
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +4 -46
- nautobot/project-static/docs/development/apps/migration/from-v1.html +4 -46
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +4 -46
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +4 -46
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +4 -46
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +4 -46
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +8 -50
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +4 -46
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +14 -211
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +4 -46
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +4 -46
- nautobot/project-static/docs/development/core/application-registry.html +4 -46
- nautobot/project-static/docs/development/core/best-practices.html +4 -46
- nautobot/project-static/docs/development/core/bootstrap-ui.html +4 -46
- nautobot/project-static/docs/development/core/caching.html +4 -46
- nautobot/project-static/docs/development/core/controllers.html +4 -46
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +74 -73
- nautobot/project-static/docs/development/core/generic-views.html +4 -46
- nautobot/project-static/docs/development/core/getting-started.html +224 -249
- nautobot/project-static/docs/development/core/homepage.html +7 -49
- nautobot/project-static/docs/development/core/index.html +4 -46
- nautobot/project-static/docs/development/core/{minikube-dev-environment-for-k8s-jobs.html → local-k8s.html} +168 -469
- nautobot/project-static/docs/development/core/model-checklist.html +12 -56
- nautobot/project-static/docs/development/core/model-features.html +4 -46
- nautobot/project-static/docs/development/core/natural-keys.html +4 -46
- nautobot/project-static/docs/development/core/navigation-menu.html +4 -46
- nautobot/project-static/docs/development/core/release-checklist.html +7 -49
- nautobot/project-static/docs/development/core/role-internals.html +4 -46
- nautobot/project-static/docs/development/core/settings.html +4 -46
- nautobot/project-static/docs/development/core/style-guide.html +7 -49
- nautobot/project-static/docs/development/core/templates.html +4 -46
- nautobot/project-static/docs/development/core/testing.html +4 -46
- nautobot/project-static/docs/development/core/ui-component-framework.html +273 -369
- nautobot/project-static/docs/development/core/user-preferences.html +4 -46
- nautobot/project-static/docs/development/index.html +4 -46
- nautobot/project-static/docs/development/jobs/index.html +122 -216
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +4 -46
- nautobot/project-static/docs/index.html +23 -54
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +7 -47
- nautobot/project-static/docs/overview/design_philosophy.html +4 -46
- nautobot/project-static/docs/release-notes/index.html +12 -52
- nautobot/project-static/docs/release-notes/version-1.0.html +193 -234
- nautobot/project-static/docs/release-notes/version-1.1.html +190 -231
- nautobot/project-static/docs/release-notes/version-1.2.html +265 -306
- nautobot/project-static/docs/release-notes/version-1.3.html +291 -332
- nautobot/project-static/docs/release-notes/version-1.4.html +377 -417
- nautobot/project-static/docs/release-notes/version-1.5.html +566 -605
- nautobot/project-static/docs/release-notes/version-1.6.html +447 -904
- nautobot/project-static/docs/release-notes/version-2.0.html +489 -528
- nautobot/project-static/docs/release-notes/version-2.1.html +324 -363
- nautobot/project-static/docs/release-notes/version-2.2.html +317 -356
- nautobot/project-static/docs/release-notes/version-2.3.html +352 -997
- nautobot/project-static/docs/release-notes/version-2.4.html +101 -417
- nautobot/project-static/docs/requirements.txt +2 -2
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +287 -295
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +4 -46
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +4 -46
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +6 -48
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +4 -46
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +4 -46
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +8 -110
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +4 -46
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +4 -46
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +4 -46
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +4 -46
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +4 -46
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +4 -46
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +4 -46
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +4 -46
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +6 -48
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +4 -46
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +4 -46
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +4 -46
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +8 -66
- nautobot/project-static/docs/user-guide/administration/installation/index.html +4 -46
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +5 -47
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +4 -46
- nautobot/project-static/docs/user-guide/administration/installation/services.html +4 -46
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +4 -46
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +4 -46
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +4 -46
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +4 -46
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +4 -46
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +4 -46
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +4 -46
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +4 -46
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +4 -46
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +8 -49
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +4 -46
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +4 -46
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +12 -50
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +7 -49
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +4 -46
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +4 -46
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +4 -46
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +4 -46
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +4 -46
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +4 -46
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +4 -46
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +4 -46
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +4 -46
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +4 -46
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +4 -46
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +4 -46
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +4 -46
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +7 -51
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +4 -46
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +4 -46
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +4 -46
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +7 -49
- nautobot/project-static/docs/user-guide/index.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +8 -50
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +7 -50
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +7 -49
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +5 -47
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +25 -94
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +5 -74
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +4 -46
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +4 -46
- nautobot/project-static/js/forms.js +1 -1
- nautobot/tenancy/api/views.py +13 -9
- nautobot/tenancy/views.py +2 -4
- nautobot/users/admin.py +1 -1
- nautobot/users/api/serializers.py +4 -5
- nautobot/users/api/views.py +3 -3
- nautobot/virtualization/api/serializers.py +4 -4
- nautobot/virtualization/api/views.py +24 -5
- nautobot/virtualization/filters.py +3 -20
- nautobot/virtualization/models.py +1 -1
- nautobot/virtualization/tables.py +2 -2
- nautobot/virtualization/templates/virtualization/cluster_edit.html +7 -1
- nautobot/virtualization/templates/virtualization/virtualmachine.html +9 -1
- nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +8 -2
- nautobot/virtualization/tests/test_filters.py +0 -17
- nautobot/wireless/filters.py +2 -2
- nautobot/wireless/forms.py +1 -1
- nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +9 -1
- nautobot/wireless/tests/test_filters.py +1 -29
- nautobot/wireless/views.py +10 -0
- {nautobot-2.4.0.dist-info → nautobot-2.4.0b1.dist-info}/METADATA +6 -6
- {nautobot-2.4.0.dist-info → nautobot-2.4.0b1.dist-info}/RECORD +543 -591
- {nautobot-2.4.0.dist-info → nautobot-2.4.0b1.dist-info}/WHEEL +1 -1
- nautobot/core/api/constants.py +0 -11
- nautobot/core/jobs/bulk_actions.py +0 -248
- nautobot/core/templates/about.html +0 -67
- nautobot/core/templates/inc/tenancy_form_panel.html +0 -9
- nautobot/core/templates/inc/tenant_table_row.html +0 -11
- nautobot/core/utils/querysets.py +0 -64
- nautobot/dcim/migrations/0067_controllermanageddevicegroup_tenant.py +0 -25
- nautobot/dcim/tests/integration/test_controller.py +0 -62
- nautobot/dcim/tests/integration/test_controller_managed_device_group.py +0 -71
- nautobot/dcim/tests/test_jobs.py +0 -118
- nautobot/extras/migrations/0120_job_is_singleton_job_is_singleton_override.py +0 -22
- nautobot/extras/migrations/0121_alter_team_contacts.py +0 -17
- nautobot/extras/test_jobs/singleton.py +0 -16
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_edit.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_edit_button.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_list_nav.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_list_view.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue_add.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue_config.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_completed.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_nav.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_pending.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_run_form.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_nautobot_login.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_run_job.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_run_scheduled_job_form.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_scheduled_job_result.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/buttons-example.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/cluster-type-before-after-example.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/object-fields-panel-example_2.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/stats-panel-example-code.png +0 -0
- nautobot/project-static/docs/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/wireless-networks-and-controllers.html +0 -9444
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +0 -9722
- nautobot/wireless/tests/integration/__init__.py +0 -0
- nautobot/wireless/tests/integration/test_radio_profile.py +0 -42
- {nautobot-2.4.0.dist-info → nautobot-2.4.0b1.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.4.0.dist-info → nautobot-2.4.0b1.dist-info}/NOTICE +0 -0
- {nautobot-2.4.0.dist-info → nautobot-2.4.0b1.dist-info}/entry_points.txt +0 -0
nautobot/extras/forms/forms.py
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import inspect
|
|
2
|
-
import logging
|
|
3
2
|
|
|
4
|
-
from celery import chain
|
|
5
3
|
from django import forms
|
|
6
4
|
from django.conf import settings
|
|
7
5
|
from django.contrib.auth import get_user_model
|
|
@@ -9,7 +7,7 @@ from django.contrib.contenttypes.models import ContentType
|
|
|
9
7
|
from django.core.exceptions import ValidationError
|
|
10
8
|
from django.core.validators import MinValueValidator
|
|
11
9
|
from django.db.models.fields import TextField
|
|
12
|
-
from django.forms import inlineformset_factory, ModelMultipleChoiceField
|
|
10
|
+
from django.forms import inlineformset_factory, ModelMultipleChoiceField
|
|
13
11
|
from django.urls.base import reverse
|
|
14
12
|
from django.utils.timezone import get_current_timezone_name
|
|
15
13
|
|
|
@@ -37,7 +35,6 @@ from nautobot.core.forms import (
|
|
|
37
35
|
TagFilterField,
|
|
38
36
|
)
|
|
39
37
|
from nautobot.core.forms.constants import BOOLEAN_WITH_BLANK_CHOICES
|
|
40
|
-
from nautobot.core.forms.forms import ConfirmationForm
|
|
41
38
|
from nautobot.core.utils.deprecation import class_deprecated_in_favor_of
|
|
42
39
|
from nautobot.dcim.models import Device, DeviceRedundancyGroup, DeviceType, Location, Platform
|
|
43
40
|
from nautobot.extras.choices import (
|
|
@@ -91,12 +88,9 @@ from nautobot.extras.models import (
|
|
|
91
88
|
Webhook,
|
|
92
89
|
)
|
|
93
90
|
from nautobot.extras.registry import registry
|
|
94
|
-
from nautobot.extras.signals import change_context_state
|
|
95
|
-
from nautobot.extras.tasks import delete_custom_field_data
|
|
96
91
|
from nautobot.extras.utils import (
|
|
97
92
|
ChangeLoggedModelsQuery,
|
|
98
93
|
FeatureQuery,
|
|
99
|
-
get_worker_count,
|
|
100
94
|
RoleModelsQuery,
|
|
101
95
|
TaggableClassesQuery,
|
|
102
96
|
)
|
|
@@ -117,90 +111,87 @@ from .mixins import (
|
|
|
117
111
|
TagsBulkEditFormMixin,
|
|
118
112
|
)
|
|
119
113
|
|
|
120
|
-
logger = logging.getLogger(__name__)
|
|
121
|
-
|
|
122
114
|
__all__ = (
|
|
123
115
|
"BaseDynamicGroupMembershipFormSet",
|
|
124
|
-
"ComputedFieldFilterForm",
|
|
125
116
|
"ComputedFieldForm",
|
|
117
|
+
"ComputedFieldFilterForm",
|
|
118
|
+
"ConfigContextForm",
|
|
126
119
|
"ConfigContextBulkEditForm",
|
|
127
120
|
"ConfigContextFilterForm",
|
|
128
|
-
"
|
|
121
|
+
"ConfigContextSchemaForm",
|
|
129
122
|
"ConfigContextSchemaBulkEditForm",
|
|
130
123
|
"ConfigContextSchemaFilterForm",
|
|
131
|
-
"ConfigContextSchemaForm",
|
|
132
|
-
"CustomFieldBulkCreateForm", # 2.0 TODO remove this deprecated class
|
|
133
|
-
"CustomFieldBulkDeleteForm",
|
|
134
|
-
"CustomFieldChoiceFormSet",
|
|
135
|
-
"CustomFieldFilterForm",
|
|
136
124
|
"CustomFieldForm",
|
|
125
|
+
"CustomFieldFilterForm",
|
|
137
126
|
"CustomFieldModelCSVForm",
|
|
138
|
-
"
|
|
127
|
+
"CustomFieldBulkCreateForm", # 2.0 TODO remove this deprecated class
|
|
128
|
+
"CustomFieldChoiceFormSet",
|
|
139
129
|
"CustomLinkForm",
|
|
130
|
+
"CustomLinkFilterForm",
|
|
140
131
|
"DynamicGroupBulkAssignForm",
|
|
141
|
-
"DynamicGroupFilterForm",
|
|
142
132
|
"DynamicGroupForm",
|
|
133
|
+
"DynamicGroupFilterForm",
|
|
143
134
|
"DynamicGroupMembershipFormSet",
|
|
144
|
-
"ExportTemplateFilterForm",
|
|
145
135
|
"ExportTemplateForm",
|
|
146
|
-
"
|
|
136
|
+
"ExportTemplateFilterForm",
|
|
147
137
|
"ExternalIntegrationFilterForm",
|
|
148
138
|
"ExternalIntegrationForm",
|
|
139
|
+
"ExternalIntegrationBulkEditForm",
|
|
140
|
+
"GitRepositoryForm",
|
|
149
141
|
"GitRepositoryBulkEditForm",
|
|
150
142
|
"GitRepositoryFilterForm",
|
|
151
|
-
"GitRepositoryForm",
|
|
152
|
-
"GraphQLQueryFilterForm",
|
|
153
143
|
"GraphQLQueryForm",
|
|
144
|
+
"GraphQLQueryFilterForm",
|
|
154
145
|
"ImageAttachmentForm",
|
|
146
|
+
"JobForm",
|
|
155
147
|
"JobBulkEditForm",
|
|
148
|
+
"JobButtonForm",
|
|
156
149
|
"JobButtonBulkEditForm",
|
|
157
150
|
"JobButtonFilterForm",
|
|
158
|
-
"JobButtonForm",
|
|
159
151
|
"JobEditForm",
|
|
160
152
|
"JobFilterForm",
|
|
161
|
-
"JobForm",
|
|
162
|
-
"JobHookFilterForm",
|
|
163
153
|
"JobHookForm",
|
|
154
|
+
"JobHookFilterForm",
|
|
164
155
|
"JobQueueBulkEditForm",
|
|
165
156
|
"JobQueueFilterForm",
|
|
166
157
|
"JobQueueForm",
|
|
167
|
-
"JobResultFilterForm",
|
|
168
158
|
"JobScheduleForm",
|
|
159
|
+
"JobResultFilterForm",
|
|
169
160
|
"LocalContextFilterForm",
|
|
170
|
-
"LocalContextModelBulkEditForm",
|
|
171
161
|
"LocalContextModelForm",
|
|
172
|
-
"
|
|
162
|
+
"LocalContextModelBulkEditForm",
|
|
173
163
|
"MetadataTypeBulkEditForm",
|
|
174
|
-
"MetadataTypeFilterForm",
|
|
175
164
|
"MetadataTypeForm",
|
|
176
|
-
"
|
|
165
|
+
"MetadataTypeFilterForm",
|
|
166
|
+
"MetadataChoiceFormSet",
|
|
177
167
|
"NoteForm",
|
|
168
|
+
"NoteFilterForm",
|
|
178
169
|
"ObjectChangeFilterForm",
|
|
179
170
|
"ObjectMetadataFilterForm",
|
|
180
171
|
"PasswordInputWithPlaceholder",
|
|
181
|
-
"RelationshipAssociationFilterForm",
|
|
182
|
-
"RelationshipFilterForm",
|
|
183
172
|
"RelationshipForm",
|
|
173
|
+
"RelationshipFilterForm",
|
|
174
|
+
"RelationshipAssociationFilterForm",
|
|
184
175
|
"RoleBulkEditForm",
|
|
185
176
|
"RoleFilterForm",
|
|
186
177
|
"RoleForm",
|
|
187
178
|
"SavedViewForm",
|
|
188
179
|
"SavedViewModalForm",
|
|
189
180
|
"ScheduledJobFilterForm",
|
|
190
|
-
"SecretFilterForm",
|
|
191
181
|
"SecretForm",
|
|
192
|
-
"
|
|
193
|
-
"SecretsGroupFilterForm",
|
|
182
|
+
"SecretFilterForm",
|
|
194
183
|
"SecretsGroupForm",
|
|
184
|
+
"SecretsGroupFilterForm",
|
|
185
|
+
"SecretsGroupAssociationFormSet",
|
|
195
186
|
"StaticGroupAssociationFilterForm",
|
|
196
|
-
"StatusBulkEditForm",
|
|
197
|
-
"StatusFilterForm",
|
|
198
187
|
"StatusForm",
|
|
199
|
-
"
|
|
200
|
-
"
|
|
188
|
+
"StatusFilterForm",
|
|
189
|
+
"StatusBulkEditForm",
|
|
201
190
|
"TagForm",
|
|
202
|
-
"
|
|
191
|
+
"TagFilterForm",
|
|
192
|
+
"TagBulkEditForm",
|
|
203
193
|
"WebhookForm",
|
|
194
|
+
"WebhookFilterForm",
|
|
204
195
|
)
|
|
205
196
|
|
|
206
197
|
|
|
@@ -500,44 +491,6 @@ class CustomFieldBulkCreateForm(CustomFieldModelBulkEditFormMixin):
|
|
|
500
491
|
"""No longer needed as a separate class - use CustomFieldModelBulkEditFormMixin instead."""
|
|
501
492
|
|
|
502
493
|
|
|
503
|
-
class CustomFieldBulkDeleteForm(ConfirmationForm):
|
|
504
|
-
def __init__(self, *args, delete_all=False, **kwargs):
|
|
505
|
-
super().__init__(*args, **kwargs)
|
|
506
|
-
queryset = CustomField.objects.all()
|
|
507
|
-
self.fields["pk"] = ModelMultipleChoiceField(
|
|
508
|
-
queryset=queryset, widget=MultipleHiddenInput, required=not delete_all
|
|
509
|
-
)
|
|
510
|
-
|
|
511
|
-
def construct_custom_field_delete_tasks(self, queryset):
|
|
512
|
-
"""
|
|
513
|
-
Helper method to construct a list of celery tasks to execute when bulk deleting custom fields.
|
|
514
|
-
"""
|
|
515
|
-
change_context = change_context_state.get()
|
|
516
|
-
if change_context is None:
|
|
517
|
-
context = None
|
|
518
|
-
else:
|
|
519
|
-
context = change_context.as_dict(queryset)
|
|
520
|
-
context["context_detail"] = "bulk delete custom field data"
|
|
521
|
-
tasks = [
|
|
522
|
-
delete_custom_field_data.si(obj.key, set(obj.content_types.values_list("pk", flat=True)), context)
|
|
523
|
-
for obj in queryset
|
|
524
|
-
]
|
|
525
|
-
return tasks
|
|
526
|
-
|
|
527
|
-
def perform_pre_delete(self, queryset):
|
|
528
|
-
"""
|
|
529
|
-
Remove all Custom Field Keys/Values from _custom_field_data of the related ContentType in the background.
|
|
530
|
-
"""
|
|
531
|
-
if not get_worker_count():
|
|
532
|
-
logger.error("Celery worker process not running. Object custom fields may fail to reflect this deletion.")
|
|
533
|
-
return
|
|
534
|
-
tasks = self.construct_custom_field_delete_tasks(queryset)
|
|
535
|
-
# Executing the tasks in the background sequentially using chain() aligns with how a single
|
|
536
|
-
# CustomField object is deleted. We decided to not check the result because it needs at least one worker
|
|
537
|
-
# to be active and comes with extra performance penalty.
|
|
538
|
-
chain(*tasks).apply_async()
|
|
539
|
-
|
|
540
|
-
|
|
541
494
|
#
|
|
542
495
|
# Custom Links
|
|
543
496
|
#
|
|
@@ -1037,8 +990,6 @@ class JobEditForm(NautobotModelForm):
|
|
|
1037
990
|
"job_queues",
|
|
1038
991
|
"default_job_queue_override",
|
|
1039
992
|
"default_job_queue",
|
|
1040
|
-
"is_singleton",
|
|
1041
|
-
"is_singleton_override",
|
|
1042
993
|
"tags",
|
|
1043
994
|
]
|
|
1044
995
|
|
|
@@ -1138,11 +1089,6 @@ class JobBulkEditForm(NautobotBulkEditForm):
|
|
|
1138
1089
|
required=False,
|
|
1139
1090
|
help_text="Default Job Queue the job runs on if no Job Queue is specified",
|
|
1140
1091
|
)
|
|
1141
|
-
is_singleton = forms.NullBooleanField(
|
|
1142
|
-
required=False,
|
|
1143
|
-
widget=BulkEditNullBooleanSelect,
|
|
1144
|
-
help_text="Whether this job should fail to run if another instance of this job is already running",
|
|
1145
|
-
)
|
|
1146
1092
|
# Flags to indicate whether the above properties are inherited from the source code or overridden by the database
|
|
1147
1093
|
# Text field overrides
|
|
1148
1094
|
clear_grouping_override = forms.BooleanField(
|
|
@@ -1186,62 +1132,10 @@ class JobBulkEditForm(NautobotBulkEditForm):
|
|
|
1186
1132
|
required=False,
|
|
1187
1133
|
help_text="If checked, the values of has sensitive variables will be reverted to the default values defined in each Job's source code",
|
|
1188
1134
|
)
|
|
1189
|
-
is_singleton_override = forms.BooleanField(
|
|
1190
|
-
required=False,
|
|
1191
|
-
help_text="If checked, the values of is singleton will be reverted to the default values defined in each Job's source code",
|
|
1192
|
-
)
|
|
1193
1135
|
|
|
1194
1136
|
class Meta:
|
|
1195
1137
|
model = Job
|
|
1196
1138
|
|
|
1197
|
-
def post_save(self, obj):
|
|
1198
|
-
super().post_save(obj)
|
|
1199
|
-
|
|
1200
|
-
cleaned_data = self.cleaned_data
|
|
1201
|
-
|
|
1202
|
-
# Handle text related fields
|
|
1203
|
-
for overridable_field in JOB_OVERRIDABLE_FIELDS:
|
|
1204
|
-
override_field = overridable_field + "_override"
|
|
1205
|
-
clear_override_field = "clear_" + overridable_field + "_override"
|
|
1206
|
-
reset_override = cleaned_data.get(clear_override_field, False)
|
|
1207
|
-
override_value = cleaned_data.get(overridable_field)
|
|
1208
|
-
if reset_override:
|
|
1209
|
-
setattr(obj, override_field, False)
|
|
1210
|
-
elif not reset_override and override_value not in [None, ""]:
|
|
1211
|
-
setattr(obj, override_field, True)
|
|
1212
|
-
setattr(obj, overridable_field, override_value)
|
|
1213
|
-
|
|
1214
|
-
# Handle job queues
|
|
1215
|
-
clear_override_field = "clear_job_queues_override"
|
|
1216
|
-
reset_override = cleaned_data.get(clear_override_field, False)
|
|
1217
|
-
if reset_override:
|
|
1218
|
-
meta_task_queues = obj.job_class.task_queues
|
|
1219
|
-
job_queues = []
|
|
1220
|
-
for queue_name in meta_task_queues:
|
|
1221
|
-
try:
|
|
1222
|
-
job_queues.append(JobQueue.objects.get(name=queue_name))
|
|
1223
|
-
except JobQueue.DoesNotExist:
|
|
1224
|
-
# Do we want to create the Job Queue for the users here if we do not have it in the database?
|
|
1225
|
-
pass
|
|
1226
|
-
obj.job_queues_override = False
|
|
1227
|
-
obj.job_queues.set(job_queues)
|
|
1228
|
-
elif cleaned_data["job_queues"]:
|
|
1229
|
-
obj.job_queues_override = True
|
|
1230
|
-
|
|
1231
|
-
# Handle default job queue
|
|
1232
|
-
clear_override_field = "clear_default_job_queue_override"
|
|
1233
|
-
reset_override = cleaned_data.get(clear_override_field, False)
|
|
1234
|
-
if reset_override:
|
|
1235
|
-
meta_task_queues = obj.job_class.task_queues
|
|
1236
|
-
obj.default_job_queue_override = False
|
|
1237
|
-
obj.default_job_queue, _ = JobQueue.objects.get_or_create(
|
|
1238
|
-
name=meta_task_queues[0] if meta_task_queues else settings.CELERY_TASK_DEFAULT_QUEUE
|
|
1239
|
-
)
|
|
1240
|
-
elif cleaned_data["default_job_queue"]:
|
|
1241
|
-
obj.default_job_queue_override = True
|
|
1242
|
-
|
|
1243
|
-
obj.validated_save()
|
|
1244
|
-
|
|
1245
1139
|
|
|
1246
1140
|
class JobFilterForm(BootstrapMixin, forms.Form):
|
|
1247
1141
|
model = Job
|
|
@@ -1885,8 +1779,6 @@ class RoleBulkEditForm(NautobotBulkEditForm):
|
|
|
1885
1779
|
|
|
1886
1780
|
pk = forms.ModelMultipleChoiceField(queryset=Role.objects.all(), widget=forms.MultipleHiddenInput)
|
|
1887
1781
|
color = forms.CharField(max_length=6, required=False, widget=ColorSelect())
|
|
1888
|
-
description = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False)
|
|
1889
|
-
weight = forms.IntegerField(required=False)
|
|
1890
1782
|
content_types = MultipleContentTypeField(
|
|
1891
1783
|
queryset=RoleModelsQuery().as_queryset(), required=False, label="Content Type(s)"
|
|
1892
1784
|
)
|
nautobot/extras/forms/mixins.py
CHANGED
|
@@ -34,7 +34,7 @@ from nautobot.extras.utils import remove_prefix_from_cf_key
|
|
|
34
34
|
logger = logging.getLogger(__name__)
|
|
35
35
|
|
|
36
36
|
|
|
37
|
-
__all__ = (
|
|
37
|
+
__all__ = (
|
|
38
38
|
"ContactTeamModelFilterFormMixin",
|
|
39
39
|
"CustomFieldModelBulkEditFormMixin",
|
|
40
40
|
"CustomFieldModelFilterFormMixin",
|
|
@@ -673,7 +673,7 @@ class RelationshipModelFormMixin(forms.ModelForm):
|
|
|
673
673
|
for peer_id in target_peer_ids:
|
|
674
674
|
relationship = self.fields[field_name].model
|
|
675
675
|
if not relationship.symmetric:
|
|
676
|
-
association = RelationshipAssociation(
|
|
676
|
+
association = RelationshipAssociation(
|
|
677
677
|
relationship=relationship,
|
|
678
678
|
**{
|
|
679
679
|
f"{side}_type": self.obj_type,
|
|
@@ -837,21 +837,13 @@ class StatusModelFilterFormMixin(forms.Form):
|
|
|
837
837
|
self.order_fields(self.field_order) # Reorder fields again
|
|
838
838
|
|
|
839
839
|
|
|
840
|
-
class TagsBulkEditFormMixin(
|
|
840
|
+
class TagsBulkEditFormMixin(forms.Form):
|
|
841
841
|
def __init__(self, *args, **kwargs):
|
|
842
842
|
super().__init__(*args, **kwargs)
|
|
843
843
|
|
|
844
844
|
# Add add/remove tags fields
|
|
845
|
-
self.fields["add_tags"] = DynamicModelMultipleChoiceField(
|
|
846
|
-
|
|
847
|
-
query_params={"content_types": self.model._meta.label_lower},
|
|
848
|
-
required=False,
|
|
849
|
-
)
|
|
850
|
-
self.fields["remove_tags"] = DynamicModelMultipleChoiceField(
|
|
851
|
-
queryset=Tag.objects.all(),
|
|
852
|
-
query_params={"content_types": self.model._meta.label_lower},
|
|
853
|
-
required=False,
|
|
854
|
-
)
|
|
845
|
+
self.fields["add_tags"] = DynamicModelMultipleChoiceField(queryset=Tag.objects.all(), required=False)
|
|
846
|
+
self.fields["remove_tags"] = DynamicModelMultipleChoiceField(queryset=Tag.objects.all(), required=False)
|
|
855
847
|
|
|
856
848
|
|
|
857
849
|
# 2.2 TODO: Names below are only for backward compatibility with Nautobot 1.3 and earlier. Remove in 2.2
|
nautobot/extras/group_sync.py
CHANGED
|
@@ -8,15 +8,15 @@ from django.contrib.auth.models import Group
|
|
|
8
8
|
logger = logging.getLogger(__name__)
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
CLAIMS_GROUP_NAME = getattr(settings, "
|
|
11
|
+
CLAIMS_GROUP_NAME = getattr(settings, "NAUTOBOT_SSO_CLAIMS_GROUP", "groups")
|
|
12
12
|
""" Which claim to look at in the OAuth2/OIDC response
|
|
13
13
|
|
|
14
14
|
For Okta you can look at `Okta -> Authorization Servers -> Claims`. And a reasonable
|
|
15
15
|
default is "groups". For Azure a reasonable default is "roles".
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
SUPERUSER_GROUPS = getattr(settings, "
|
|
19
|
-
STAFF_GROUPS = getattr(settings, "
|
|
18
|
+
SUPERUSER_GROUPS = getattr(settings, "NAUTOBOT_SSO_SUPERUSER_GROUPS", [])
|
|
19
|
+
STAFF_GROUPS = getattr(settings, "NAUTOBOT_SSO_STAFF_GROUPS", [])
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
def group_sync(uid, user=None, response=None, *args, **kwargs):
|
nautobot/extras/health_checks.py
CHANGED
|
@@ -160,4 +160,5 @@ class RedisBackend(RedisHealthCheck):
|
|
|
160
160
|
elif client_class == "django_redis.client.DefaultClient":
|
|
161
161
|
self.check_redis(redis_url=location, **options.get("CONNECTION_POOL_KWARGS", {}))
|
|
162
162
|
else:
|
|
163
|
-
self.
|
|
163
|
+
if self.redis_url is None:
|
|
164
|
+
self.add_error(ServiceUnavailable(f"{client_class} is an unsupported CLIENT_CLASS!"))
|
nautobot/extras/jobs.py
CHANGED
|
@@ -18,7 +18,6 @@ from db_file_storage.form_widgets import DBClearableFileInput
|
|
|
18
18
|
from django import forms
|
|
19
19
|
from django.conf import settings
|
|
20
20
|
from django.contrib.auth import get_user_model
|
|
21
|
-
from django.core.cache import cache
|
|
22
21
|
from django.core.exceptions import ObjectDoesNotExist
|
|
23
22
|
from django.core.files.base import ContentFile
|
|
24
23
|
from django.core.files.uploadedfile import UploadedFile
|
|
@@ -68,15 +67,15 @@ User = get_user_model()
|
|
|
68
67
|
|
|
69
68
|
|
|
70
69
|
__all__ = [
|
|
70
|
+
"Job",
|
|
71
71
|
"BooleanVar",
|
|
72
72
|
"ChoiceVar",
|
|
73
73
|
"FileVar",
|
|
74
|
+
"IntegerVar",
|
|
74
75
|
"IPAddressVar",
|
|
75
76
|
"IPAddressWithMaskVar",
|
|
76
77
|
"IPNetworkVar",
|
|
77
|
-
"IntegerVar",
|
|
78
78
|
"JSONVar",
|
|
79
|
-
"Job",
|
|
80
79
|
"MultiChoiceVar",
|
|
81
80
|
"MultiObjectVar",
|
|
82
81
|
"ObjectVar",
|
|
@@ -106,16 +105,13 @@ class BaseJob:
|
|
|
106
105
|
|
|
107
106
|
- name (str)
|
|
108
107
|
- description (str)
|
|
109
|
-
- approval_required (bool)
|
|
110
|
-
- dryrun_default (bool)
|
|
111
|
-
- field_order (list)
|
|
112
|
-
- has_sensitive_variables (bool)
|
|
113
108
|
- hidden (bool)
|
|
109
|
+
- field_order (list)
|
|
110
|
+
- approval_required (bool)
|
|
114
111
|
- soft_time_limit (int)
|
|
115
|
-
- task_queues (list)
|
|
116
|
-
- template_name (str)
|
|
117
112
|
- time_limit (int)
|
|
118
|
-
-
|
|
113
|
+
- has_sensitive_variables (bool)
|
|
114
|
+
- task_queues (list)
|
|
119
115
|
"""
|
|
120
116
|
|
|
121
117
|
def __init__(self):
|
|
@@ -193,31 +189,6 @@ class BaseJob:
|
|
|
193
189
|
)
|
|
194
190
|
raise RunJobTaskFailed(f"Job {self.job_model} is not enabled to be run!")
|
|
195
191
|
|
|
196
|
-
ignore_singleton_lock = self.celery_kwargs.get("nautobot_job_ignore_singleton_lock", False)
|
|
197
|
-
if self.job_model.is_singleton:
|
|
198
|
-
is_running = cache.get(self.singleton_cache_key)
|
|
199
|
-
if is_running:
|
|
200
|
-
if ignore_singleton_lock:
|
|
201
|
-
self.logger.info(
|
|
202
|
-
"Job %s is a singleton and already running, but singleton will be ignored because"
|
|
203
|
-
" `ignore_singleton_lock` is set.",
|
|
204
|
-
self.job_model,
|
|
205
|
-
extra={"object": self.job_model, "grouping": "initialization"},
|
|
206
|
-
)
|
|
207
|
-
else:
|
|
208
|
-
self.logger.error(
|
|
209
|
-
"Job %s is a singleton and already running.",
|
|
210
|
-
self.job_model,
|
|
211
|
-
extra={"object": self.job_model, "grouping": "initialization"},
|
|
212
|
-
)
|
|
213
|
-
raise RunJobTaskFailed(f"Job '{self.job_model}' is a singleton and already running.")
|
|
214
|
-
cache_parameters = {
|
|
215
|
-
"key": self.singleton_cache_key,
|
|
216
|
-
"value": 1,
|
|
217
|
-
"timeout": self.job_model.time_limit or settings.CELERY_TASK_TIME_LIMIT,
|
|
218
|
-
}
|
|
219
|
-
cache.set(**cache_parameters)
|
|
220
|
-
|
|
221
192
|
soft_time_limit = self.job_model.soft_time_limit or settings.CELERY_TASK_SOFT_TIME_LIMIT
|
|
222
193
|
time_limit = self.job_model.time_limit or settings.CELERY_TASK_TIME_LIMIT
|
|
223
194
|
if time_limit <= soft_time_limit:
|
|
@@ -311,14 +282,6 @@ class BaseJob:
|
|
|
311
282
|
if status == JobResultStatusChoices.STATUS_SUCCESS:
|
|
312
283
|
self.logger.success("Job completed", extra={"grouping": "post_run"})
|
|
313
284
|
|
|
314
|
-
cache.delete(self.singleton_cache_key)
|
|
315
|
-
|
|
316
|
-
@final
|
|
317
|
-
@classproperty
|
|
318
|
-
def singleton_cache_key(cls) -> str: # pylint: disable=no-self-argument
|
|
319
|
-
"""Cache key for singleton jobs."""
|
|
320
|
-
return f"nautobot.extras.jobs.running.{cls.class_path}"
|
|
321
|
-
|
|
322
285
|
@final
|
|
323
286
|
@classproperty
|
|
324
287
|
def file_path(cls) -> str: # pylint: disable=no-self-argument
|
|
@@ -337,7 +300,7 @@ class BaseJob:
|
|
|
337
300
|
- my_plugin.jobs.MyPluginJob - App-provided Job
|
|
338
301
|
- git_repository.jobs.myjob.MyJob - GitRepository Job
|
|
339
302
|
"""
|
|
340
|
-
return f"{cls.__module__}.{cls.__name__}"
|
|
303
|
+
return f"{cls.__module__}.{cls.__name__}"
|
|
341
304
|
|
|
342
305
|
@final
|
|
343
306
|
@classproperty
|
|
@@ -374,7 +337,7 @@ class BaseJob:
|
|
|
374
337
|
@final
|
|
375
338
|
@classproperty
|
|
376
339
|
def name(cls) -> str: # pylint: disable=no-self-argument
|
|
377
|
-
return cls._get_meta_attr_and_assert_type("name", cls.__name__, expected_type=str)
|
|
340
|
+
return cls._get_meta_attr_and_assert_type("name", cls.__name__, expected_type=str)
|
|
378
341
|
|
|
379
342
|
@final
|
|
380
343
|
@classproperty
|
|
@@ -438,11 +401,6 @@ class BaseJob:
|
|
|
438
401
|
def task_queues(cls) -> list: # pylint: disable=no-self-argument
|
|
439
402
|
return cls._get_meta_attr_and_assert_type("task_queues", [], expected_type=(list, tuple))
|
|
440
403
|
|
|
441
|
-
@final
|
|
442
|
-
@classproperty
|
|
443
|
-
def is_singleton(cls) -> bool: # pylint: disable=no-self-argument
|
|
444
|
-
return cls._get_meta_attr_and_assert_type("is_singleton", False, expected_type=bool)
|
|
445
|
-
|
|
446
404
|
@final
|
|
447
405
|
@classproperty
|
|
448
406
|
def properties_dict(cls) -> dict: # pylint: disable=no-self-argument
|
|
@@ -461,14 +419,13 @@ class BaseJob:
|
|
|
461
419
|
"time_limit": cls.time_limit,
|
|
462
420
|
"has_sensitive_variables": cls.has_sensitive_variables,
|
|
463
421
|
"task_queues": cls.task_queues,
|
|
464
|
-
"is_singleton": cls.is_singleton,
|
|
465
422
|
}
|
|
466
423
|
|
|
467
424
|
@final
|
|
468
425
|
@classproperty
|
|
469
426
|
def registered_name(cls) -> str: # pylint: disable=no-self-argument
|
|
470
427
|
"""Deprecated - use class_path classproperty instead."""
|
|
471
|
-
return f"{cls.__module__}.{cls.__name__}"
|
|
428
|
+
return f"{cls.__module__}.{cls.__name__}"
|
|
472
429
|
|
|
473
430
|
@classmethod
|
|
474
431
|
def _get_vars(cls):
|
|
@@ -529,19 +486,6 @@ class BaseJob:
|
|
|
529
486
|
label="Profile job execution",
|
|
530
487
|
help_text="Profiles the job execution using cProfile and outputs a report to /tmp/",
|
|
531
488
|
)
|
|
532
|
-
# If the class already exists there may be overrides, so we have to check this.
|
|
533
|
-
try:
|
|
534
|
-
job_model = JobModel.objects.get(module_name=cls.__module__, job_class_name=cls.__name__)
|
|
535
|
-
is_singleton = job_model.is_singleton
|
|
536
|
-
except JobModel.DoesNotExist:
|
|
537
|
-
is_singleton = cls.is_singleton
|
|
538
|
-
if is_singleton:
|
|
539
|
-
form.fields["_ignore_singleton_lock"] = forms.BooleanField(
|
|
540
|
-
required=False,
|
|
541
|
-
initial=False,
|
|
542
|
-
label="Ignore singleton lock",
|
|
543
|
-
help_text="Allow this singleton job to run even when another instance is already running",
|
|
544
|
-
)
|
|
545
489
|
|
|
546
490
|
job_model = JobModel.objects.get_for_class_path(cls.class_path)
|
|
547
491
|
dryrun_default = job_model.dryrun_default if job_model.dryrun_default_override else cls.dryrun_default
|
|
@@ -575,9 +519,7 @@ class BaseJob:
|
|
|
575
519
|
field.disabled = True
|
|
576
520
|
|
|
577
521
|
# Ensure non-Job-specific fields are still last after applying field_order
|
|
578
|
-
for field in ["_job_queue", "_profile"
|
|
579
|
-
if field not in form.fields:
|
|
580
|
-
continue
|
|
522
|
+
for field in ["_job_queue", "_profile"]:
|
|
581
523
|
value = form.fields.pop(field)
|
|
582
524
|
form.fields[field] = value
|
|
583
525
|
|
|
@@ -1089,7 +1031,7 @@ class JobHookReceiver(Job):
|
|
|
1089
1031
|
|
|
1090
1032
|
object_change = ObjectVar(model=ObjectChange)
|
|
1091
1033
|
|
|
1092
|
-
def run(self, object_change):
|
|
1034
|
+
def run(self, object_change):
|
|
1093
1035
|
"""JobHookReceiver subclasses generally shouldn't need to override this method."""
|
|
1094
1036
|
self.receive_job_hook(
|
|
1095
1037
|
change=object_change,
|
|
@@ -1118,7 +1060,7 @@ class JobButtonReceiver(Job):
|
|
|
1118
1060
|
object_pk = StringVar()
|
|
1119
1061
|
object_model_name = StringVar()
|
|
1120
1062
|
|
|
1121
|
-
def run(self, object_pk, object_model_name):
|
|
1063
|
+
def run(self, object_pk, object_model_name):
|
|
1122
1064
|
"""JobButtonReceiver subclasses generally shouldn't need to override this method."""
|
|
1123
1065
|
model = get_model_from_name(object_model_name)
|
|
1124
1066
|
obj = model.objects.get(pk=object_pk)
|
nautobot/extras/managers.py
CHANGED
|
@@ -22,9 +22,8 @@ class JobResultManager(BaseManager.from_queryset(RestrictedQuerySet), TaskResult
|
|
|
22
22
|
return self.model(id=task_id)
|
|
23
23
|
|
|
24
24
|
@transaction_retry(max_retries=2)
|
|
25
|
-
def store_result(
|
|
25
|
+
def store_result(
|
|
26
26
|
self,
|
|
27
|
-
*,
|
|
28
27
|
task_id,
|
|
29
28
|
result,
|
|
30
29
|
status,
|
|
@@ -42,7 +41,6 @@ class JobResultManager(BaseManager.from_queryset(RestrictedQuerySet), TaskResult
|
|
|
42
41
|
using=None,
|
|
43
42
|
content_type=None,
|
|
44
43
|
content_encoding=None,
|
|
45
|
-
**kwargs,
|
|
46
44
|
):
|
|
47
45
|
"""
|
|
48
46
|
Store the result and status of a Celery task.
|
|
@@ -2,6 +2,7 @@ from collections import OrderedDict
|
|
|
2
2
|
|
|
3
3
|
from django.db import migrations
|
|
4
4
|
|
|
5
|
+
from nautobot.extras.choices import LogLevelChoices
|
|
5
6
|
from nautobot.extras.constants import (
|
|
6
7
|
JOB_LOG_MAX_ABSOLUTE_URL_LENGTH,
|
|
7
8
|
JOB_LOG_MAX_GROUPING_LENGTH,
|
|
@@ -122,13 +123,14 @@ def reverse_migrate_params(apps, schema_editor):
|
|
|
122
123
|
]
|
|
123
124
|
)
|
|
124
125
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
126
|
+
if entry.log_level != LogLevelChoices.LOG_DEFAULT:
|
|
127
|
+
job_result.data[entry.grouping].setdefault(entry.log_level, 0)
|
|
128
|
+
job_result.data[entry.grouping][entry.log_level] += 1
|
|
129
|
+
if "total" not in job_result.data:
|
|
130
|
+
job_result.data["total"] = _data_grouping_struct()
|
|
131
|
+
del job_result.data["total"]["log"]
|
|
132
|
+
job_result.data["total"].setdefault(entry.log_level, 0)
|
|
133
|
+
job_result.data["total"][entry.log_level] += 1
|
|
132
134
|
|
|
133
135
|
job_result.save()
|
|
134
136
|
|
|
@@ -61,7 +61,7 @@ class Contact(ContactTeamSharedBase):
|
|
|
61
61
|
class Team(ContactTeamSharedBase):
|
|
62
62
|
"""A group of Contacts, usable interchangeably with a single Contact in most cases."""
|
|
63
63
|
|
|
64
|
-
contacts = models.ManyToManyField(to=Contact, related_name="teams"
|
|
64
|
+
contacts = models.ManyToManyField(to=Contact, related_name="teams")
|
|
65
65
|
|
|
66
66
|
class Meta(ContactTeamSharedBase.Meta):
|
|
67
67
|
abstract = False
|
|
@@ -578,13 +578,7 @@ class CustomField(
|
|
|
578
578
|
)
|
|
579
579
|
|
|
580
580
|
def to_form_field(
|
|
581
|
-
self,
|
|
582
|
-
set_initial=True,
|
|
583
|
-
enforce_required=True,
|
|
584
|
-
for_csv_import=False,
|
|
585
|
-
simple_json_filter=False,
|
|
586
|
-
label=None,
|
|
587
|
-
for_filter_form=False,
|
|
581
|
+
self, set_initial=True, enforce_required=True, for_csv_import=False, simple_json_filter=False, label=None
|
|
588
582
|
):
|
|
589
583
|
"""
|
|
590
584
|
Return a form field suitable for setting a CustomField's value for an object.
|
|
@@ -596,7 +590,6 @@ class CustomField(
|
|
|
596
590
|
this is *not* used for CSV imports since 2.0, but it *is* used for JSON/YAML import of DeviceTypes.
|
|
597
591
|
simple_json_filter: Return a TextInput widget for JSON filtering instead of the default TextArea widget.
|
|
598
592
|
label: Set the input label manually (if required); otherwise, defaults to field's __str__() implementation.
|
|
599
|
-
for_filter_form: If True return the relevant form field for filter form
|
|
600
593
|
"""
|
|
601
594
|
initial = self.default if set_initial else None
|
|
602
595
|
required = self.required if enforce_required else False
|
|
@@ -683,7 +676,7 @@ class CustomField(
|
|
|
683
676
|
default_choice = self.custom_field_choices.filter(value=self.default).first()
|
|
684
677
|
|
|
685
678
|
# Set the initial value to the first available choice (if any)
|
|
686
|
-
if self.type == CustomFieldTypeChoices.TYPE_SELECT
|
|
679
|
+
if self.type == CustomFieldTypeChoices.TYPE_SELECT:
|
|
687
680
|
if not required or default_choice is None:
|
|
688
681
|
choices = add_blank_choice(choices)
|
|
689
682
|
field_class = CSVChoiceField if for_csv_import else forms.ChoiceField
|
|
@@ -711,10 +704,16 @@ class CustomField(
|
|
|
711
704
|
|
|
712
705
|
def to_filter_form_field(self, lookup_expr="exact", *args, **kwargs):
|
|
713
706
|
"""Return a filter form field suitable for filtering a CustomField's value for an object."""
|
|
714
|
-
form_field = self.to_form_field(*args, **kwargs
|
|
715
|
-
# We would handle type selection differently because:
|
|
707
|
+
form_field = self.to_form_field(*args, **kwargs)
|
|
708
|
+
# We would handle type selection differently because:
|
|
709
|
+
# 1. We'd need to use StaticSelect2Multiple for lookup_type 'exact' because self.type `select` uses StaticSelect2 by default.
|
|
710
|
+
# 2. Remove the blank choice since StaticSelect2Multiple is always blank and interprets the blank choice as an extra option.
|
|
711
|
+
# 3. If lookup_type is not the same as exact, use MultiValueCharInput
|
|
716
712
|
if self.type == CustomFieldTypeChoices.TYPE_SELECT:
|
|
717
|
-
if lookup_expr
|
|
713
|
+
if lookup_expr in ["exact", "contains"]:
|
|
714
|
+
choices = form_field.choices[1:]
|
|
715
|
+
form_field.widget = StaticSelect2Multiple(choices=choices)
|
|
716
|
+
else:
|
|
718
717
|
form_field.widget = MultiValueCharInput()
|
|
719
718
|
return form_field
|
|
720
719
|
|