nautobot 2.4.0b1__py3-none-any.whl → 2.4.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of nautobot might be problematic. Click here for more details.
- nautobot/apps/__init__.py +1 -1
- nautobot/apps/api.py +8 -8
- nautobot/apps/change_logging.py +2 -2
- nautobot/apps/choices.py +4 -4
- nautobot/apps/events.py +3 -3
- nautobot/apps/factory.py +2 -2
- nautobot/apps/filters.py +1 -1
- nautobot/apps/forms.py +20 -20
- nautobot/apps/graphql.py +2 -2
- nautobot/apps/jobs.py +8 -8
- nautobot/apps/models.py +19 -19
- nautobot/apps/tables.py +1 -1
- nautobot/apps/testing.py +10 -10
- nautobot/apps/ui.py +2 -2
- nautobot/apps/utils.py +7 -7
- nautobot/apps/views.py +7 -7
- nautobot/circuits/api/serializers.py +1 -0
- nautobot/circuits/api/views.py +4 -8
- nautobot/circuits/tables.py +2 -1
- nautobot/circuits/templates/circuits/circuit_create.html +1 -7
- nautobot/circuits/tests/integration/test_circuits_bulk_operations.py +43 -0
- nautobot/circuits/tests/integration/test_relationships.py +1 -1
- nautobot/circuits/views.py +3 -3
- nautobot/cloud/api/views.py +6 -10
- nautobot/cloud/models.py +1 -1
- nautobot/cloud/views.py +0 -16
- nautobot/core/api/constants.py +11 -0
- nautobot/core/api/fields.py +5 -5
- nautobot/core/api/filter_backends.py +3 -9
- nautobot/core/api/schema.py +13 -2
- nautobot/core/api/serializers.py +40 -34
- nautobot/core/api/views.py +56 -4
- nautobot/core/apps/__init__.py +0 -5
- nautobot/core/celery/log.py +4 -4
- nautobot/core/celery/schedulers.py +2 -2
- nautobot/core/choices.py +2 -2
- nautobot/core/events/__init__.py +3 -3
- nautobot/core/filters.py +67 -35
- nautobot/core/forms/__init__.py +19 -19
- nautobot/core/forms/fields.py +14 -11
- nautobot/core/forms/forms.py +33 -2
- nautobot/core/graphql/types.py +1 -1
- nautobot/core/jobs/__init__.py +28 -7
- nautobot/core/jobs/bulk_actions.py +285 -0
- nautobot/core/jobs/cleanup.py +48 -12
- nautobot/core/jobs/groups.py +1 -1
- nautobot/core/management/commands/validate_models.py +1 -1
- nautobot/core/models/__init__.py +3 -1
- nautobot/core/models/query_functions.py +2 -2
- nautobot/core/models/tree_queries.py +6 -3
- nautobot/core/settings.py +29 -2
- nautobot/core/settings.yaml +21 -0
- nautobot/core/tables.py +79 -61
- nautobot/core/templates/about.html +67 -0
- nautobot/core/templates/generic/object_bulk_destroy.html +1 -1
- nautobot/core/templates/inc/media.html +3 -0
- nautobot/core/templates/inc/nav_menu.html +1 -0
- nautobot/core/templates/inc/tenancy_form_panel.html +9 -0
- nautobot/core/templates/inc/tenant_table_row.html +11 -0
- nautobot/core/templates/nautobot_config.py.j2 +13 -0
- nautobot/core/templates/search.html +7 -0
- nautobot/core/templates/utilities/render_jinja2.html +1 -1
- nautobot/core/templates/utilities/templatetags/tag.html +1 -1
- nautobot/core/templates/utilities/theme_preview.html +7 -0
- nautobot/core/templatetags/helpers.py +11 -2
- nautobot/core/testing/__init__.py +8 -8
- nautobot/core/testing/api.py +170 -15
- nautobot/core/testing/filters.py +45 -10
- nautobot/core/testing/forms.py +2 -0
- nautobot/core/testing/integration.py +514 -5
- nautobot/core/testing/mixins.py +7 -2
- nautobot/core/testing/views.py +44 -29
- nautobot/core/tests/integration/test_app_home.py +0 -1
- nautobot/core/tests/integration/test_app_navbar.py +0 -1
- nautobot/core/tests/integration/test_filters.py +0 -2
- nautobot/core/tests/integration/test_home.py +0 -1
- nautobot/core/tests/integration/test_navbar.py +0 -1
- nautobot/core/tests/integration/test_view_authentication.py +1 -0
- nautobot/core/tests/runner.py +1 -1
- nautobot/core/tests/test_api.py +98 -1
- nautobot/core/tests/test_csv.py +25 -3
- nautobot/core/tests/test_filters.py +209 -246
- nautobot/core/tests/test_forms.py +1 -0
- nautobot/core/tests/test_jobs.py +492 -1
- nautobot/core/tests/test_models.py +9 -0
- nautobot/core/tests/test_settings_schema.py +7 -0
- nautobot/core/tests/test_tables.py +100 -0
- nautobot/core/tests/test_utils.py +63 -1
- nautobot/core/tests/test_views.py +30 -3
- nautobot/core/ui/nav.py +1 -0
- nautobot/core/ui/object_detail.py +15 -1
- nautobot/core/urls.py +11 -0
- nautobot/core/utils/git.py +7 -2
- nautobot/core/utils/lookup.py +11 -8
- nautobot/core/utils/querysets.py +64 -0
- nautobot/core/utils/requests.py +24 -9
- nautobot/core/views/__init__.py +42 -0
- nautobot/core/views/generic.py +131 -197
- nautobot/core/views/mixins.py +136 -41
- nautobot/core/views/renderers.py +6 -6
- nautobot/core/views/utils.py +2 -2
- nautobot/dcim/api/serializers.py +56 -64
- nautobot/dcim/api/views.py +47 -113
- nautobot/dcim/constants.py +6 -13
- nautobot/dcim/factory.py +6 -1
- nautobot/dcim/filters/__init__.py +31 -2
- nautobot/dcim/forms.py +48 -17
- nautobot/dcim/graphql/types.py +2 -2
- nautobot/dcim/migrations/0067_controllermanageddevicegroup_tenant.py +25 -0
- nautobot/dcim/models/__init__.py +1 -1
- nautobot/dcim/models/device_component_templates.py +2 -2
- nautobot/dcim/models/device_components.py +22 -20
- nautobot/dcim/models/devices.py +10 -1
- nautobot/dcim/models/locations.py +3 -3
- nautobot/dcim/models/power.py +6 -5
- nautobot/dcim/models/racks.py +4 -4
- nautobot/dcim/tables/__init__.py +3 -3
- nautobot/dcim/tables/devices.py +9 -6
- nautobot/dcim/tables/devicetypes.py +2 -2
- nautobot/dcim/tables/racks.py +1 -1
- nautobot/dcim/templates/dcim/cable.html +1 -1
- nautobot/dcim/templates/dcim/controller_create.html +1 -7
- nautobot/dcim/templates/dcim/controller_retrieve.html +1 -9
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +2 -0
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +5 -0
- nautobot/dcim/templates/dcim/device/base.html +1 -1
- nautobot/dcim/templates/dcim/device.html +3 -11
- nautobot/dcim/templates/dcim/device_component.html +1 -1
- nautobot/dcim/templates/dcim/device_edit.html +36 -37
- nautobot/dcim/templates/dcim/devicetype.html +1 -1
- nautobot/dcim/templates/dcim/location.html +2 -10
- nautobot/dcim/templates/dcim/location_edit.html +1 -7
- nautobot/dcim/templates/dcim/locationtype.html +1 -1
- nautobot/dcim/templates/dcim/locationtype_retrieve.html +1 -1
- nautobot/dcim/templates/dcim/manufacturer.html +1 -1
- nautobot/dcim/templates/dcim/platform.html +1 -1
- nautobot/dcim/templates/dcim/powerfeed.html +1 -1
- nautobot/dcim/templates/dcim/powerpanel.html +1 -1
- nautobot/dcim/templates/dcim/rack.html +2 -10
- nautobot/dcim/templates/dcim/rack_edit.html +1 -7
- nautobot/dcim/templates/dcim/rackgroup.html +1 -1
- nautobot/dcim/templates/dcim/rackreservation.html +3 -11
- nautobot/dcim/templates/dcim/virtualchassis.html +1 -1
- nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +1 -9
- nautobot/dcim/templates/dcim/virtualdevicecontext_update.html +1 -7
- nautobot/dcim/tests/integration/test_controller.py +62 -0
- nautobot/dcim/tests/integration/test_controller_managed_device_group.py +71 -0
- nautobot/dcim/tests/integration/test_device_bulk_operations.py +30 -0
- nautobot/dcim/tests/integration/test_location_bulk_operations.py +43 -0
- nautobot/dcim/tests/test_api.py +16 -5
- nautobot/dcim/tests/test_filters.py +33 -0
- nautobot/dcim/tests/test_forms.py +51 -2
- nautobot/dcim/tests/test_graphql.py +52 -0
- nautobot/dcim/tests/test_jobs.py +118 -0
- nautobot/dcim/tests/test_models.py +52 -9
- nautobot/dcim/tests/test_views.py +30 -84
- nautobot/dcim/views.py +13 -28
- nautobot/extras/api/customfields.py +2 -2
- nautobot/extras/api/serializers.py +123 -85
- nautobot/extras/api/views.py +33 -30
- nautobot/extras/constants.py +3 -0
- nautobot/extras/datasources/git.py +125 -0
- nautobot/extras/filters/__init__.py +8 -6
- nautobot/extras/forms/base.py +2 -2
- nautobot/extras/forms/forms.py +139 -31
- nautobot/extras/forms/mixins.py +14 -6
- nautobot/extras/group_sync.py +3 -3
- nautobot/extras/health_checks.py +1 -2
- nautobot/extras/jobs.py +85 -18
- nautobot/extras/managers.py +3 -1
- nautobot/extras/migrations/0018_joblog_data_migration.py +7 -9
- nautobot/extras/migrations/0120_job_is_singleton_job_is_singleton_override.py +22 -0
- nautobot/extras/migrations/0121_alter_team_contacts.py +17 -0
- nautobot/extras/migrations/0122_add_graphqlquery_owner_content_type.py +34 -0
- nautobot/extras/models/__init__.py +1 -1
- nautobot/extras/models/contacts.py +1 -1
- nautobot/extras/models/customfields.py +41 -23
- nautobot/extras/models/datasources.py +85 -0
- nautobot/extras/models/groups.py +11 -9
- nautobot/extras/models/jobs.py +23 -4
- nautobot/extras/models/models.py +17 -2
- nautobot/extras/models/relationships.py +17 -5
- nautobot/extras/plugins/__init__.py +13 -2
- nautobot/extras/plugins/marketplace_manifest.yml +84 -79
- nautobot/extras/plugins/tables.py +16 -14
- nautobot/extras/plugins/views.py +65 -69
- nautobot/extras/registry.py +1 -1
- nautobot/extras/secrets/__init__.py +2 -2
- nautobot/extras/signals.py +15 -1
- nautobot/extras/tables.py +7 -5
- nautobot/extras/templates/extras/computedfield.html +1 -1
- nautobot/extras/templates/extras/configcontext.html +1 -1
- nautobot/extras/templates/extras/configcontextschema.html +1 -1
- nautobot/extras/templates/extras/customfield.html +1 -1
- nautobot/extras/templates/extras/customlink.html +1 -1
- nautobot/extras/templates/extras/dynamicgroup.html +2 -10
- nautobot/extras/templates/extras/exporttemplate.html +1 -1
- nautobot/extras/templates/extras/gitrepository.html +1 -1
- nautobot/extras/templates/extras/graphqlquery.html +1 -1
- nautobot/extras/templates/extras/job_detail.html +17 -1
- nautobot/extras/templates/extras/job_edit.html +1 -0
- nautobot/extras/templates/extras/jobbutton_retrieve.html +1 -1
- nautobot/extras/templates/extras/jobhook.html +1 -1
- nautobot/extras/templates/extras/jobqueue_retrieve.html +1 -9
- nautobot/extras/templates/extras/jobresult.html +1 -1
- nautobot/extras/templates/extras/marketplace.html +29 -11
- nautobot/extras/templates/extras/objectchange.html +1 -1
- nautobot/extras/templates/extras/plugin_detail.html +33 -16
- nautobot/extras/templates/extras/plugins_tiles.html +21 -10
- nautobot/extras/templates/extras/relationship.html +1 -63
- nautobot/extras/templates/extras/role_retrieve.html +1 -1
- nautobot/extras/templates/extras/scheduledjob.html +1 -1
- nautobot/extras/templates/extras/secret.html +1 -1
- nautobot/extras/templates/extras/secretsgroup.html +1 -1
- nautobot/extras/templates/extras/status.html +1 -1
- nautobot/extras/templates/extras/tag.html +1 -1
- nautobot/extras/templates/extras/webhook.html +1 -1
- nautobot/extras/templatetags/job_buttons.py +4 -4
- nautobot/extras/test_jobs/api_test_job.py +1 -1
- nautobot/extras/test_jobs/atomic_transaction.py +2 -2
- nautobot/extras/test_jobs/dry_run.py +1 -1
- nautobot/extras/test_jobs/fail.py +5 -5
- nautobot/extras/test_jobs/file_output.py +1 -1
- nautobot/extras/test_jobs/file_upload_fail.py +1 -1
- nautobot/extras/test_jobs/file_upload_pass.py +1 -1
- nautobot/extras/test_jobs/ipaddress_vars.py +3 -1
- nautobot/extras/test_jobs/jobs_module/jobs_submodule/jobs.py +1 -1
- nautobot/extras/test_jobs/location_with_custom_field.py +1 -1
- nautobot/extras/test_jobs/log_redaction.py +1 -1
- nautobot/extras/test_jobs/log_skip_db_logging.py +1 -1
- nautobot/extras/test_jobs/modify_db.py +1 -1
- nautobot/extras/test_jobs/object_var_optional.py +1 -1
- nautobot/extras/test_jobs/object_var_required.py +1 -1
- nautobot/extras/test_jobs/object_vars.py +1 -1
- nautobot/extras/test_jobs/pass.py +3 -3
- nautobot/extras/test_jobs/profiling.py +1 -1
- nautobot/extras/test_jobs/relative_import.py +3 -3
- nautobot/extras/test_jobs/singleton.py +16 -0
- nautobot/extras/test_jobs/soft_time_limit_greater_than_time_limit.py +1 -1
- nautobot/extras/test_jobs/task_queues.py +1 -1
- nautobot/extras/tests/git_data/01-valid-files/graphql_queries/device_interfaces.gql +8 -0
- nautobot/extras/tests/git_data/01-valid-files/graphql_queries/device_names.gql +5 -0
- nautobot/extras/tests/git_data/02-invalid-files/graphql_queries/bad_device_names.gql +5 -0
- nautobot/extras/tests/git_helper.py +9 -1
- nautobot/extras/tests/integration/__init__.py +29 -16
- nautobot/extras/tests/integration/test_plugin_banner.py +0 -2
- nautobot/extras/tests/test_api.py +19 -13
- nautobot/extras/tests/test_customfields.py +50 -52
- nautobot/extras/tests/test_datasources.py +29 -1
- nautobot/extras/tests/test_dynamicgroups.py +1 -1
- nautobot/extras/tests/test_filters.py +6 -6
- nautobot/extras/tests/test_forms.py +33 -1
- nautobot/extras/tests/test_jobs.py +178 -32
- nautobot/extras/tests/test_models.py +299 -10
- nautobot/extras/tests/test_plugins.py +62 -9
- nautobot/extras/tests/test_relationships.py +120 -9
- nautobot/extras/tests/test_utils.py +22 -1
- nautobot/extras/tests/test_views.py +56 -194
- nautobot/extras/utils.py +20 -10
- nautobot/extras/views.py +85 -110
- nautobot/ipam/api/fields.py +3 -3
- nautobot/ipam/api/serializers.py +41 -33
- nautobot/ipam/api/views.py +68 -117
- nautobot/ipam/factory.py +1 -1
- nautobot/ipam/filters.py +3 -2
- nautobot/ipam/lookups.py +101 -62
- nautobot/ipam/models.py +74 -18
- nautobot/ipam/querysets.py +2 -2
- nautobot/ipam/tables.py +25 -9
- nautobot/ipam/templates/ipam/ipaddress.html +2 -10
- 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 +2 -10
- nautobot/ipam/templates/ipam/prefix_edit.html +1 -7
- nautobot/ipam/templates/ipam/rir.html +1 -1
- nautobot/ipam/templates/ipam/routetarget.html +1 -1
- nautobot/ipam/templates/ipam/service.html +1 -1
- nautobot/ipam/templates/ipam/vlan.html +2 -10
- nautobot/ipam/templates/ipam/vlan_edit.html +1 -7
- nautobot/ipam/templates/ipam/vlangroup.html +1 -1
- nautobot/ipam/templates/ipam/vrf.html +1 -1
- nautobot/ipam/templates/ipam/vrf_edit.html +1 -7
- nautobot/ipam/tests/test_api.py +436 -3
- nautobot/ipam/tests/test_forms.py +49 -47
- nautobot/ipam/tests/test_migrations.py +30 -30
- nautobot/ipam/tests/test_models.py +119 -34
- nautobot/ipam/tests/test_querysets.py +63 -1
- nautobot/ipam/tests/test_utils.py +41 -2
- nautobot/ipam/tests/test_views.py +3 -0
- nautobot/ipam/utils/__init__.py +54 -17
- nautobot/ipam/views.py +61 -87
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.css.map +1 -1
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.min.css.map +1 -1
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css +40 -2
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css.map +1 -1
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css +1 -1
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css.map +1 -1
- nautobot/project-static/docs/404.html +131 -14
- nautobot/project-static/docs/apps/index.html +131 -14
- nautobot/project-static/docs/apps/nautobot-apps.html +132 -16
- nautobot/project-static/docs/assets/_mkdocstrings.css +25 -1
- nautobot/project-static/docs/assets/javascripts/{bundle.83f73b43.min.js → bundle.60a45f97.min.js} +2 -2
- nautobot/project-static/docs/assets/javascripts/{bundle.83f73b43.min.js.map → bundle.60a45f97.min.js.map} +2 -2
- nautobot/project-static/docs/assets/javascripts/workers/{search.6ce7567c.min.js → search.f8cc74c7.min.js} +1 -1
- nautobot/project-static/docs/assets/javascripts/workers/{search.6ce7567c.min.js.map → search.f8cc74c7.min.js.map} +1 -1
- nautobot/project-static/docs/assets/stylesheets/{main.6f8fc17f.min.css → main.a40c8224.min.css} +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +147 -20
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +144 -17
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +459 -132
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +175 -28
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +180 -31
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +138 -16
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +137 -15
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +164 -27
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +187 -38
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +193 -31
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +216 -48
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +324 -75
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +666 -175
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +194 -46
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +538 -177
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +578 -221
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +145 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +156 -25
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +492 -65
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +705 -215
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +943 -422
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +144 -17
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +619 -200
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +474 -159
- nautobot/project-static/docs/development/apps/api/configuration-view.html +131 -14
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +131 -14
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +131 -14
- nautobot/project-static/docs/development/apps/api/models/global-search.html +131 -14
- nautobot/project-static/docs/development/apps/api/models/graphql.html +131 -14
- nautobot/project-static/docs/development/apps/api/models/index.html +131 -14
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +131 -14
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +131 -14
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +131 -14
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +131 -14
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +131 -14
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +131 -14
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +131 -14
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +131 -14
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +131 -14
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +153 -17
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +131 -14
- nautobot/project-static/docs/development/apps/api/prometheus.html +131 -14
- nautobot/project-static/docs/development/apps/api/setup.html +131 -14
- nautobot/project-static/docs/development/apps/api/testing.html +131 -14
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +131 -14
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +131 -14
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +131 -14
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +131 -14
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +131 -14
- nautobot/project-static/docs/development/apps/api/views/base-template.html +131 -14
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +131 -14
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +131 -14
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +131 -14
- nautobot/project-static/docs/development/apps/api/views/index.html +131 -14
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +131 -14
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +131 -14
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +131 -14
- nautobot/project-static/docs/development/apps/api/views/notes.html +131 -14
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +137 -16
- nautobot/project-static/docs/development/apps/api/views/urls.html +131 -14
- nautobot/project-static/docs/development/apps/index.html +131 -14
- nautobot/project-static/docs/development/apps/migration/code-updates.html +131 -14
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +131 -14
- nautobot/project-static/docs/development/apps/migration/from-v1.html +131 -14
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +131 -14
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +131 -14
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +131 -14
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +131 -14
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +135 -18
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +131 -14
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +297 -25
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +131 -14
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +131 -14
- nautobot/project-static/docs/development/core/application-registry.html +131 -14
- nautobot/project-static/docs/development/core/best-practices.html +131 -14
- nautobot/project-static/docs/development/core/bootstrap-ui.html +131 -14
- nautobot/project-static/docs/development/core/caching.html +131 -14
- nautobot/project-static/docs/development/core/controllers.html +131 -14
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +158 -84
- nautobot/project-static/docs/development/core/generic-views.html +131 -14
- nautobot/project-static/docs/development/core/getting-started.html +334 -234
- nautobot/project-static/docs/development/core/homepage.html +134 -17
- nautobot/project-static/docs/development/core/index.html +131 -14
- nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +9829 -0
- nautobot/project-static/docs/development/core/model-checklist.html +141 -22
- nautobot/project-static/docs/development/core/model-features.html +131 -14
- nautobot/project-static/docs/development/core/natural-keys.html +131 -14
- nautobot/project-static/docs/development/core/navigation-menu.html +131 -14
- nautobot/project-static/docs/development/core/release-checklist.html +134 -17
- nautobot/project-static/docs/development/core/role-internals.html +131 -14
- nautobot/project-static/docs/development/core/settings.html +131 -14
- nautobot/project-static/docs/development/core/style-guide.html +134 -17
- nautobot/project-static/docs/development/core/templates.html +132 -15
- nautobot/project-static/docs/development/core/testing.html +131 -14
- nautobot/project-static/docs/development/core/ui-component-framework.html +454 -283
- nautobot/project-static/docs/development/core/user-preferences.html +131 -14
- nautobot/project-static/docs/development/index.html +131 -14
- nautobot/project-static/docs/development/jobs/index.html +301 -132
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +131 -14
- nautobot/project-static/docs/index.html +139 -33
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_edit.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_edit_button.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_list_nav.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_list_view.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue_add.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue_config.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_completed.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_nav.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_pending.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_run_form.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_nautobot_login.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_run_job.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_run_scheduled_job_form.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_scheduled_job_result.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/buttons-example.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/cluster-type-before-after-example.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/object-fields-panel-example_2.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/stats-panel-example-code.png +0 -0
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +132 -17
- nautobot/project-static/docs/overview/design_philosophy.html +131 -14
- nautobot/project-static/docs/release-notes/index.html +137 -22
- nautobot/project-static/docs/release-notes/version-1.0.html +319 -203
- nautobot/project-static/docs/release-notes/version-1.1.html +316 -200
- nautobot/project-static/docs/release-notes/version-1.2.html +391 -275
- nautobot/project-static/docs/release-notes/version-1.3.html +417 -301
- nautobot/project-static/docs/release-notes/version-1.4.html +502 -387
- nautobot/project-static/docs/release-notes/version-1.5.html +690 -576
- nautobot/project-static/docs/release-notes/version-1.6.html +989 -457
- nautobot/project-static/docs/release-notes/version-2.0.html +613 -499
- nautobot/project-static/docs/release-notes/version-2.1.html +448 -334
- nautobot/project-static/docs/release-notes/version-2.2.html +441 -327
- nautobot/project-static/docs/release-notes/version-2.3.html +1171 -451
- nautobot/project-static/docs/release-notes/version-2.4.html +800 -111
- nautobot/project-static/docs/requirements.txt +2 -2
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +303 -287
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +131 -14
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +131 -14
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +133 -16
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +131 -14
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +131 -14
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +195 -18
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +131 -14
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +134 -17
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +131 -14
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +131 -14
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +131 -14
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +131 -14
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +131 -14
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +131 -14
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +133 -16
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +131 -14
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +131 -14
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +131 -14
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +151 -18
- nautobot/project-static/docs/user-guide/administration/installation/index.html +131 -14
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +132 -15
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +131 -14
- nautobot/project-static/docs/user-guide/administration/installation/services.html +131 -14
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +131 -14
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +131 -14
- nautobot/project-static/docs/user-guide/administration/security/index.html +9420 -0
- nautobot/project-static/docs/user-guide/administration/security/notices.html +9843 -0
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +131 -14
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +131 -14
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +131 -14
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +131 -14
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +131 -14
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +131 -14
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +131 -14
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +134 -18
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +131 -14
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +131 -14
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +135 -22
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +134 -17
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +134 -17
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +236 -34
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +131 -14
- 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 +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +134 -17
- nautobot/project-static/docs/{development/core/local-k8s.html → user-guide/feature-guides/wireless-networks-and-controllers.html} +632 -566
- nautobot/project-static/docs/user-guide/index.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +135 -18
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +451 -16
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +135 -17
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +134 -17
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +9797 -0
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +132 -15
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +179 -35
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +159 -15
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +131 -14
- nautobot/project-static/js/forms.js +1 -1
- nautobot/tenancy/api/views.py +9 -13
- nautobot/tenancy/templates/tenancy/tenant.html +1 -2
- nautobot/tenancy/templates/tenancy/tenantgroup.html +1 -1
- nautobot/tenancy/views.py +4 -2
- nautobot/users/admin.py +1 -1
- nautobot/users/api/serializers.py +5 -4
- nautobot/users/api/views.py +3 -3
- nautobot/virtualization/api/serializers.py +4 -4
- nautobot/virtualization/api/views.py +5 -24
- nautobot/virtualization/filters.py +20 -3
- nautobot/virtualization/models.py +1 -1
- nautobot/virtualization/tables.py +2 -2
- nautobot/virtualization/templates/virtualization/cluster.html +1 -1
- nautobot/virtualization/templates/virtualization/cluster_edit.html +1 -7
- nautobot/virtualization/templates/virtualization/clustergroup.html +1 -1
- nautobot/virtualization/templates/virtualization/clustertype.html +1 -1
- nautobot/virtualization/templates/virtualization/virtualmachine.html +2 -10
- nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +2 -8
- nautobot/virtualization/templates/virtualization/vminterface.html +1 -1
- nautobot/virtualization/tests/test_filters.py +17 -0
- nautobot/wireless/filters.py +2 -2
- nautobot/wireless/forms.py +1 -1
- nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +1 -9
- nautobot/wireless/tests/integration/__init__.py +0 -0
- nautobot/wireless/tests/integration/test_radio_profile.py +42 -0
- nautobot/wireless/tests/test_filters.py +29 -1
- nautobot/wireless/tests/test_views.py +22 -1
- nautobot/wireless/views.py +0 -10
- {nautobot-2.4.0b1.dist-info → nautobot-2.4.2.dist-info}/METADATA +9 -9
- {nautobot-2.4.0b1.dist-info → nautobot-2.4.2.dist-info}/RECORD +667 -610
- {nautobot-2.4.0b1.dist-info → nautobot-2.4.2.dist-info}/WHEEL +1 -1
- nautobot/core/fixtures/user-data.json +0 -59
- /nautobot/project-static/docs/assets/stylesheets/{main.6f8fc17f.min.css.map → main.a40c8224.min.css.map} +0 -0
- {nautobot-2.4.0b1.dist-info → nautobot-2.4.2.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.4.0b1.dist-info → nautobot-2.4.2.dist-info}/NOTICE +0 -0
- {nautobot-2.4.0b1.dist-info → nautobot-2.4.2.dist-info}/entry_points.txt +0 -0
nautobot/extras/utils.py
CHANGED
|
@@ -6,6 +6,7 @@ import hmac
|
|
|
6
6
|
import logging
|
|
7
7
|
import re
|
|
8
8
|
import sys
|
|
9
|
+
from typing import Optional
|
|
9
10
|
|
|
10
11
|
from django.apps import apps
|
|
11
12
|
from django.conf import settings
|
|
@@ -13,7 +14,7 @@ from django.contrib.contenttypes.models import ContentType
|
|
|
13
14
|
from django.core.cache import cache
|
|
14
15
|
from django.core.validators import ValidationError
|
|
15
16
|
from django.db import transaction
|
|
16
|
-
from django.db.models import Q
|
|
17
|
+
from django.db.models import Model, Q
|
|
17
18
|
from django.template.loader import get_template, TemplateDoesNotExist
|
|
18
19
|
from django.utils.deconstruct import deconstructible
|
|
19
20
|
import kubernetes.client
|
|
@@ -36,16 +37,24 @@ from nautobot.extras.registry import registry
|
|
|
36
37
|
logger = logging.getLogger(__name__)
|
|
37
38
|
|
|
38
39
|
|
|
39
|
-
def get_base_template(base_template, model):
|
|
40
|
+
def get_base_template(base_template: Optional[str], model: type[Model]) -> str:
|
|
40
41
|
"""
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
Attempt to locate the correct base template for an object detail view and related views, if one was not specified.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
base_template (str, optional): If not None, this explicitly specified template will be preferred.
|
|
46
|
+
model (Model): The model to identify a base template for, if base_template is None.
|
|
47
|
+
|
|
48
|
+
Returns the specified `base_template`, if not `None`.
|
|
49
|
+
Otherwise, if `"<app>/<model_name>.html"` exists (legacy ObjectView pattern), returns that string.
|
|
50
|
+
Otherwise, if `"<app>/<model_name>_retrieve.html"` exists (as used in `NautobotUIViewSet`), returns that string.
|
|
51
|
+
If all else fails, returns `"generic/object_retrieve.html"`.
|
|
52
|
+
|
|
53
|
+
Note: before Nautobot 2.4.2, this API would default to "base.html" rather than "generic/object_retrieve.html".
|
|
54
|
+
This behavior was changed to the current behavior to address issue #6550 and similar incorrect behavior.
|
|
45
55
|
"""
|
|
46
56
|
if base_template is None:
|
|
47
57
|
base_template = f"{model._meta.app_label}/{model._meta.model_name}.html"
|
|
48
|
-
# 2.0 TODO(Hanlin): This can be removed once an object view has been established for every model.
|
|
49
58
|
try:
|
|
50
59
|
get_template(base_template)
|
|
51
60
|
except TemplateDoesNotExist:
|
|
@@ -53,7 +62,7 @@ def get_base_template(base_template, model):
|
|
|
53
62
|
try:
|
|
54
63
|
get_template(base_template)
|
|
55
64
|
except TemplateDoesNotExist:
|
|
56
|
-
base_template = "
|
|
65
|
+
base_template = "generic/object_retrieve.html"
|
|
57
66
|
return base_template
|
|
58
67
|
|
|
59
68
|
|
|
@@ -579,6 +588,7 @@ def refresh_job_model_from_job_class(job_model_class, job_class, job_queue_class
|
|
|
579
588
|
"installed": True,
|
|
580
589
|
"enabled": False,
|
|
581
590
|
"default_job_queue": default_job_queue,
|
|
591
|
+
"is_singleton": job_class.is_singleton,
|
|
582
592
|
},
|
|
583
593
|
)
|
|
584
594
|
|
|
@@ -665,9 +675,9 @@ def run_kubernetes_job_and_return_job_result(job_queue, job_result, job_kwargs):
|
|
|
665
675
|
"runjob_with_job_result",
|
|
666
676
|
f"{job_result.pk}",
|
|
667
677
|
]
|
|
668
|
-
|
|
678
|
+
job_result.log(f"Creating job pod {pod_name} in namespace {pod_namespace}")
|
|
669
679
|
api_instance.create_namespaced_job(body=pod_manifest, namespace=pod_namespace)
|
|
670
|
-
|
|
680
|
+
job_result.log(f"Reading job pod {pod_name} in namespace {pod_namespace}")
|
|
671
681
|
api_instance.read_namespaced_job(name="nautobot-job-" + str(job_result.pk), namespace=pod_namespace)
|
|
672
682
|
return job_result
|
|
673
683
|
|
nautobot/extras/views.py
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
from typing import Optional
|
|
2
3
|
from urllib.parse import parse_qs
|
|
3
4
|
|
|
4
|
-
from celery import chain
|
|
5
|
-
from django.conf import settings
|
|
6
5
|
from django.contrib import messages
|
|
7
6
|
from django.contrib.contenttypes.models import ContentType
|
|
8
7
|
from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
|
@@ -33,6 +32,7 @@ from nautobot.core.models.utils import pretty_print_query, serialize_object_v2
|
|
|
33
32
|
from nautobot.core.tables import ButtonsColumn
|
|
34
33
|
from nautobot.core.ui import object_detail
|
|
35
34
|
from nautobot.core.ui.choices import SectionChoices
|
|
35
|
+
from nautobot.core.ui.object_detail import ObjectDetailContent, ObjectFieldsPanel
|
|
36
36
|
from nautobot.core.utils.config import get_settings_or_config
|
|
37
37
|
from nautobot.core.utils.lookup import (
|
|
38
38
|
get_filterset_for_model,
|
|
@@ -68,10 +68,7 @@ from nautobot.dcim.tables import (
|
|
|
68
68
|
RackTable,
|
|
69
69
|
VirtualDeviceContextTable,
|
|
70
70
|
)
|
|
71
|
-
from nautobot.extras.constants import JOB_OVERRIDABLE_FIELDS
|
|
72
71
|
from nautobot.extras.context_managers import deferred_change_logging_for_bulk_operation
|
|
73
|
-
from nautobot.extras.signals import change_context_state
|
|
74
|
-
from nautobot.extras.tasks import delete_custom_field_data
|
|
75
72
|
from nautobot.extras.utils import get_base_template, get_job_queue, get_worker_count
|
|
76
73
|
from nautobot.ipam.models import IPAddress, Prefix, VLAN
|
|
77
74
|
from nautobot.ipam.tables import IPAddressTable, PrefixTable, VLANTable
|
|
@@ -659,37 +656,7 @@ class CustomFieldBulkDeleteView(generic.BulkDeleteView):
|
|
|
659
656
|
queryset = CustomField.objects.all()
|
|
660
657
|
table = tables.CustomFieldTable
|
|
661
658
|
filterset = filters.CustomFieldFilterSet
|
|
662
|
-
|
|
663
|
-
def construct_custom_field_delete_tasks(self, queryset):
|
|
664
|
-
"""
|
|
665
|
-
Helper method to construct a list of celery tasks to execute when bulk deleting custom fields.
|
|
666
|
-
"""
|
|
667
|
-
change_context = change_context_state.get()
|
|
668
|
-
if change_context is None:
|
|
669
|
-
context = None
|
|
670
|
-
else:
|
|
671
|
-
context = change_context.as_dict(queryset)
|
|
672
|
-
context["context_detail"] = "bulk delete custom field data"
|
|
673
|
-
tasks = [
|
|
674
|
-
delete_custom_field_data.si(obj.key, set(obj.content_types.values_list("pk", flat=True)), context)
|
|
675
|
-
for obj in queryset
|
|
676
|
-
]
|
|
677
|
-
return tasks
|
|
678
|
-
|
|
679
|
-
def perform_pre_delete(self, request, queryset):
|
|
680
|
-
"""
|
|
681
|
-
Remove all Custom Field Keys/Values from _custom_field_data of the related ContentType in the background.
|
|
682
|
-
"""
|
|
683
|
-
if not get_worker_count():
|
|
684
|
-
messages.error(
|
|
685
|
-
request, "Celery worker process not running. Object custom fields may fail to reflect this deletion."
|
|
686
|
-
)
|
|
687
|
-
return
|
|
688
|
-
tasks = self.construct_custom_field_delete_tasks(queryset)
|
|
689
|
-
# Executing the tasks in the background sequentially using chain() aligns with how a single
|
|
690
|
-
# CustomField object is deleted. We decided to not check the result because it needs at least one worker
|
|
691
|
-
# to be active and comes with extra performance penalty.
|
|
692
|
-
chain(*tasks).apply_async()
|
|
659
|
+
form = forms.CustomFieldBulkDeleteForm
|
|
693
660
|
|
|
694
661
|
|
|
695
662
|
#
|
|
@@ -935,10 +902,13 @@ class DynamicGroupBulkDeleteView(generic.BulkDeleteView):
|
|
|
935
902
|
class ObjectDynamicGroupsView(generic.GenericView):
|
|
936
903
|
"""
|
|
937
904
|
Present a list of dynamic groups associated to a particular object.
|
|
938
|
-
|
|
905
|
+
|
|
906
|
+
base_template: Specify to explicitly identify the base object detail template to render.
|
|
907
|
+
If not provided, "<app>/<model>.html", "<app>/<model>_retrieve.html", or "generic/object_retrieve.html"
|
|
908
|
+
will be used, as per `get_base_template()`.
|
|
939
909
|
"""
|
|
940
910
|
|
|
941
|
-
base_template = None
|
|
911
|
+
base_template: Optional[str] = None
|
|
942
912
|
|
|
943
913
|
def get(self, request, model, **kwargs):
|
|
944
914
|
# Handle QuerySet restriction of parent object if needed
|
|
@@ -961,7 +931,7 @@ class ObjectDynamicGroupsView(generic.GenericView):
|
|
|
961
931
|
}
|
|
962
932
|
RequestConfig(request, paginate).configure(dynamicgroups_table)
|
|
963
933
|
|
|
964
|
-
|
|
934
|
+
base_template = get_base_template(self.base_template, model)
|
|
965
935
|
|
|
966
936
|
return render(
|
|
967
937
|
request,
|
|
@@ -971,7 +941,7 @@ class ObjectDynamicGroupsView(generic.GenericView):
|
|
|
971
941
|
"verbose_name": obj._meta.verbose_name,
|
|
972
942
|
"verbose_name_plural": obj._meta.verbose_name_plural,
|
|
973
943
|
"table": dynamicgroups_table,
|
|
974
|
-
"base_template":
|
|
944
|
+
"base_template": base_template,
|
|
975
945
|
"active_tab": "dynamic-groups",
|
|
976
946
|
},
|
|
977
947
|
)
|
|
@@ -1097,10 +1067,10 @@ class GitRepositoryEditView(generic.ObjectEditView):
|
|
|
1097
1067
|
obj.user = request.user
|
|
1098
1068
|
return super().alter_obj(obj, request, url_args, url_kwargs)
|
|
1099
1069
|
|
|
1100
|
-
def get_return_url(self, request, obj):
|
|
1070
|
+
def get_return_url(self, request, obj=None, default_return_url=None):
|
|
1101
1071
|
if request.method == "POST":
|
|
1102
1072
|
return reverse("extras:gitrepository_result", kwargs={"pk": obj.pk})
|
|
1103
|
-
return super().get_return_url(request, obj)
|
|
1073
|
+
return super().get_return_url(request, obj=obj, default_return_url=default_return_url)
|
|
1104
1074
|
|
|
1105
1075
|
|
|
1106
1076
|
class GitRepositoryDeleteView(generic.ObjectDeleteView):
|
|
@@ -1248,27 +1218,27 @@ class ImageAttachmentEditView(generic.ObjectEditView):
|
|
|
1248
1218
|
return get_object_or_404(self.queryset, pk=kwargs["pk"])
|
|
1249
1219
|
return self.queryset.model()
|
|
1250
1220
|
|
|
1251
|
-
def alter_obj(self,
|
|
1252
|
-
if not
|
|
1221
|
+
def alter_obj(self, obj, request, url_args, url_kwargs):
|
|
1222
|
+
if not obj.present_in_database:
|
|
1253
1223
|
# Assign the parent object based on URL kwargs
|
|
1254
|
-
model =
|
|
1255
|
-
if "object_id" in
|
|
1256
|
-
|
|
1257
|
-
elif "slug" in
|
|
1258
|
-
|
|
1224
|
+
model = url_kwargs.get("model")
|
|
1225
|
+
if "object_id" in url_kwargs:
|
|
1226
|
+
obj.parent = get_object_or_404(model, pk=url_kwargs["object_id"])
|
|
1227
|
+
elif "slug" in url_kwargs:
|
|
1228
|
+
obj.parent = get_object_or_404(model, slug=url_kwargs["slug"])
|
|
1259
1229
|
else:
|
|
1260
1230
|
raise RuntimeError("Neither object_id nor slug were provided?")
|
|
1261
|
-
return
|
|
1231
|
+
return obj
|
|
1262
1232
|
|
|
1263
|
-
def get_return_url(self, request,
|
|
1264
|
-
return
|
|
1233
|
+
def get_return_url(self, request, obj=None, default_return_url=None):
|
|
1234
|
+
return obj.parent.get_absolute_url()
|
|
1265
1235
|
|
|
1266
1236
|
|
|
1267
1237
|
class ImageAttachmentDeleteView(generic.ObjectDeleteView):
|
|
1268
1238
|
queryset = ImageAttachment.objects.all()
|
|
1269
1239
|
|
|
1270
|
-
def get_return_url(self, request,
|
|
1271
|
-
return
|
|
1240
|
+
def get_return_url(self, request, obj=None, default_return_url=None):
|
|
1241
|
+
return obj.parent.get_absolute_url()
|
|
1272
1242
|
|
|
1273
1243
|
|
|
1274
1244
|
#
|
|
@@ -1365,6 +1335,9 @@ class JobRunView(ObjectPermissionRequiredMixin, View):
|
|
|
1365
1335
|
pass
|
|
1366
1336
|
initial["_job_queue"] = jq
|
|
1367
1337
|
initial["_profile"] = job_result.celery_kwargs.get("nautobot_job_profile", False)
|
|
1338
|
+
initial["_ignore_singleton_lock"] = job_result.celery_kwargs.get(
|
|
1339
|
+
"nautobot_job_ignore_singleton_lock", False
|
|
1340
|
+
)
|
|
1368
1341
|
initial.update(explicit_initial)
|
|
1369
1342
|
except JobResult.DoesNotExist:
|
|
1370
1343
|
messages.warning(
|
|
@@ -1379,7 +1352,9 @@ class JobRunView(ObjectPermissionRequiredMixin, View):
|
|
|
1379
1352
|
get_template(job_class.template_name)
|
|
1380
1353
|
template_name = job_class.template_name
|
|
1381
1354
|
except TemplateDoesNotExist as err:
|
|
1382
|
-
messages.error(
|
|
1355
|
+
messages.error(
|
|
1356
|
+
request, f'Unable to render requested custom job template "{job_class.template_name}": {err}'
|
|
1357
|
+
)
|
|
1383
1358
|
except RuntimeError as err:
|
|
1384
1359
|
messages.error(request, f"Unable to run or schedule '{job_model}': {err}")
|
|
1385
1360
|
return redirect("extras:job_list")
|
|
@@ -1447,6 +1422,7 @@ class JobRunView(ObjectPermissionRequiredMixin, View):
|
|
|
1447
1422
|
dryrun = job_form.cleaned_data.get("dryrun", False)
|
|
1448
1423
|
# Run the job. A new JobResult is created.
|
|
1449
1424
|
profile = job_form.cleaned_data.pop("_profile")
|
|
1425
|
+
ignore_singleton_lock = job_form.cleaned_data.pop("_ignore_singleton_lock", False)
|
|
1450
1426
|
schedule_type = schedule_form.cleaned_data["_schedule_type"]
|
|
1451
1427
|
|
|
1452
1428
|
if (not dryrun and job_model.approval_required) or schedule_type in JobExecutionType.SCHEDULE_CHOICES:
|
|
@@ -1460,6 +1436,7 @@ class JobRunView(ObjectPermissionRequiredMixin, View):
|
|
|
1460
1436
|
approval_required=job_model.approval_required,
|
|
1461
1437
|
task_queue=jq.name if jq else None,
|
|
1462
1438
|
profile=profile,
|
|
1439
|
+
ignore_singleton_lock=ignore_singleton_lock,
|
|
1463
1440
|
**job_class.serialize_data(job_form.cleaned_data),
|
|
1464
1441
|
)
|
|
1465
1442
|
|
|
@@ -1477,6 +1454,7 @@ class JobRunView(ObjectPermissionRequiredMixin, View):
|
|
|
1477
1454
|
job_model,
|
|
1478
1455
|
request.user,
|
|
1479
1456
|
profile=profile,
|
|
1457
|
+
ignore_singleton_lock=ignore_singleton_lock,
|
|
1480
1458
|
task_queue=jq.name if jq else None,
|
|
1481
1459
|
**job_class.serialize_data(job_kwargs),
|
|
1482
1460
|
)
|
|
@@ -1502,7 +1480,9 @@ class JobRunView(ObjectPermissionRequiredMixin, View):
|
|
|
1502
1480
|
get_template(job_class.template_name)
|
|
1503
1481
|
template_name = job_class.template_name
|
|
1504
1482
|
except TemplateDoesNotExist as err:
|
|
1505
|
-
messages.error(
|
|
1483
|
+
messages.error(
|
|
1484
|
+
request, f'Unable to render requested custom job template "{job_class.template_name}": {err}'
|
|
1485
|
+
)
|
|
1506
1486
|
|
|
1507
1487
|
return render(
|
|
1508
1488
|
request,
|
|
@@ -1533,52 +1513,6 @@ class JobBulkEditView(generic.BulkEditView):
|
|
|
1533
1513
|
form = forms.JobBulkEditForm
|
|
1534
1514
|
template_name = "extras/job_bulk_edit.html"
|
|
1535
1515
|
|
|
1536
|
-
def extra_post_save_action(self, obj, form):
|
|
1537
|
-
cleaned_data = form.cleaned_data
|
|
1538
|
-
|
|
1539
|
-
# Handle text related fields
|
|
1540
|
-
for overridable_field in JOB_OVERRIDABLE_FIELDS:
|
|
1541
|
-
override_field = overridable_field + "_override"
|
|
1542
|
-
clear_override_field = "clear_" + overridable_field + "_override"
|
|
1543
|
-
reset_override = cleaned_data.get(clear_override_field, False)
|
|
1544
|
-
override_value = cleaned_data.get(overridable_field)
|
|
1545
|
-
if reset_override:
|
|
1546
|
-
setattr(obj, override_field, False)
|
|
1547
|
-
elif not reset_override and override_value not in [None, ""]:
|
|
1548
|
-
setattr(obj, override_field, True)
|
|
1549
|
-
setattr(obj, overridable_field, override_value)
|
|
1550
|
-
|
|
1551
|
-
# Handle job queues
|
|
1552
|
-
clear_override_field = "clear_job_queues_override"
|
|
1553
|
-
reset_override = cleaned_data.get(clear_override_field, False)
|
|
1554
|
-
if reset_override:
|
|
1555
|
-
meta_task_queues = obj.job_class.task_queues
|
|
1556
|
-
job_queues = []
|
|
1557
|
-
for queue_name in meta_task_queues:
|
|
1558
|
-
try:
|
|
1559
|
-
job_queues.append(JobQueue.objects.get(name=queue_name))
|
|
1560
|
-
except JobQueue.DoesNotExist:
|
|
1561
|
-
# Do we want to create the Job Queue for the users here if we do not have it in the database?
|
|
1562
|
-
pass
|
|
1563
|
-
obj.job_queues_override = False
|
|
1564
|
-
obj.job_queues.set(job_queues)
|
|
1565
|
-
elif cleaned_data["job_queues"]:
|
|
1566
|
-
obj.job_queues_override = True
|
|
1567
|
-
|
|
1568
|
-
# Handle default job queue
|
|
1569
|
-
clear_override_field = "clear_default_job_queue_override"
|
|
1570
|
-
reset_override = cleaned_data.get(clear_override_field, False)
|
|
1571
|
-
if reset_override:
|
|
1572
|
-
meta_task_queues = obj.job_class.task_queues
|
|
1573
|
-
obj.default_job_queue_override = False
|
|
1574
|
-
obj.default_job_queue, _ = JobQueue.objects.get_or_create(
|
|
1575
|
-
name=meta_task_queues[0] if meta_task_queues else settings.CELERY_TASK_DEFAULT_QUEUE
|
|
1576
|
-
)
|
|
1577
|
-
elif cleaned_data["default_job_queue"]:
|
|
1578
|
-
obj.default_job_queue_override = True
|
|
1579
|
-
|
|
1580
|
-
obj.validated_save()
|
|
1581
|
-
|
|
1582
1516
|
|
|
1583
1517
|
class JobDeleteView(generic.ObjectDeleteView):
|
|
1584
1518
|
queryset = JobModel.objects.all()
|
|
@@ -2098,6 +2032,9 @@ def get_annotated_jobresult_queryset():
|
|
|
2098
2032
|
debug_log_count=count_related(
|
|
2099
2033
|
JobLogEntry, "job_result", filter_dict={"log_level": LogLevelChoices.LOG_DEBUG}
|
|
2100
2034
|
),
|
|
2035
|
+
success_log_count=count_related(
|
|
2036
|
+
JobLogEntry, "job_result", filter_dict={"log_level": LogLevelChoices.LOG_SUCCESS}
|
|
2037
|
+
),
|
|
2101
2038
|
info_log_count=count_related(
|
|
2102
2039
|
JobLogEntry, "job_result", filter_dict={"log_level": LogLevelChoices.LOG_INFO}
|
|
2103
2040
|
),
|
|
@@ -2253,10 +2190,13 @@ class ObjectChangeView(generic.ObjectView):
|
|
|
2253
2190
|
class ObjectChangeLogView(generic.GenericView):
|
|
2254
2191
|
"""
|
|
2255
2192
|
Present a history of changes made to a particular object.
|
|
2256
|
-
|
|
2193
|
+
|
|
2194
|
+
base_template: Specify to explicitly identify the base object detail template to render.
|
|
2195
|
+
If not provided, "<app>/<model>.html", "<app>/<model>_retrieve.html", or "generic/object_retrieve.html"
|
|
2196
|
+
will be used, as per `get_base_template()`.
|
|
2257
2197
|
"""
|
|
2258
2198
|
|
|
2259
|
-
base_template = None
|
|
2199
|
+
base_template: Optional[str] = None
|
|
2260
2200
|
|
|
2261
2201
|
def get(self, request, model, **kwargs):
|
|
2262
2202
|
# Handle QuerySet restriction of parent object if needed
|
|
@@ -2284,7 +2224,7 @@ class ObjectChangeLogView(generic.GenericView):
|
|
|
2284
2224
|
}
|
|
2285
2225
|
RequestConfig(request, paginate).configure(objectchanges_table)
|
|
2286
2226
|
|
|
2287
|
-
|
|
2227
|
+
base_template = get_base_template(self.base_template, model)
|
|
2288
2228
|
|
|
2289
2229
|
return render(
|
|
2290
2230
|
request,
|
|
@@ -2294,7 +2234,7 @@ class ObjectChangeLogView(generic.GenericView):
|
|
|
2294
2234
|
"verbose_name": obj._meta.verbose_name,
|
|
2295
2235
|
"verbose_name_plural": obj._meta.verbose_name_plural,
|
|
2296
2236
|
"table": objectchanges_table,
|
|
2297
|
-
"base_template":
|
|
2237
|
+
"base_template": base_template,
|
|
2298
2238
|
"active_tab": "changelog",
|
|
2299
2239
|
},
|
|
2300
2240
|
)
|
|
@@ -2387,10 +2327,13 @@ class NoteDeleteView(generic.ObjectDeleteView):
|
|
|
2387
2327
|
class ObjectNotesView(generic.GenericView):
|
|
2388
2328
|
"""
|
|
2389
2329
|
Present a list of notes associated to a particular object.
|
|
2390
|
-
|
|
2330
|
+
|
|
2331
|
+
base_template: Specify to explicitly identify the base object detail template to render.
|
|
2332
|
+
If not provided, "<app>/<model>.html", "<app>/<model>_retrieve.html", or "generic/object_retrieve.html"
|
|
2333
|
+
will be used, as per `get_base_template()`.
|
|
2391
2334
|
"""
|
|
2392
2335
|
|
|
2393
|
-
base_template = None
|
|
2336
|
+
base_template: Optional[str] = None
|
|
2394
2337
|
|
|
2395
2338
|
def get(self, request, model, **kwargs):
|
|
2396
2339
|
# Handle QuerySet restriction of parent object if needed
|
|
@@ -2414,7 +2357,7 @@ class ObjectNotesView(generic.GenericView):
|
|
|
2414
2357
|
}
|
|
2415
2358
|
RequestConfig(request, paginate).configure(notes_table)
|
|
2416
2359
|
|
|
2417
|
-
|
|
2360
|
+
base_template = get_base_template(self.base_template, model)
|
|
2418
2361
|
|
|
2419
2362
|
return render(
|
|
2420
2363
|
request,
|
|
@@ -2424,7 +2367,7 @@ class ObjectNotesView(generic.GenericView):
|
|
|
2424
2367
|
"verbose_name": obj._meta.verbose_name,
|
|
2425
2368
|
"verbose_name_plural": obj._meta.verbose_name_plural,
|
|
2426
2369
|
"table": notes_table,
|
|
2427
|
-
"base_template":
|
|
2370
|
+
"base_template": base_template,
|
|
2428
2371
|
"active_tab": "notes",
|
|
2429
2372
|
"form": notes_form,
|
|
2430
2373
|
},
|
|
@@ -2446,6 +2389,38 @@ class RelationshipListView(generic.ObjectListView):
|
|
|
2446
2389
|
|
|
2447
2390
|
class RelationshipView(generic.ObjectView):
|
|
2448
2391
|
queryset = Relationship.objects.all()
|
|
2392
|
+
object_detail_content = ObjectDetailContent(
|
|
2393
|
+
panels=(
|
|
2394
|
+
ObjectFieldsPanel(
|
|
2395
|
+
label="Relationship",
|
|
2396
|
+
section=SectionChoices.LEFT_HALF,
|
|
2397
|
+
weight=100,
|
|
2398
|
+
fields="__all__",
|
|
2399
|
+
exclude_fields=[
|
|
2400
|
+
"source_type",
|
|
2401
|
+
"source_label",
|
|
2402
|
+
"source_hidden",
|
|
2403
|
+
"source_filter",
|
|
2404
|
+
"destination_type",
|
|
2405
|
+
"destination_label",
|
|
2406
|
+
"destination_hidden",
|
|
2407
|
+
"destination_filter",
|
|
2408
|
+
],
|
|
2409
|
+
),
|
|
2410
|
+
ObjectFieldsPanel(
|
|
2411
|
+
label="Source Attributes",
|
|
2412
|
+
section=SectionChoices.RIGHT_HALF,
|
|
2413
|
+
weight=100,
|
|
2414
|
+
fields=["source_type", "source_label", "source_hidden", "source_filter"],
|
|
2415
|
+
),
|
|
2416
|
+
ObjectFieldsPanel(
|
|
2417
|
+
label="Destination Attributes",
|
|
2418
|
+
section=SectionChoices.RIGHT_HALF,
|
|
2419
|
+
weight=200,
|
|
2420
|
+
fields=["destination_type", "destination_label", "destination_hidden", "destination_filter"],
|
|
2421
|
+
),
|
|
2422
|
+
)
|
|
2423
|
+
)
|
|
2449
2424
|
|
|
2450
2425
|
|
|
2451
2426
|
class RelationshipEditView(generic.ObjectEditView):
|
nautobot/ipam/api/fields.py
CHANGED
|
@@ -7,11 +7,11 @@ class IPFieldSerializer(serializers.CharField):
|
|
|
7
7
|
"""Convert internal (IPNetwork) representation to API (string) representation."""
|
|
8
8
|
return str(value)
|
|
9
9
|
|
|
10
|
-
def to_internal_value(self,
|
|
10
|
+
def to_internal_value(self, data):
|
|
11
11
|
"""Convert API (string) representation to internal (IPNetwork) representation."""
|
|
12
12
|
try:
|
|
13
|
-
return netaddr.IPNetwork(
|
|
13
|
+
return netaddr.IPNetwork(data)
|
|
14
14
|
except netaddr.AddrFormatError:
|
|
15
|
-
raise serializers.ValidationError(f"Invalid IP address format: {
|
|
15
|
+
raise serializers.ValidationError(f"Invalid IP address format: {data}")
|
|
16
16
|
except (TypeError, ValueError) as e:
|
|
17
17
|
raise serializers.ValidationError(e)
|
nautobot/ipam/api/serializers.py
CHANGED
|
@@ -62,16 +62,16 @@ class VRFDeviceAssignmentSerializer(ValidatedModelSerializer):
|
|
|
62
62
|
fields = "__all__"
|
|
63
63
|
validators = []
|
|
64
64
|
|
|
65
|
-
def validate(self,
|
|
66
|
-
if
|
|
65
|
+
def validate(self, attrs):
|
|
66
|
+
if attrs.get("device"):
|
|
67
67
|
validator = UniqueTogetherValidator(queryset=VRFDeviceAssignment.objects.all(), fields=("device", "vrf"))
|
|
68
|
-
validator(
|
|
69
|
-
if
|
|
68
|
+
validator(attrs, self)
|
|
69
|
+
if attrs.get("virtual_machine"):
|
|
70
70
|
validator = UniqueTogetherValidator(
|
|
71
71
|
queryset=VRFDeviceAssignment.objects.all(), fields=("virtual_machine", "vrf")
|
|
72
72
|
)
|
|
73
|
-
validator(
|
|
74
|
-
return super().validate(
|
|
73
|
+
validator(attrs, self)
|
|
74
|
+
return super().validate(attrs)
|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
class VRFPrefixAssignmentSerializer(ValidatedModelSerializer):
|
|
@@ -133,17 +133,17 @@ class VLANSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
|
|
|
133
133
|
validators = []
|
|
134
134
|
extra_kwargs = {"locations": {"read_only": True}}
|
|
135
135
|
|
|
136
|
-
def validate(self,
|
|
136
|
+
def validate(self, attrs):
|
|
137
137
|
# Validate uniqueness of vid and name if a group has been assigned.
|
|
138
|
-
if
|
|
138
|
+
if attrs.get("vlan_group", None):
|
|
139
139
|
for field in ["vid", "name"]:
|
|
140
140
|
validator = UniqueTogetherValidator(queryset=VLAN.objects.all(), fields=("vlan_group", field))
|
|
141
|
-
validator(
|
|
141
|
+
validator(attrs, self)
|
|
142
142
|
|
|
143
143
|
# Enforce model validation
|
|
144
|
-
super().validate(
|
|
144
|
+
super().validate(attrs)
|
|
145
145
|
|
|
146
|
-
return
|
|
146
|
+
return attrs
|
|
147
147
|
|
|
148
148
|
|
|
149
149
|
class VLANLegacySerializer(VLANSerializer):
|
|
@@ -205,6 +205,12 @@ class PrefixSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
|
|
|
205
205
|
write_only=True,
|
|
206
206
|
)
|
|
207
207
|
|
|
208
|
+
def get_field_names(self, declared_fields, info):
|
|
209
|
+
"""Add reverse M2M for VRF's to the fields for this serializer."""
|
|
210
|
+
field_names = list(super().get_field_names(declared_fields, info))
|
|
211
|
+
self.extend_field_names(field_names, "vrfs")
|
|
212
|
+
return field_names
|
|
213
|
+
|
|
208
214
|
class Meta:
|
|
209
215
|
model = Prefix
|
|
210
216
|
fields = "__all__"
|
|
@@ -213,6 +219,7 @@ class PrefixSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
|
|
|
213
219
|
"namespace": {"default": get_default_namespace},
|
|
214
220
|
"prefix_length": {"read_only": True},
|
|
215
221
|
"locations": {"read_only": True},
|
|
222
|
+
"vrfs": {"read_only": True},
|
|
216
223
|
}
|
|
217
224
|
|
|
218
225
|
|
|
@@ -320,16 +327,16 @@ class IPAddressSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
|
|
|
320
327
|
"parent": {"required": False},
|
|
321
328
|
}
|
|
322
329
|
|
|
323
|
-
def validate(self,
|
|
324
|
-
namespace =
|
|
325
|
-
parent =
|
|
330
|
+
def validate(self, attrs):
|
|
331
|
+
namespace = attrs.get("namespace", None)
|
|
332
|
+
parent = attrs.get("parent", None)
|
|
326
333
|
|
|
327
334
|
# Only assert namespace/parent on create.
|
|
328
335
|
if self.instance is None and not any([namespace, parent]):
|
|
329
336
|
raise ValidationError({"__all__": "One of parent or namespace must be provided"})
|
|
330
337
|
|
|
331
|
-
super().validate(
|
|
332
|
-
return
|
|
338
|
+
super().validate(attrs)
|
|
339
|
+
return attrs
|
|
333
340
|
|
|
334
341
|
def get_field_names(self, declared_fields, info):
|
|
335
342
|
"""Add reverse relations to the automatically discovered fields."""
|
|
@@ -379,9 +386,9 @@ class IPAllocationSerializer(NautobotModelSerializer, TaggedModelSerializerMixin
|
|
|
379
386
|
"custom_fields",
|
|
380
387
|
)
|
|
381
388
|
|
|
382
|
-
def validate(self,
|
|
383
|
-
|
|
384
|
-
return super().validate(
|
|
389
|
+
def validate(self, attrs):
|
|
390
|
+
attrs["mask_length"] = self.context["prefix"].prefix_length
|
|
391
|
+
return super().validate(attrs)
|
|
385
392
|
|
|
386
393
|
|
|
387
394
|
class VLANAllocationSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
|
|
@@ -391,12 +398,13 @@ class VLANAllocationSerializer(NautobotModelSerializer, TaggedModelSerializerMix
|
|
|
391
398
|
|
|
392
399
|
vid = serializers.IntegerField(required=False, min_value=constants.VLAN_VID_MIN, max_value=constants.VLAN_VID_MAX)
|
|
393
400
|
|
|
394
|
-
def validate(self,
|
|
401
|
+
def validate(self, attrs):
|
|
395
402
|
"""
|
|
396
403
|
Skip `ValidatedModel` validation.
|
|
404
|
+
|
|
397
405
|
This allows to skip `vid` attribute of `VLAN` model, while validate name and status.
|
|
398
406
|
"""
|
|
399
|
-
return
|
|
407
|
+
return attrs
|
|
400
408
|
|
|
401
409
|
class Meta(VLANSerializer.Meta):
|
|
402
410
|
model = VLAN
|
|
@@ -425,19 +433,19 @@ class IPAddressToInterfaceSerializer(ValidatedModelSerializer):
|
|
|
425
433
|
fields = "__all__"
|
|
426
434
|
validators = []
|
|
427
435
|
|
|
428
|
-
def validate(self,
|
|
436
|
+
def validate(self, attrs):
|
|
429
437
|
# Validate uniqueness of (parent, name) since we omitted the automatically created validator from Meta.
|
|
430
|
-
if
|
|
438
|
+
if attrs.get("interface"):
|
|
431
439
|
validator = UniqueTogetherValidator(
|
|
432
440
|
queryset=IPAddressToInterface.objects.all(), fields=("interface", "ip_address")
|
|
433
441
|
)
|
|
434
|
-
validator(
|
|
435
|
-
if
|
|
442
|
+
validator(attrs, self)
|
|
443
|
+
if attrs.get("vm_interface"):
|
|
436
444
|
validator = UniqueTogetherValidator(
|
|
437
445
|
queryset=IPAddressToInterface.objects.all(), fields=("vm_interface", "ip_address")
|
|
438
446
|
)
|
|
439
|
-
validator(
|
|
440
|
-
return super().validate(
|
|
447
|
+
validator(attrs, self)
|
|
448
|
+
return super().validate(attrs)
|
|
441
449
|
|
|
442
450
|
|
|
443
451
|
#
|
|
@@ -464,11 +472,11 @@ class ServiceSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
|
|
|
464
472
|
"virtual_machine": {"help_text": "Required if no device is specified"},
|
|
465
473
|
}
|
|
466
474
|
|
|
467
|
-
def validate(self,
|
|
468
|
-
if
|
|
475
|
+
def validate(self, attrs):
|
|
476
|
+
if attrs.get("device"):
|
|
469
477
|
validator = UniqueTogetherValidator(queryset=Service.objects.all(), fields=("name", "device"))
|
|
470
|
-
validator(
|
|
471
|
-
if
|
|
478
|
+
validator(attrs, self)
|
|
479
|
+
if attrs.get("virtual_machine"):
|
|
472
480
|
validator = UniqueTogetherValidator(queryset=Service.objects.all(), fields=("name", "virtual_machine"))
|
|
473
|
-
validator(
|
|
474
|
-
return super().validate(
|
|
481
|
+
validator(attrs, self)
|
|
482
|
+
return super().validate(attrs)
|