nautobot 2.4.13__py3-none-any.whl → 2.4.15__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/choices.py +8 -0
- nautobot/apps/ui.py +14 -0
- nautobot/core/api/views.py +2 -0
- nautobot/core/choices.py +4 -0
- nautobot/core/filters.py +21 -41
- nautobot/core/graphql/generators.py +8 -0
- nautobot/core/graphql/schema.py +30 -30
- nautobot/core/management/commands/check_job_approval_status.py +47 -0
- nautobot/core/management/commands/generate_test_data.py +1 -1
- nautobot/core/management/commands/migrate.py +90 -1
- nautobot/core/models/tree_queries.py +17 -0
- nautobot/core/settings.py +2 -2
- nautobot/core/settings.yaml +3 -3
- nautobot/core/tables.py +29 -6
- nautobot/core/templates/base_django.html +1 -1
- nautobot/core/templates/components/panel/header_extra_content_table.html +1 -1
- nautobot/core/templates/generic/object_list.html +17 -20
- nautobot/core/templates/inc/breadcrumbs.html +14 -0
- nautobot/core/templatetags/buttons.py +2 -4
- nautobot/core/templatetags/helpers.py +29 -6
- nautobot/core/templatetags/ui_framework.py +21 -0
- nautobot/core/testing/api.py +7 -0
- nautobot/core/testing/filters.py +20 -3
- nautobot/core/testing/forms.py +1 -1
- nautobot/core/tests/integration/test_filters.py +2 -2
- nautobot/core/tests/test_breadcrumbs.py +366 -0
- nautobot/core/tests/test_commands.py +40 -0
- nautobot/core/tests/test_filters.py +51 -1
- nautobot/core/tests/test_forms.py +1 -1
- nautobot/core/tests/test_graphql.py +4 -4
- nautobot/core/tests/test_titles.py +183 -0
- nautobot/core/tests/test_tree_queries.py +30 -0
- nautobot/core/tests/test_views.py +2 -2
- nautobot/core/tests/test_views_utils.py +1 -1
- nautobot/core/ui/breadcrumbs.py +538 -0
- nautobot/core/ui/bulk_buttons.py +53 -0
- nautobot/core/ui/object_detail.py +31 -8
- nautobot/core/ui/titles.py +127 -0
- nautobot/core/ui/utils.py +25 -0
- nautobot/core/utils/migrations.py +1 -1
- nautobot/core/views/__init__.py +1 -1
- nautobot/core/views/mixins.py +26 -1
- nautobot/core/views/renderers.py +20 -2
- nautobot/core/views/utils.py +14 -13
- nautobot/dcim/api/serializers.py +9 -0
- nautobot/dcim/choices.py +55 -0
- nautobot/dcim/constants.py +0 -16
- nautobot/dcim/factory.py +1 -1
- nautobot/dcim/filters/__init__.py +15 -3
- nautobot/dcim/forms.py +120 -7
- nautobot/dcim/management/commands/trace_paths.py +1 -1
- nautobot/dcim/migrations/0072_alter_powerfeed_options_and_more.py +97 -0
- nautobot/dcim/models/device_component_templates.py +8 -0
- nautobot/dcim/models/device_components.py +31 -12
- nautobot/dcim/models/devices.py +1 -1
- nautobot/dcim/models/power.py +171 -10
- nautobot/dcim/models/racks.py +7 -4
- nautobot/dcim/tables/devices.py +2 -0
- nautobot/dcim/tables/devicetypes.py +1 -0
- nautobot/dcim/tables/power.py +30 -2
- nautobot/dcim/templates/dcim/device.html +2 -2
- nautobot/dcim/templates/dcim/devicetype_retrieve.html +1 -214
- nautobot/dcim/templates/dcim/location_retrieve.html +2 -2
- nautobot/dcim/templates/dcim/powerfeed_edit.html +8 -0
- nautobot/dcim/templates/dcim/powerfeed_retrieve.html +1 -1
- nautobot/dcim/templates/dcim/rack.html +2 -318
- nautobot/dcim/templates/dcim/rack_edit.html +2 -47
- nautobot/dcim/templates/dcim/rack_retrieve.html +318 -0
- nautobot/dcim/templates/dcim/rack_update.html +47 -0
- nautobot/dcim/tests/integration/test_device_bulk_operations.py +61 -0
- nautobot/dcim/tests/test_api.py +24 -4
- nautobot/dcim/tests/test_filters.py +91 -13
- nautobot/dcim/tests/test_models.py +262 -0
- nautobot/dcim/tests/test_views.py +20 -12
- nautobot/dcim/urls.py +2 -27
- nautobot/dcim/utils.py +13 -30
- nautobot/dcim/views.py +428 -146
- nautobot/extras/choices.py +12 -4
- nautobot/extras/factory.py +19 -20
- nautobot/extras/filters/__init__.py +3 -2
- nautobot/extras/filters/mixins.py +23 -7
- nautobot/extras/forms/__init__.py +2 -1
- nautobot/extras/forms/forms.py +71 -0
- nautobot/extras/forms/mixins.py +4 -2
- nautobot/extras/managers.py +4 -1
- nautobot/extras/migrations/0062_collect_roles_from_related_apps_roles.py +30 -7
- nautobot/extras/migrations/0124_add_joblogentry_index.py +16 -0
- nautobot/extras/migrations/0125_jobresult_date_started.py +18 -0
- nautobot/extras/models/customfields.py +53 -5
- nautobot/extras/models/datasources.py +1 -2
- nautobot/extras/models/jobs.py +13 -3
- nautobot/extras/models/relationships.py +55 -6
- nautobot/extras/plugins/views.py +24 -1
- nautobot/extras/secrets/__init__.py +1 -1
- nautobot/extras/tables.py +9 -0
- nautobot/extras/templates/extras/customfield.html +2 -129
- nautobot/extras/templates/extras/customfield_edit.html +2 -108
- nautobot/extras/templates/extras/customfield_retrieve.html +129 -0
- nautobot/extras/templates/extras/customfield_update.html +108 -0
- nautobot/extras/templates/extras/graphqlquery.html +2 -97
- nautobot/extras/templates/extras/graphqlquery_list.html +1 -0
- nautobot/extras/templates/extras/graphqlquery_retrieve.html +97 -0
- nautobot/extras/templates/extras/inc/jobresult.html +7 -3
- nautobot/extras/templates/extras/jobresult.html +2 -155
- nautobot/extras/templates/extras/jobresult_retrieve.html +155 -0
- nautobot/extras/templates/extras/marketplace.html +5 -6
- nautobot/extras/templates/extras/note.html +2 -53
- nautobot/extras/templates/extras/note_retrieve.html +53 -0
- nautobot/extras/templates/extras/plugins_list.html +5 -6
- nautobot/extras/templates/extras/secretsgroup.html +2 -29
- nautobot/extras/templates/extras/secretsgroup_edit.html +2 -82
- nautobot/extras/templates/extras/secretsgroup_retrieve.html +29 -0
- nautobot/extras/templates/extras/secretsgroup_update.html +82 -0
- nautobot/extras/templatetags/custom_links.py +2 -2
- nautobot/extras/templatetags/job_buttons.py +1 -1
- nautobot/extras/templatetags/plugins.py +1 -1
- nautobot/extras/tests/integration/test_computedfields.py +2 -2
- nautobot/extras/tests/integration/test_customfields.py +14 -11
- nautobot/extras/tests/integration/test_dynamicgroups.py +1 -1
- nautobot/extras/tests/integration/test_notes.py +1 -1
- nautobot/extras/tests/integration/test_plugins.py +6 -6
- nautobot/extras/tests/integration/test_relationships.py +2 -2
- nautobot/extras/tests/test_customfields.py +115 -7
- nautobot/extras/tests/test_filters.py +9 -0
- nautobot/extras/tests/test_forms.py +2 -2
- nautobot/extras/tests/test_plugins.py +2 -3
- nautobot/extras/tests/test_relationships.py +14 -8
- nautobot/extras/tests/test_views.py +285 -2
- nautobot/extras/urls.py +5 -110
- nautobot/extras/utils.py +5 -2
- nautobot/extras/views.py +116 -311
- nautobot/ipam/api/views.py +69 -6
- nautobot/ipam/tables.py +8 -15
- nautobot/ipam/tests/migration/test_migrations.py +8 -8
- nautobot/ipam/tests/test_api.py +352 -2
- nautobot/ipam/tests/test_models.py +1 -1
- nautobot/project-static/docs/404.html +34 -34
- nautobot/project-static/docs/apps/index.html +34 -34
- nautobot/project-static/docs/apps/nautobot-apps.html +34 -34
- nautobot/project-static/docs/assets/_mkdocstrings.css +44 -6
- nautobot/project-static/docs/assets/javascripts/{bundle.56ea9cef.min.js → bundle.50899def.min.js} +2 -2
- nautobot/project-static/docs/assets/javascripts/{bundle.56ea9cef.min.js.map → bundle.50899def.min.js.map} +2 -2
- nautobot/project-static/docs/assets/stylesheets/{main.342714a4.min.css → main.7e37652d.min.css} +1 -1
- nautobot/project-static/docs/assets/stylesheets/{main.342714a4.min.css.map → main.7e37652d.min.css.map} +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +39 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +36 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +139 -54
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +48 -38
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +50 -40
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +36 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +35 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +43 -39
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +52 -42
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +50 -41
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +54 -44
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +85 -93
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +154 -62
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +54 -46
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +146 -87
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +240 -70
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +38 -35
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +41 -35
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +173 -52
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +269 -85
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +5987 -2643
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +36 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +165 -89
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +161 -69
- nautobot/project-static/docs/development/apps/api/configuration-view.html +34 -34
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +34 -34
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +34 -34
- nautobot/project-static/docs/development/apps/api/models/global-search.html +34 -34
- nautobot/project-static/docs/development/apps/api/models/graphql.html +34 -34
- nautobot/project-static/docs/development/apps/api/models/index.html +34 -34
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +34 -34
- nautobot/project-static/docs/development/apps/api/prometheus.html +34 -34
- nautobot/project-static/docs/development/apps/api/setup.html +34 -34
- nautobot/project-static/docs/development/apps/api/testing.html +34 -34
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +34 -34
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +34 -34
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +34 -34
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +34 -34
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/base-template.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/index.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +42 -36
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/notes.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/urls.html +34 -34
- nautobot/project-static/docs/development/apps/index.html +34 -34
- nautobot/project-static/docs/development/apps/migration/code-updates.html +34 -34
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +34 -34
- nautobot/project-static/docs/development/apps/migration/from-v1.html +34 -34
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +34 -34
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +34 -34
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +34 -34
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +34 -34
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +37 -37
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/breadcrumbs-titles.html +10544 -0
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +34 -34
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +34 -34
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +34 -34
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +37 -37
- nautobot/project-static/docs/development/core/application-registry.html +162 -133
- nautobot/project-static/docs/development/core/best-practices.html +34 -34
- nautobot/project-static/docs/development/core/bootstrap-ui.html +34 -34
- nautobot/project-static/docs/development/core/caching.html +34 -34
- nautobot/project-static/docs/development/core/controllers.html +34 -34
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +34 -34
- nautobot/project-static/docs/development/core/generic-views.html +34 -34
- nautobot/project-static/docs/development/core/getting-started.html +34 -34
- nautobot/project-static/docs/development/core/homepage.html +34 -34
- nautobot/project-static/docs/development/core/index.html +34 -34
- nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +34 -34
- nautobot/project-static/docs/development/core/model-checklist.html +34 -34
- nautobot/project-static/docs/development/core/model-features.html +34 -34
- nautobot/project-static/docs/development/core/natural-keys.html +34 -34
- nautobot/project-static/docs/development/core/navigation-menu.html +34 -34
- nautobot/project-static/docs/development/core/release-checklist.html +34 -34
- nautobot/project-static/docs/development/core/role-internals.html +34 -34
- nautobot/project-static/docs/development/core/settings.html +34 -34
- nautobot/project-static/docs/development/core/style-guide.html +34 -34
- nautobot/project-static/docs/development/core/templates.html +34 -34
- nautobot/project-static/docs/development/core/testing.html +34 -34
- nautobot/project-static/docs/development/core/ui-component-framework.html +724 -289
- nautobot/project-static/docs/development/core/user-preferences.html +34 -34
- nautobot/project-static/docs/development/index.html +34 -34
- nautobot/project-static/docs/development/jobs/getting-started.html +34 -34
- nautobot/project-static/docs/development/jobs/index.html +34 -34
- nautobot/project-static/docs/development/jobs/installation.html +34 -34
- nautobot/project-static/docs/development/jobs/job-extensions.html +34 -34
- nautobot/project-static/docs/development/jobs/job-logging.html +34 -34
- nautobot/project-static/docs/development/jobs/job-patterns.html +34 -34
- nautobot/project-static/docs/development/jobs/job-structure.html +34 -34
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +34 -34
- nautobot/project-static/docs/development/jobs/testing.html +34 -34
- nautobot/project-static/docs/index.html +34 -34
- nautobot/project-static/docs/media/development/core/ui-component-framework/breadcrumbs-titles-data-flow.png +0 -0
- nautobot/project-static/docs/media/power_distribution.png +0 -0
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +34 -34
- nautobot/project-static/docs/overview/design_philosophy.html +34 -34
- nautobot/project-static/docs/release-notes/index.html +34 -34
- nautobot/project-static/docs/release-notes/version-1.0.html +34 -34
- nautobot/project-static/docs/release-notes/version-1.1.html +34 -34
- nautobot/project-static/docs/release-notes/version-1.2.html +34 -34
- nautobot/project-static/docs/release-notes/version-1.3.html +34 -34
- nautobot/project-static/docs/release-notes/version-1.4.html +34 -34
- nautobot/project-static/docs/release-notes/version-1.5.html +34 -34
- nautobot/project-static/docs/release-notes/version-1.6.html +34 -34
- nautobot/project-static/docs/release-notes/version-2.0.html +34 -34
- nautobot/project-static/docs/release-notes/version-2.1.html +34 -34
- nautobot/project-static/docs/release-notes/version-2.2.html +34 -34
- nautobot/project-static/docs/release-notes/version-2.3.html +34 -34
- nautobot/project-static/docs/release-notes/version-2.4.html +402 -34
- nautobot/project-static/docs/requirements.txt +3 -3
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +303 -299
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +34 -34
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +34 -34
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +34 -34
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +34 -34
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +34 -34
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +37 -37
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +34 -34
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +34 -34
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +34 -34
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +34 -34
- nautobot/project-static/docs/user-guide/administration/installation/index.html +34 -34
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +34 -34
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +34 -34
- nautobot/project-static/docs/user-guide/administration/installation/services.html +34 -34
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +34 -34
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +34 -34
- nautobot/project-static/docs/user-guide/administration/security/index.html +34 -34
- nautobot/project-static/docs/user-guide/administration/security/notices.html +34 -34
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +296 -251
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +37 -37
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +42 -52
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +37 -37
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulefamily.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +316 -39
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +35 -35
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +147 -37
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +52 -35
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +51 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +34 -34
- nautobot/project-static/docs/user-guide/index.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +35 -35
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +34 -34
- nautobot/tenancy/api/views.py +2 -1
- nautobot/users/tests/test_api.py +2 -2
- nautobot/virtualization/templates/virtualization/virtualmachine.html +2 -252
- nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +2 -75
- nautobot/virtualization/templates/virtualization/virtualmachine_retrieve.html +252 -0
- nautobot/virtualization/templates/virtualization/virtualmachine_update.html +75 -0
- nautobot/virtualization/urls.py +3 -61
- nautobot/virtualization/views.py +48 -72
- {nautobot-2.4.13.dist-info → nautobot-2.4.15.dist-info}/METADATA +27 -27
- {nautobot-2.4.13.dist-info → nautobot-2.4.15.dist-info}/RECORD +463 -439
- {nautobot-2.4.13.dist-info → nautobot-2.4.15.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.4.13.dist-info → nautobot-2.4.15.dist-info}/NOTICE +0 -0
- {nautobot-2.4.13.dist-info → nautobot-2.4.15.dist-info}/WHEEL +0 -0
- {nautobot-2.4.13.dist-info → nautobot-2.4.15.dist-info}/entry_points.txt +0 -0
nautobot/apps/choices.py
CHANGED
|
@@ -18,11 +18,15 @@ from nautobot.dcim.choices import (
|
|
|
18
18
|
InterfaceRedundancyGroupProtocolChoices,
|
|
19
19
|
InterfaceTypeChoices,
|
|
20
20
|
PortTypeChoices,
|
|
21
|
+
PowerFeedBreakerPoleChoices,
|
|
21
22
|
PowerFeedPhaseChoices,
|
|
23
|
+
PowerFeedStatusChoices,
|
|
22
24
|
PowerFeedSupplyChoices,
|
|
23
25
|
PowerFeedTypeChoices,
|
|
24
26
|
PowerOutletFeedLegChoices,
|
|
25
27
|
PowerOutletTypeChoices,
|
|
28
|
+
PowerPanelTypeChoices,
|
|
29
|
+
PowerPathChoices,
|
|
26
30
|
PowerPortTypeChoices,
|
|
27
31
|
RackDimensionUnitChoices,
|
|
28
32
|
RackElevationDetailRenderChoices,
|
|
@@ -89,11 +93,15 @@ __all__ = (
|
|
|
89
93
|
"ObjectChangeActionChoices",
|
|
90
94
|
"ObjectChangeEventContextChoices",
|
|
91
95
|
"PortTypeChoices",
|
|
96
|
+
"PowerFeedBreakerPoleChoices",
|
|
92
97
|
"PowerFeedPhaseChoices",
|
|
98
|
+
"PowerFeedStatusChoices",
|
|
93
99
|
"PowerFeedSupplyChoices",
|
|
94
100
|
"PowerFeedTypeChoices",
|
|
95
101
|
"PowerOutletFeedLegChoices",
|
|
96
102
|
"PowerOutletTypeChoices",
|
|
103
|
+
"PowerPanelTypeChoices",
|
|
104
|
+
"PowerPathChoices",
|
|
97
105
|
"PowerPortTypeChoices",
|
|
98
106
|
"PrefixTypeChoices",
|
|
99
107
|
"RackDimensionUnitChoices",
|
nautobot/apps/ui.py
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
from nautobot.core.choices import ButtonColorChoices
|
|
4
4
|
from nautobot.core.ui.base import PermissionsMixin
|
|
5
|
+
from nautobot.core.ui.breadcrumbs import (
|
|
6
|
+
BaseBreadcrumbItem,
|
|
7
|
+
Breadcrumbs,
|
|
8
|
+
InstanceBreadcrumbItem,
|
|
9
|
+
ModelBreadcrumbItem,
|
|
10
|
+
ViewNameBreadcrumbItem,
|
|
11
|
+
)
|
|
5
12
|
from nautobot.core.ui.choices import LayoutChoices, SectionChoices
|
|
6
13
|
from nautobot.core.ui.homepage import (
|
|
7
14
|
HomePageBase,
|
|
@@ -36,6 +43,7 @@ from nautobot.core.ui.object_detail import (
|
|
|
36
43
|
Tab,
|
|
37
44
|
TextPanel,
|
|
38
45
|
)
|
|
46
|
+
from nautobot.core.ui.titles import Titles
|
|
39
47
|
from nautobot.core.ui.utils import render_component_template
|
|
40
48
|
from nautobot.extras.choices import BannerClassChoices
|
|
41
49
|
from nautobot.extras.plugins import Banner, TemplateExtension
|
|
@@ -43,7 +51,9 @@ from nautobot.extras.plugins import Banner, TemplateExtension
|
|
|
43
51
|
__all__ = (
|
|
44
52
|
"Banner",
|
|
45
53
|
"BannerClassChoices",
|
|
54
|
+
"BaseBreadcrumbItem",
|
|
46
55
|
"BaseTextPanel",
|
|
56
|
+
"Breadcrumbs",
|
|
47
57
|
"Button",
|
|
48
58
|
"ButtonColorChoices",
|
|
49
59
|
"Component",
|
|
@@ -55,8 +65,10 @@ __all__ = (
|
|
|
55
65
|
"HomePageGroup",
|
|
56
66
|
"HomePageItem",
|
|
57
67
|
"HomePagePanel",
|
|
68
|
+
"InstanceBreadcrumbItem",
|
|
58
69
|
"KeyValueTablePanel",
|
|
59
70
|
"LayoutChoices",
|
|
71
|
+
"ModelBreadcrumbItem",
|
|
60
72
|
"NavMenuAddButton",
|
|
61
73
|
"NavMenuBase",
|
|
62
74
|
"NavMenuButton",
|
|
@@ -75,5 +87,7 @@ __all__ = (
|
|
|
75
87
|
"Tab",
|
|
76
88
|
"TemplateExtension",
|
|
77
89
|
"TextPanel",
|
|
90
|
+
"Titles",
|
|
91
|
+
"ViewNameBreadcrumbItem",
|
|
78
92
|
"render_component_template",
|
|
79
93
|
)
|
nautobot/core/api/views.py
CHANGED
|
@@ -519,6 +519,8 @@ class StatusView(NautobotAPIVersionMixin, APIView):
|
|
|
519
519
|
if version:
|
|
520
520
|
if isinstance(version, tuple):
|
|
521
521
|
version = ".".join(str(n) for n in version)
|
|
522
|
+
else:
|
|
523
|
+
version = str(version)
|
|
522
524
|
installed_apps[app_config.name] = version
|
|
523
525
|
installed_apps = dict(sorted(installed_apps.items()))
|
|
524
526
|
|
nautobot/core/choices.py
CHANGED
|
@@ -194,6 +194,7 @@ class ButtonActionColorChoices(ChoiceSet):
|
|
|
194
194
|
EXPORT = "success"
|
|
195
195
|
IMPORT = "primary"
|
|
196
196
|
INFO = "info"
|
|
197
|
+
RENAME = "warning"
|
|
197
198
|
SUBMIT = "primary"
|
|
198
199
|
SWAP = "primary"
|
|
199
200
|
|
|
@@ -210,6 +211,7 @@ class ButtonActionColorChoices(ChoiceSet):
|
|
|
210
211
|
(EXPORT, "Export"),
|
|
211
212
|
(IMPORT, "Import"),
|
|
212
213
|
(INFO, "Info"),
|
|
214
|
+
(RENAME, "Rename"),
|
|
213
215
|
(SUBMIT, "Submit"),
|
|
214
216
|
(SWAP, "Swap"),
|
|
215
217
|
)
|
|
@@ -236,6 +238,7 @@ class ButtonActionIconChoices(ChoiceSet):
|
|
|
236
238
|
LOCK = "mdi-lock"
|
|
237
239
|
MAGNIFY = "mdi-magnify"
|
|
238
240
|
NOTE = "mdi-note-text"
|
|
241
|
+
RENAME = "mdi-pencil"
|
|
239
242
|
SWAP = "mdi-swap-vertical"
|
|
240
243
|
TRASH = "mdi-trash-can-outline"
|
|
241
244
|
|
|
@@ -256,6 +259,7 @@ class ButtonActionIconChoices(ChoiceSet):
|
|
|
256
259
|
(LOCK, "Lock"),
|
|
257
260
|
(MAGNIFY, "Magnify"),
|
|
258
261
|
(NOTE, "Note"),
|
|
262
|
+
(RENAME, "Rename"),
|
|
259
263
|
(SWAP, "Swap"),
|
|
260
264
|
(TRASH, "Trash"),
|
|
261
265
|
)
|
nautobot/core/filters.py
CHANGED
|
@@ -209,14 +209,12 @@ class ContentTypeFilterMixin:
|
|
|
209
209
|
return qs
|
|
210
210
|
|
|
211
211
|
if value.isdigit():
|
|
212
|
-
return
|
|
213
|
-
|
|
212
|
+
return self.get_method(qs)(**{f"{self.field_name}__pk": value})
|
|
214
213
|
try:
|
|
215
214
|
app_label, model = value.lower().split(".")
|
|
216
215
|
except ValueError:
|
|
217
216
|
return qs.none()
|
|
218
|
-
|
|
219
|
-
return qs.filter(
|
|
217
|
+
return self.get_method(qs)(
|
|
220
218
|
**{
|
|
221
219
|
f"{self.field_name}__app_label": app_label,
|
|
222
220
|
f"{self.field_name}__model": model,
|
|
@@ -244,6 +242,8 @@ class ContentTypeChoiceFilter(ContentTypeFilterMixin, django_filters.ChoiceFilte
|
|
|
244
242
|
content_type = ContentTypeChoiceFilter(
|
|
245
243
|
choices=FeatureQuery("dynamic_groups").get_choices,
|
|
246
244
|
)
|
|
245
|
+
|
|
246
|
+
In most cases you should use `ContentTypeMultipleChoiceFilter` instead.
|
|
247
247
|
"""
|
|
248
248
|
|
|
249
249
|
|
|
@@ -251,6 +251,9 @@ class ContentTypeMultipleChoiceFilter(django_filters.MultipleChoiceFilter):
|
|
|
251
251
|
"""
|
|
252
252
|
Allows multiple-choice ContentType filtering by <app_label>.<model> (e.g. "dcim.location").
|
|
253
253
|
|
|
254
|
+
Does NOT allow filtering by PK at this time; it would need to be reimplemented similar to
|
|
255
|
+
NaturalKeyOrPKMultipleChoiceFilter as a breaking change.
|
|
256
|
+
|
|
254
257
|
Defaults to joining multiple options with "AND". Pass `conjoined=False` to
|
|
255
258
|
override this behavior to join with "OR" instead.
|
|
256
259
|
|
|
@@ -265,43 +268,14 @@ class ContentTypeMultipleChoiceFilter(django_filters.MultipleChoiceFilter):
|
|
|
265
268
|
kwargs.setdefault("conjoined", True)
|
|
266
269
|
super().__init__(*args, **kwargs)
|
|
267
270
|
|
|
268
|
-
def
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
for v in value:
|
|
277
|
-
if self.conjoined:
|
|
278
|
-
qs = ContentTypeFilter.filter(self, qs, v)
|
|
279
|
-
else:
|
|
280
|
-
if v.isdigit():
|
|
281
|
-
q |= models.Q(**{f"{self.field_name}__pk": value})
|
|
282
|
-
continue
|
|
283
|
-
# Similar to the ContentTypeFilter.filter() call above, but instead of narrowing the query each time
|
|
284
|
-
# (a AND b AND c ...) we broaden the query each time (a OR b OR c ...).
|
|
285
|
-
# Specifically, we're mapping a value like ['dcim.device', 'ipam.vlan'] to a query like
|
|
286
|
-
# Q((field__app_label="dcim" AND field__model="device") OR (field__app_label="ipam" AND field__model="VLAN"))
|
|
287
|
-
try:
|
|
288
|
-
app_label, model = v.lower().split(".")
|
|
289
|
-
except ValueError:
|
|
290
|
-
continue
|
|
291
|
-
q |= models.Q(
|
|
292
|
-
**{
|
|
293
|
-
f"{self.field_name}__app_label": app_label,
|
|
294
|
-
f"{self.field_name}__model": model,
|
|
295
|
-
}
|
|
296
|
-
)
|
|
297
|
-
|
|
298
|
-
if not self.conjoined:
|
|
299
|
-
qs = qs.filter(q)
|
|
300
|
-
|
|
301
|
-
if self.distinct:
|
|
302
|
-
qs = qs.distinct()
|
|
303
|
-
|
|
304
|
-
return qs
|
|
271
|
+
def get_filter_predicate(self, v):
|
|
272
|
+
if v.isdigit():
|
|
273
|
+
return {f"{self.field_name}__pk": v}
|
|
274
|
+
try:
|
|
275
|
+
app_label, model = v.lower().split(".")
|
|
276
|
+
except ValueError:
|
|
277
|
+
return {f"{self.field_name}__pk": v}
|
|
278
|
+
return {f"{self.field_name}__app_label": app_label, f"{self.field_name}__model": model}
|
|
305
279
|
|
|
306
280
|
|
|
307
281
|
class MappedPredicatesFilterMixin:
|
|
@@ -642,6 +616,9 @@ class BaseFilterSet(django_filters.FilterSet):
|
|
|
642
616
|
(
|
|
643
617
|
django_filters.ModelChoiceFilter,
|
|
644
618
|
django_filters.ModelMultipleChoiceFilter,
|
|
619
|
+
ContentTypeFilter,
|
|
620
|
+
ContentTypeChoiceFilter,
|
|
621
|
+
ContentTypeMultipleChoiceFilter,
|
|
645
622
|
MultiValueUUIDFilter,
|
|
646
623
|
TagFilter,
|
|
647
624
|
TreeNodeMultipleChoiceFilter,
|
|
@@ -820,6 +797,7 @@ class BaseFilterSet(django_filters.FilterSet):
|
|
|
820
797
|
to_field_name="name",
|
|
821
798
|
label="Contacts (name or ID)",
|
|
822
799
|
)
|
|
800
|
+
cls.declared_filters["contacts"] = filters["contacts"] # pylint: disable=no-member
|
|
823
801
|
|
|
824
802
|
if "teams" not in filters:
|
|
825
803
|
filters["teams"] = NaturalKeyOrPKMultipleChoiceFilter(
|
|
@@ -828,6 +806,7 @@ class BaseFilterSet(django_filters.FilterSet):
|
|
|
828
806
|
to_field_name="name",
|
|
829
807
|
label="Teams (name or ID)",
|
|
830
808
|
)
|
|
809
|
+
cls.declared_filters["teams"] = filters["teams"] # pylint: disable=no-member
|
|
831
810
|
|
|
832
811
|
if "dynamic_groups" not in filters and getattr(cls._meta.model, "is_dynamic_group_associable_model", False): # pylint: disable=no-member
|
|
833
812
|
if not hasattr(cls._meta.model, "static_group_association_set"): # pylint: disable=no-member
|
|
@@ -848,6 +827,7 @@ class BaseFilterSet(django_filters.FilterSet):
|
|
|
848
827
|
query_params={"content_type": cls._meta.model._meta.label_lower}, # pylint: disable=no-member
|
|
849
828
|
label="Dynamic groups (name or ID)",
|
|
850
829
|
)
|
|
830
|
+
cls.declared_filters["dynamic_groups"] = filters["dynamic_groups"] # pylint: disable=no-member
|
|
851
831
|
|
|
852
832
|
# django-filters has no concept of "abstract" filtersets, so we have to fake it
|
|
853
833
|
if cls._meta.model is not None: # pylint: disable=no-member
|
|
@@ -16,6 +16,9 @@ logger = logging.getLogger(__name__)
|
|
|
16
16
|
RESOLVER_PREFIX = "resolve_"
|
|
17
17
|
|
|
18
18
|
|
|
19
|
+
LIST_SEARCH_PARAMS_BY_SCHEMA_TYPE = {}
|
|
20
|
+
|
|
21
|
+
|
|
19
22
|
def generate_restricted_queryset():
|
|
20
23
|
"""
|
|
21
24
|
Generate a function to return a restricted queryset compatible with the internal permissions system.
|
|
@@ -248,6 +251,9 @@ def generate_schema_type(app_name: str, model: object) -> OptimizedNautobotObjec
|
|
|
248
251
|
def generate_list_search_parameters(schema_type):
|
|
249
252
|
"""Generate list of query parameters for the list resolver based on a filterset."""
|
|
250
253
|
|
|
254
|
+
if schema_type in LIST_SEARCH_PARAMS_BY_SCHEMA_TYPE:
|
|
255
|
+
return LIST_SEARCH_PARAMS_BY_SCHEMA_TYPE[schema_type]
|
|
256
|
+
|
|
251
257
|
search_params = {
|
|
252
258
|
"limit": graphene.Int(),
|
|
253
259
|
"offset": graphene.Int(),
|
|
@@ -259,6 +265,8 @@ def generate_list_search_parameters(schema_type):
|
|
|
259
265
|
)
|
|
260
266
|
)
|
|
261
267
|
|
|
268
|
+
LIST_SEARCH_PARAMS_BY_SCHEMA_TYPE[schema_type] = search_params
|
|
269
|
+
|
|
262
270
|
return search_params
|
|
263
271
|
|
|
264
272
|
|
nautobot/core/graphql/schema.py
CHANGED
|
@@ -243,12 +243,12 @@ def extend_schema_type_custom_field(schema_type, model):
|
|
|
243
243
|
(DjangoObjectType): The extended schema_type object
|
|
244
244
|
"""
|
|
245
245
|
|
|
246
|
-
|
|
246
|
+
custom_fields = CustomField.objects.get_for_model(model, get_queryset=False)
|
|
247
247
|
prefix = ""
|
|
248
248
|
if settings.GRAPHQL_CUSTOM_FIELD_PREFIX and isinstance(settings.GRAPHQL_CUSTOM_FIELD_PREFIX, str):
|
|
249
249
|
prefix = f"{settings.GRAPHQL_CUSTOM_FIELD_PREFIX}_"
|
|
250
250
|
|
|
251
|
-
for field in
|
|
251
|
+
for field in custom_fields:
|
|
252
252
|
# Since we guaranteed cf.key's uniqueness in CustomField data migration
|
|
253
253
|
# We can safely field_key this in our GraphQL without duplication
|
|
254
254
|
# For new CustomField instances, we also make sure that duplicate key does not exist.
|
|
@@ -281,6 +281,7 @@ def extend_schema_type_custom_field(schema_type, model):
|
|
|
281
281
|
|
|
282
282
|
def extend_schema_type_computed_field(schema_type, model):
|
|
283
283
|
"""Extend schema_type object to had attribute and resolver around computed_fields.
|
|
284
|
+
|
|
284
285
|
Each computed field will be defined as a first level attribute.
|
|
285
286
|
|
|
286
287
|
Args:
|
|
@@ -291,12 +292,12 @@ def extend_schema_type_computed_field(schema_type, model):
|
|
|
291
292
|
(DjangoObjectType): The extended schema_type object
|
|
292
293
|
"""
|
|
293
294
|
|
|
294
|
-
|
|
295
|
+
computed_fields = ComputedField.objects.get_for_model(model, get_queryset=False)
|
|
295
296
|
prefix = ""
|
|
296
297
|
if settings.GRAPHQL_COMPUTED_FIELD_PREFIX and isinstance(settings.GRAPHQL_COMPUTED_FIELD_PREFIX, str):
|
|
297
298
|
prefix = f"{settings.GRAPHQL_COMPUTED_FIELD_PREFIX}_"
|
|
298
299
|
|
|
299
|
-
for field in
|
|
300
|
+
for field in computed_fields:
|
|
300
301
|
field_name = f"{prefix}{field.key}"
|
|
301
302
|
try:
|
|
302
303
|
check_if_key_is_graphql_safe("Computed Field", field.key)
|
|
@@ -396,12 +397,16 @@ def extend_schema_type_global_features(schema_type, model):
|
|
|
396
397
|
|
|
397
398
|
|
|
398
399
|
def extend_schema_type_relationships(schema_type, model):
|
|
399
|
-
"""
|
|
400
|
-
|
|
400
|
+
"""
|
|
401
|
+
Extend the schema type with attributes and resolvers for the relationships associated with this model.
|
|
401
402
|
|
|
403
|
+
Args:
|
|
404
|
+
schema_type (DjangoObjectType): GraphQL Object type for a given model
|
|
405
|
+
model (Model): Django model
|
|
406
|
+
"""
|
|
402
407
|
relationships_by_side = {
|
|
403
|
-
"source": Relationship.objects.get_for_model_source(model),
|
|
404
|
-
"destination": Relationship.objects.get_for_model_destination(model),
|
|
408
|
+
"source": Relationship.objects.get_for_model_source(model, get_queryset=False),
|
|
409
|
+
"destination": Relationship.objects.get_for_model_destination(model, get_queryset=False),
|
|
405
410
|
}
|
|
406
411
|
|
|
407
412
|
prefix = ""
|
|
@@ -499,30 +504,16 @@ def generate_query_mixin():
|
|
|
499
504
|
|
|
500
505
|
logger.debug("Generating dynamic schemas for all models in the models_features graphql registry")
|
|
501
506
|
# - Ensure an attribute/schematype with the same name doesn't already exist
|
|
502
|
-
registered_models = registry.get("
|
|
503
|
-
for
|
|
504
|
-
|
|
505
|
-
try:
|
|
506
|
-
# Find the model class based on the content type
|
|
507
|
-
ct = ContentType.objects.get(app_label=app_name, model=model_name)
|
|
508
|
-
model = ct.model_class()
|
|
509
|
-
except ContentType.DoesNotExist:
|
|
510
|
-
logger.warning(
|
|
511
|
-
'Unable to generate a schema type for the model "%s.%s" in GraphQL, '
|
|
512
|
-
"as this model doesn't have an associated ContentType. Please create the Object manually.",
|
|
513
|
-
app_name,
|
|
514
|
-
model_name,
|
|
515
|
-
)
|
|
516
|
-
continue
|
|
507
|
+
registered_models = registry.get("feature_models", {}).get("graphql", [])
|
|
508
|
+
for model in registered_models:
|
|
509
|
+
type_identifier = model._meta.label_lower
|
|
517
510
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
# Skip models that have been added statically
|
|
522
|
-
continue
|
|
511
|
+
if type_identifier in registry["graphql_types"].keys():
|
|
512
|
+
# Skip models that have been added statically
|
|
513
|
+
continue
|
|
523
514
|
|
|
524
|
-
|
|
525
|
-
|
|
515
|
+
schema_type = generate_schema_type(app_name=model._meta.app_label, model=model)
|
|
516
|
+
registry["graphql_types"][type_identifier] = schema_type
|
|
526
517
|
|
|
527
518
|
logger.debug("Adding plugins' statically defined graphql schema types")
|
|
528
519
|
# After checking for conflict
|
|
@@ -542,6 +533,15 @@ def generate_query_mixin():
|
|
|
542
533
|
registry["graphql_types"][type_identifier] = schema_type
|
|
543
534
|
|
|
544
535
|
logger.debug("Extending all registered schema types with dynamic attributes")
|
|
536
|
+
|
|
537
|
+
# Precache all content-types as we'll need them for filtering and the like
|
|
538
|
+
for content_type in ContentType.objects.all():
|
|
539
|
+
ContentType.objects._add_to_cache(ContentType.objects.db, content_type)
|
|
540
|
+
|
|
541
|
+
CustomField.objects.populate_list_caches()
|
|
542
|
+
ComputedField.objects.populate_list_caches()
|
|
543
|
+
Relationship.objects.populate_list_caches()
|
|
544
|
+
|
|
545
545
|
for schema_type in registry["graphql_types"].values():
|
|
546
546
|
if already_present(schema_type._meta.model):
|
|
547
547
|
continue
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from django.core.exceptions import ValidationError
|
|
2
|
+
from django.core.management.base import BaseCommand
|
|
3
|
+
|
|
4
|
+
from nautobot.extras.models import Job, ScheduledJob
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ApprovalRequiredScheduledJobsError(ValidationError):
|
|
8
|
+
"""Raised when scheduled jobs requiring approval are found during managment command."""
|
|
9
|
+
|
|
10
|
+
def __init__(self, message_lines):
|
|
11
|
+
self.message_lines = message_lines
|
|
12
|
+
super().__init__(message_lines)
|
|
13
|
+
|
|
14
|
+
def __str__(self):
|
|
15
|
+
return "\n".join(self.message_lines)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Command(BaseCommand):
|
|
19
|
+
help = "Checks for scheduled jobs and jobs that require approval."
|
|
20
|
+
|
|
21
|
+
def handle(self, *args, **options):
|
|
22
|
+
approval_required_scheduled_jobs = ScheduledJob.objects.filter(approval_required=True).values_list("id", "name")
|
|
23
|
+
|
|
24
|
+
if approval_required_scheduled_jobs:
|
|
25
|
+
message_lines = [
|
|
26
|
+
"These need to be approved (and run) or denied before upgrading to Nautobot v3, as the introduction of the approval workflows feature means that future scheduled-job approvals will be handled differently.",
|
|
27
|
+
"Refer to the documentation: https://docs.nautobot.com/projects/core/en/v2.4.14/user-guide/platform-functionality/jobs/job-scheduling-and-approvals/#approval-via-the-ui",
|
|
28
|
+
"Below is a list of affected scheduled jobs:",
|
|
29
|
+
]
|
|
30
|
+
for schedule_job_id, scheduled_job_name in approval_required_scheduled_jobs:
|
|
31
|
+
message_lines.append(f" - ID: {schedule_job_id}, Name: {scheduled_job_name}")
|
|
32
|
+
raise ApprovalRequiredScheduledJobsError(message_lines)
|
|
33
|
+
|
|
34
|
+
approval_required_jobs = Job.objects.filter(approval_required=True).values_list("name", flat=True)
|
|
35
|
+
if approval_required_jobs:
|
|
36
|
+
message_lines = [
|
|
37
|
+
"Following jobs still have `approval_required=True`.",
|
|
38
|
+
"These jobs will no longer trigger approval automatically.",
|
|
39
|
+
"After upgrading to Nautobot 3.x, you should add an approval workflow definition(s) covering these jobs.",
|
|
40
|
+
"Refer to the documentation: https://docs.nautobot.com/projects/core/en/v3.0.0/user-guide/platform-functionality/approval-workflow/",
|
|
41
|
+
"Affected jobs (Names):",
|
|
42
|
+
]
|
|
43
|
+
for job_name in approval_required_jobs:
|
|
44
|
+
message_lines.append(f" - {job_name}")
|
|
45
|
+
else:
|
|
46
|
+
message_lines = ["No approval_required jobs or scheduled jobs found."]
|
|
47
|
+
self.stdout.write("\n".join(message_lines))
|
|
@@ -375,7 +375,7 @@ class Command(BaseCommand):
|
|
|
375
375
|
confirm = input(
|
|
376
376
|
f"""\
|
|
377
377
|
You have requested a flush of the database before generating new data.
|
|
378
|
-
This will IRREVERSIBLY DESTROY all data in the "{connections[options[
|
|
378
|
+
This will IRREVERSIBLY DESTROY all data in the "{connections[options["database"]].settings_dict["NAME"]}" database,
|
|
379
379
|
including all user accounts, and return each table to an empty state.
|
|
380
380
|
Are you SURE you want to do this?
|
|
381
381
|
|
|
@@ -1,8 +1,97 @@
|
|
|
1
1
|
# noinspection PyUnresolvedReferences
|
|
2
|
-
|
|
2
|
+
import contextlib
|
|
3
|
+
import time
|
|
4
|
+
|
|
5
|
+
from django.apps import apps
|
|
6
|
+
from django.core.management.commands.migrate import Command as _Command
|
|
3
7
|
from django.db import models
|
|
8
|
+
from django.db.migrations.operations.fields import FieldOperation
|
|
9
|
+
from django.db.migrations.operations.models import ModelOperation
|
|
4
10
|
|
|
5
11
|
from nautobot.core.management import commands
|
|
6
12
|
|
|
7
13
|
# Overload deconstruct with our own.
|
|
8
14
|
models.Field.deconstruct = commands.custom_deconstruct
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Command(_Command):
|
|
18
|
+
def migration_progress_callback(self, action, migration=None, fake=False):
|
|
19
|
+
"""
|
|
20
|
+
Enhanced version of Django's built-in callback.
|
|
21
|
+
|
|
22
|
+
Differences in behavior:
|
|
23
|
+
- Measures and reports elapsed time whenever verbosity >= 1 (default value)
|
|
24
|
+
- Measures and reports affected record counts and elapsed time per record where applicable at verbosity >= 2.
|
|
25
|
+
- Aligns output to 80-character terminal width in most cases
|
|
26
|
+
|
|
27
|
+
Examples:
|
|
28
|
+
# nautobot-server migrate
|
|
29
|
+
Running migrations:
|
|
30
|
+
Applying dcim.0065_controller_capabilities_and_more... OK 0.10s
|
|
31
|
+
Applying wireless.0001_initial... OK 0.31s
|
|
32
|
+
Applying dcim.0066_controllermanageddevicegroup_radio_profi... OK 0.12s
|
|
33
|
+
|
|
34
|
+
# nautobot-server migrate -v=2 extras 0100
|
|
35
|
+
Operations to perform:
|
|
36
|
+
Target specific migration: 0100_fileproxy_job_result, from extras
|
|
37
|
+
Running migrations:
|
|
38
|
+
Rendering model states... DONE 19.10s
|
|
39
|
+
Unapplying ipam.0052_alter_ipaddress_index_together_and_mor... OK 0.10s
|
|
40
|
+
Affected ipam.ipaddress 75 rows 0.001s/record
|
|
41
|
+
Affected ipam.prefix 184 rows 0.000s/record
|
|
42
|
+
Affected ipam.vrf 20 rows 0.004s/record
|
|
43
|
+
Unapplying ipam.0051_added_optional_vrf_relationship_to_vdc... OK 0.10s
|
|
44
|
+
Affected ipam.vrf 20 rows 0.006s/record
|
|
45
|
+
Affected ipam.vrfdeviceassignment 140 rows 0.001s/record
|
|
46
|
+
Unapplying virtualization.0030_alter_virtualmachine_local_c... OK 0.30s
|
|
47
|
+
Affected virtualization.virtualmachine 0 rows
|
|
48
|
+
Affected virtualization.vminterface 0 rows
|
|
49
|
+
Unapplying virtualization.0029_add_role_field_to_interface_... OK 0.10s
|
|
50
|
+
Affected virtualization.vminterface 0 rows
|
|
51
|
+
"""
|
|
52
|
+
if self.verbosity < 1:
|
|
53
|
+
return
|
|
54
|
+
|
|
55
|
+
if action in ["apply_start", "render_start", "unapply_start"]:
|
|
56
|
+
self.start = time.monotonic()
|
|
57
|
+
self.affected_models = set()
|
|
58
|
+
self.affected_models_count = {}
|
|
59
|
+
self.migration = migration
|
|
60
|
+
if self.verbosity >= 2 and self.migration is not None:
|
|
61
|
+
for operation in self.migration.operations:
|
|
62
|
+
if isinstance(operation, FieldOperation):
|
|
63
|
+
self.affected_models.add((self.migration.app_label, operation.model_name.lower()))
|
|
64
|
+
elif isinstance(operation, ModelOperation):
|
|
65
|
+
self.affected_models.add((self.migration.app_label, operation.name.lower()))
|
|
66
|
+
|
|
67
|
+
for app_label, model_name in sorted(self.affected_models):
|
|
68
|
+
self.affected_models_count[f"{app_label}.{model_name}"] = 0
|
|
69
|
+
with contextlib.suppress(Exception):
|
|
70
|
+
model = apps.get_model(app_label, model_name)
|
|
71
|
+
self.affected_models_count[model._meta.label_lower] = model.objects.count()
|
|
72
|
+
|
|
73
|
+
if action == "apply_start":
|
|
74
|
+
msg = f" Applying {str(migration)[:50]}..."
|
|
75
|
+
elif action == "render_start":
|
|
76
|
+
msg = " Rendering model states..."
|
|
77
|
+
else:
|
|
78
|
+
msg = f" Unapplying {str(migration)[:48]}..."
|
|
79
|
+
self.stdout.write(f"{msg:<64}", ending="")
|
|
80
|
+
self.stdout.flush()
|
|
81
|
+
|
|
82
|
+
elif action in ["apply_success", "render_success", "unapply_success"]:
|
|
83
|
+
elapsed = time.monotonic() - self.start
|
|
84
|
+
outcome = "DONE" if action == "render_success" else "FAKED" if fake else "OK"
|
|
85
|
+
self.stdout.write(self.style.SUCCESS(f" {outcome:<5} {elapsed: 8.2f}s"))
|
|
86
|
+
if self.verbosity >= 2 and self.migration is not None:
|
|
87
|
+
for app_label, model_name in sorted(self.affected_models):
|
|
88
|
+
if self.affected_models_count[f"{app_label}.{model_name}"] == 0:
|
|
89
|
+
with contextlib.suppress(Exception):
|
|
90
|
+
model = apps.get_model(app_label, model_name)
|
|
91
|
+
self.affected_models_count[model._meta.label_lower] = model.objects.count()
|
|
92
|
+
|
|
93
|
+
for key, value in self.affected_models_count.items():
|
|
94
|
+
if value:
|
|
95
|
+
self.stdout.write(f" Affected {key:<38} {value: 8} rows {elapsed / value:6.3f}s/record")
|
|
96
|
+
else:
|
|
97
|
+
self.stdout.write(f" Affected {key:<38} {value: 8} rows")
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from django.core.cache import cache
|
|
2
2
|
from django.db.models import Case, When
|
|
3
3
|
from django.db.models.signals import post_delete, post_save
|
|
4
|
+
from tree_queries.compiler import TreeQuery
|
|
4
5
|
from tree_queries.models import TreeNode
|
|
5
6
|
from tree_queries.query import TreeManager as TreeManager_, TreeQuerySet as TreeQuerySet_
|
|
6
7
|
|
|
@@ -61,6 +62,22 @@ class TreeQuerySet(TreeQuerySet_, querysets.RestrictedQuerySet):
|
|
|
61
62
|
return deepest.tree_depth
|
|
62
63
|
return 0
|
|
63
64
|
|
|
65
|
+
def count(self):
|
|
66
|
+
"""Custom count method for optimization purposes.
|
|
67
|
+
|
|
68
|
+
TreeQuerySet instances in Nautobot are by default with tree fields. So if somewhere tree fields aren't
|
|
69
|
+
explicitly removed from the queryset and count is called, the whole tree is calculated. Since this is not
|
|
70
|
+
needed, this implementation calls `without_tree_fields` before issuing the count query and `with_tree_fields`
|
|
71
|
+
afterwards when applicable.
|
|
72
|
+
"""
|
|
73
|
+
should_have_tree_fields = isinstance(self.query, TreeQuery)
|
|
74
|
+
if should_have_tree_fields:
|
|
75
|
+
self.without_tree_fields()
|
|
76
|
+
count = super().count()
|
|
77
|
+
if should_have_tree_fields:
|
|
78
|
+
self.with_tree_fields()
|
|
79
|
+
return count
|
|
80
|
+
|
|
64
81
|
|
|
65
82
|
class TreeManager(TreeManager_, BaseManager.from_queryset(TreeQuerySet)):
|
|
66
83
|
"""
|
nautobot/core/settings.py
CHANGED
|
@@ -765,7 +765,7 @@ CONSTANCE_CONFIG = {
|
|
|
765
765
|
),
|
|
766
766
|
"JOB_CREATE_FILE_MAX_SIZE": ConstanceConfigItem(
|
|
767
767
|
default=10 << 20,
|
|
768
|
-
help_text=mark_safe(
|
|
768
|
+
help_text=mark_safe(
|
|
769
769
|
"Maximum size (in bytes) of any single file generated by a <code>Job.create_file()</code> call."
|
|
770
770
|
),
|
|
771
771
|
field_type=int,
|
|
@@ -798,7 +798,7 @@ CONSTANCE_CONFIG = {
|
|
|
798
798
|
),
|
|
799
799
|
"NETWORK_DRIVERS": ConstanceConfigItem(
|
|
800
800
|
default={},
|
|
801
|
-
help_text=mark_safe(
|
|
801
|
+
help_text=mark_safe(
|
|
802
802
|
"Extend or override default Platform.network_driver translations provided by "
|
|
803
803
|
'<a href="https://netutils.readthedocs.io/en/latest/user/lib_use_cases_lib_mapper/">netutils</a>. '
|
|
804
804
|
"Enter a dictionary in JSON format, for example:\n"
|
nautobot/core/settings.yaml
CHANGED
|
@@ -1487,9 +1487,9 @@ properties:
|
|
|
1487
1487
|
}
|
|
1488
1488
|
```
|
|
1489
1489
|
|
|
1490
|
-
The default top-level keys
|
|
1491
|
-
|
|
1492
|
-
|
|
1490
|
+
The default top-level keys consists of `ansible`, `hier_config`, `napalm`, etc, and comes from netutils, but
|
|
1491
|
+
you can also add additional keys if you have an alternative network driver that you want your Nautobot instance
|
|
1492
|
+
to include.
|
|
1493
1493
|
is_constance_config: true
|
|
1494
1494
|
type: "object"
|
|
1495
1495
|
version_added: "1.6.0"
|