nautobot 2.0.5__py3-none-any.whl → 2.1.0b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of nautobot might be problematic. Click here for more details.
- nautobot/circuits/navigation.py +0 -25
- nautobot/circuits/templates/circuits/circuit_retrieve.html +0 -9
- nautobot/circuits/templates/circuits/providernetwork_retrieve.html +0 -2
- nautobot/circuits/tests/test_filters.py +1 -0
- nautobot/core/api/serializers.py +15 -5
- nautobot/core/api/views.py +18 -19
- nautobot/core/choices.py +1 -1
- nautobot/core/filters.py +12 -4
- nautobot/core/jobs/__init__.py +125 -3
- nautobot/core/management/commands/generate_test_data.py +4 -1
- nautobot/core/models/fields.py +12 -2
- nautobot/core/settings.py +8 -7
- nautobot/core/templates/base_django.html +2 -2
- nautobot/core/templates/buttons/export.html +57 -30
- nautobot/core/templates/generic/object_list.html +2 -2
- nautobot/core/templates/generic/object_retrieve.html +8 -1
- nautobot/core/templates/home.html +5 -5
- nautobot/core/templates/inc/created_updated.html +2 -2
- nautobot/core/templates/inc/footer.html +2 -2
- nautobot/core/templates/inc/javascript.html +0 -10
- nautobot/core/templates/inc/media.html +2 -0
- nautobot/core/templates/inc/nav_menu.html +66 -68
- nautobot/core/templates/inc/object_details_advanced_panel.html +19 -0
- nautobot/core/templates/nautobot_config.py.j2 +10 -4
- nautobot/core/templates/panel_table.html +1 -1
- nautobot/core/templates/template.css +89 -0
- nautobot/core/templates/utilities/templatetags/table_config_form.html +1 -0
- nautobot/core/templatetags/buttons.py +7 -2
- nautobot/core/testing/views.py +34 -4
- nautobot/core/tests/integration/test_home.py +1 -43
- nautobot/core/tests/integration/test_navbar.py +10 -64
- nautobot/core/tests/integration/test_plugin_home.py +4 -5
- nautobot/core/tests/integration/test_plugin_navbar.py +20 -16
- nautobot/core/tests/integration/test_theme.py +4 -0
- nautobot/core/tests/test_api.py +14 -66
- nautobot/core/tests/test_filters.py +127 -0
- nautobot/core/tests/test_forms.py +1 -1
- nautobot/core/tests/test_graphql.py +165 -2
- nautobot/core/tests/test_jobs.py +112 -0
- nautobot/core/tests/test_openapi.py +6 -0
- nautobot/core/tests/test_views.py +11 -85
- nautobot/core/urls.py +6 -1
- nautobot/core/utils/lookup.py +28 -0
- nautobot/core/utils/requests.py +2 -3
- nautobot/core/views/__init__.py +3 -4
- nautobot/core/views/generic.py +9 -4
- nautobot/core/views/mixins.py +4 -2
- nautobot/core/views/renderers.py +5 -0
- nautobot/dcim/models/device_components.py +1 -0
- nautobot/dcim/navigation.py +10 -165
- nautobot/dcim/templates/dcim/location.html +1 -1
- nautobot/dcim/tests/features/locations.feature +143 -0
- nautobot/dcim/tests/test_api.py +1 -1
- nautobot/dcim/tests/test_filters.py +11 -3
- nautobot/extras/admin.py +1 -1
- nautobot/extras/api/serializers.py +33 -0
- nautobot/extras/api/urls.py +6 -0
- nautobot/extras/api/views.py +45 -6
- nautobot/extras/factory.py +28 -2
- nautobot/extras/filters/__init__.py +52 -0
- nautobot/extras/filters/mixins.py +4 -29
- nautobot/extras/forms/forms.py +43 -0
- nautobot/extras/jobs.py +31 -9
- nautobot/extras/migrations/0100_fileproxy_job_result.py +32 -0
- nautobot/extras/migrations/0101_externalintegration.py +61 -0
- nautobot/extras/migrations/0102_set_null_objectchange_contenttype.py +32 -0
- nautobot/extras/models/__init__.py +2 -0
- nautobot/extras/models/change_logging.py +2 -2
- nautobot/extras/models/models.py +96 -16
- nautobot/extras/navigation.py +17 -29
- nautobot/extras/signals.py +15 -0
- nautobot/extras/tables.py +27 -0
- nautobot/extras/templates/extras/externalintegration_retrieve.html +37 -0
- nautobot/extras/templates/extras/inc/jobresult.html +24 -0
- nautobot/extras/templates/extras/jobresult.html +24 -0
- nautobot/extras/test_jobs/file_output.py +16 -0
- nautobot/extras/tests/test_api.py +92 -0
- nautobot/extras/tests/test_filters.py +64 -2
- nautobot/extras/tests/test_jobs.py +39 -0
- nautobot/extras/tests/test_models.py +34 -0
- nautobot/extras/tests/test_views.py +22 -2
- nautobot/extras/urls.py +1 -0
- nautobot/extras/views.py +15 -0
- nautobot/ipam/forms.py +16 -0
- nautobot/ipam/models.py +3 -0
- nautobot/ipam/navigation.py +2 -59
- nautobot/ipam/templates/ipam/ipaddress.html +0 -9
- nautobot/ipam/templates/ipam/prefix.html +0 -9
- nautobot/ipam/tests/features/prefixes.feature +134 -0
- nautobot/ipam/tests/test_filters.py +5 -10
- nautobot/ipam/tests/test_views.py +8 -1
- nautobot/ipam/views.py +3 -0
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.css +191 -191
- 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 +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 +874 -881
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css.map +1 -1
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css +1 -1
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css.map +1 -1
- nautobot/project-static/css/base.css +135 -99
- nautobot/project-static/css/dark.css +65 -6
- nautobot/project-static/docs/404.html +44 -16
- nautobot/project-static/docs/apps/index.html +44 -16
- nautobot/project-static/docs/apps/nautobot-apps.html +44 -16
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +44 -16
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +44 -16
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +1597 -1457
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +44 -16
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +45 -17
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +44 -16
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +44 -16
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +44 -16
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +44 -16
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +353 -432
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +66 -38
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +44 -16
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +2154 -2307
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +807 -691
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +44 -16
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +44 -16
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +58 -30
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +3600 -3456
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +44 -16
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +44 -16
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +101 -75
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +3083 -3019
- nautobot/project-static/docs/development/apps/api/configuration-view.html +44 -16
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +44 -16
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +44 -16
- nautobot/project-static/docs/development/apps/api/models/global-search.html +44 -16
- nautobot/project-static/docs/development/apps/api/models/graphql.html +44 -16
- nautobot/project-static/docs/development/apps/api/models/index.html +44 -16
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +44 -16
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +44 -16
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +44 -16
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +44 -16
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +44 -16
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +44 -16
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +44 -16
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +44 -16
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +44 -16
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +44 -16
- nautobot/project-static/docs/development/apps/api/prometheus.html +44 -16
- nautobot/project-static/docs/development/apps/api/setup.html +44 -16
- nautobot/project-static/docs/development/apps/api/testing.html +44 -16
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +44 -16
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +44 -16
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +44 -16
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +44 -16
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-detail-views.html +44 -16
- nautobot/project-static/docs/development/apps/api/ui-extensions/tabs.html +44 -16
- nautobot/project-static/docs/development/apps/api/views/base-template.html +44 -16
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +44 -16
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +44 -16
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +44 -16
- nautobot/project-static/docs/development/apps/api/views/index.html +44 -16
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +44 -16
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +44 -16
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +44 -16
- nautobot/project-static/docs/development/apps/api/views/notes.html +44 -16
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +44 -16
- nautobot/project-static/docs/development/apps/api/views/urls.html +44 -16
- nautobot/project-static/docs/development/apps/api/views/view-overrides.html +44 -16
- nautobot/project-static/docs/development/apps/index.html +44 -16
- nautobot/project-static/docs/development/apps/migration/code-updates.html +44 -16
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +44 -16
- nautobot/project-static/docs/development/apps/migration/from-v1.html +44 -16
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +44 -16
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +44 -16
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +44 -16
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +44 -16
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +44 -16
- nautobot/project-static/docs/development/core/application-registry.html +44 -16
- nautobot/project-static/docs/development/core/best-practices.html +44 -16
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +44 -16
- nautobot/project-static/docs/development/core/extending-models.html +44 -16
- nautobot/project-static/docs/development/core/generic-views.html +44 -16
- nautobot/project-static/docs/development/core/getting-started.html +44 -16
- nautobot/project-static/docs/development/core/homepage.html +44 -16
- nautobot/project-static/docs/development/core/index.html +44 -16
- nautobot/project-static/docs/development/core/model-features.html +44 -16
- nautobot/project-static/docs/development/core/natural-keys.html +44 -16
- nautobot/project-static/docs/development/core/navigation-menu.html +44 -21
- nautobot/project-static/docs/development/core/react-ui.html +44 -16
- nautobot/project-static/docs/development/core/release-checklist.html +44 -16
- nautobot/project-static/docs/development/core/role-internals.html +44 -16
- nautobot/project-static/docs/development/core/style-guide.html +44 -16
- nautobot/project-static/docs/development/core/templates.html +44 -16
- nautobot/project-static/docs/development/core/testing.html +44 -16
- nautobot/project-static/docs/development/core/user-preferences.html +44 -16
- nautobot/project-static/docs/development/index.html +44 -16
- nautobot/project-static/docs/development/jobs/index.html +280 -234
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +44 -16
- nautobot/project-static/docs/index.html +44 -16
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/release-notes/index.html +47 -19
- nautobot/project-static/docs/release-notes/version-1.0.html +44 -16
- nautobot/project-static/docs/release-notes/version-1.1.html +44 -16
- nautobot/project-static/docs/release-notes/version-1.2.html +44 -16
- nautobot/project-static/docs/release-notes/version-1.3.html +44 -16
- nautobot/project-static/docs/release-notes/version-1.4.html +44 -16
- nautobot/project-static/docs/release-notes/version-1.5.html +44 -16
- nautobot/project-static/docs/release-notes/version-1.6.html +44 -16
- nautobot/project-static/docs/release-notes/version-2.0.html +47 -19
- nautobot/project-static/docs/release-notes/version-2.1.html +5724 -0
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +247 -237
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +44 -16
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +44 -16
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +44 -16
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +44 -16
- nautobot/project-static/docs/user-guide/administration/configuration/node-configuration.html +44 -16
- nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +109 -43
- nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +44 -16
- nautobot/project-static/docs/user-guide/administration/guides/caching.html +44 -16
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +44 -16
- nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +44 -16
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +44 -16
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +44 -16
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +44 -16
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +48 -19
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +44 -16
- nautobot/project-static/docs/user-guide/administration/installation/docker.html +44 -16
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +44 -16
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +44 -16
- nautobot/project-static/docs/user-guide/administration/installation/index.html +44 -16
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +44 -16
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +44 -16
- nautobot/project-static/docs/user-guide/administration/installation/selinux-troubleshooting.html +44 -16
- nautobot/project-static/docs/user-guide/administration/installation/services.html +44 -16
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +44 -16
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +44 -16
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +44 -16
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +44 -16
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +44 -16
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +44 -16
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +44 -16
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +44 -16
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +44 -16
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +44 -16
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +44 -16
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +44 -16
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +44 -16
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +44 -16
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +44 -16
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +44 -16
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +44 -16
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +44 -16
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +44 -16
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +44 -16
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +44 -16
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +44 -16
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +44 -16
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +44 -16
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +44 -16
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +44 -16
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +44 -16
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +44 -16
- nautobot/project-static/docs/user-guide/index.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +110 -16
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +47 -19
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +5359 -0
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +47 -19
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +113 -44
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +44 -16
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +44 -16
- nautobot/project-static/fonts/UFL.txt +96 -0
- nautobot/project-static/fonts/Ubuntu-Bold.woff2 +0 -0
- nautobot/project-static/fonts/Ubuntu-BoldItalic.woff2 +0 -0
- nautobot/project-static/fonts/Ubuntu-Italic.woff2 +0 -0
- nautobot/project-static/fonts/Ubuntu-Medium.woff2 +0 -0
- nautobot/project-static/fonts/Ubuntu-MediumItalic.woff2 +0 -0
- nautobot/project-static/fonts/Ubuntu-Regular.woff2 +0 -0
- nautobot/project-static/fonts/UbuntuMono-Bold.woff2 +0 -0
- nautobot/project-static/fonts/UbuntuMono-BoldItalic.woff2 +0 -0
- nautobot/project-static/fonts/UbuntuMono-Italic.woff2 +0 -0
- nautobot/project-static/fonts/UbuntuMono-Regular.woff2 +0 -0
- nautobot/project-static/img/dark-theme.png +0 -0
- nautobot/project-static/img/light-theme.png +0 -0
- nautobot/project-static/img/nautobot_chevron.svg +5 -0
- nautobot/project-static/img/nautobot_chevron_header.svg +5 -0
- nautobot/project-static/img/system-theme.png +0 -0
- nautobot/tenancy/navigation.py +0 -13
- nautobot/ui/package-lock.json +2 -2
- nautobot/ui/package.json +1 -1
- nautobot/users/admin.py +44 -0
- nautobot/users/migrations/0007_alter_objectpermission_object_types.py +33 -0
- nautobot/users/models.py +3 -2
- nautobot/virtualization/navigation.py +1 -33
- nautobot/virtualization/tests/test_api.py +1 -1
- nautobot/virtualization/tests/test_filters.py +1 -1
- {nautobot-2.0.5.dist-info → nautobot-2.1.0b1.dist-info}/METADATA +1 -1
- {nautobot-2.0.5.dist-info → nautobot-2.1.0b1.dist-info}/RECORD +376 -351
- {nautobot-2.0.5.dist-info → nautobot-2.1.0b1.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.0.5.dist-info → nautobot-2.1.0b1.dist-info}/WHEEL +0 -0
- {nautobot-2.0.5.dist-info → nautobot-2.1.0b1.dist-info}/entry_points.txt +0 -0
|
@@ -7,6 +7,7 @@ from unittest import mock
|
|
|
7
7
|
import uuid
|
|
8
8
|
import tempfile
|
|
9
9
|
|
|
10
|
+
from django.conf import settings
|
|
10
11
|
from django.contrib.contenttypes.models import ContentType
|
|
11
12
|
from django.core.files.uploadedfile import SimpleUploadedFile
|
|
12
13
|
from django.core.management import call_command
|
|
@@ -582,6 +583,44 @@ class JobFileUploadTest(TransactionTestCase):
|
|
|
582
583
|
self.assertEqual(models.FileProxy.objects.count(), 0)
|
|
583
584
|
|
|
584
585
|
|
|
586
|
+
class JobFileOutputTest(TransactionTestCase):
|
|
587
|
+
"""Test a job that outputs files."""
|
|
588
|
+
|
|
589
|
+
databases = ("default", "job_logs")
|
|
590
|
+
|
|
591
|
+
@override_settings(
|
|
592
|
+
MEDIA_ROOT=tempfile.gettempdir(),
|
|
593
|
+
)
|
|
594
|
+
def test_output_file_to_database(self):
|
|
595
|
+
module = "file_output"
|
|
596
|
+
name = "FileOutputJob"
|
|
597
|
+
data = {"lines": 3}
|
|
598
|
+
job_result = create_job_result_and_run_job(module, name, **data)
|
|
599
|
+
|
|
600
|
+
self.assertEqual(job_result.status, JobResultStatusChoices.STATUS_SUCCESS, job_result.traceback)
|
|
601
|
+
# JobResult should have one attached file
|
|
602
|
+
self.assertEqual(1, job_result.files.count())
|
|
603
|
+
self.assertEqual(job_result.files.first().name, "output.txt")
|
|
604
|
+
self.assertEqual(job_result.files.first().file.read().decode("utf-8"), "Hello World!\n" * 3)
|
|
605
|
+
# File shouldn't exist on filesystem
|
|
606
|
+
self.assertFalse(Path(settings.MEDIA_ROOT, "files", "output.txt").exists())
|
|
607
|
+
self.assertFalse(Path(settings.MEDIA_ROOT, "files", f"{job_result.files.first().pk}-output.txt").exists())
|
|
608
|
+
# File should exist in DB
|
|
609
|
+
# `filename` value is weird, see https://github.com/victor-o-silva/db_file_storage/issues/22
|
|
610
|
+
models.FileAttachment.objects.get(filename="extras.FileAttachment/bytes/filename/mimetype/output.txt")
|
|
611
|
+
|
|
612
|
+
# Make sure cleanup is successful
|
|
613
|
+
job_result.delete()
|
|
614
|
+
with self.assertRaises(models.FileProxy.DoesNotExist):
|
|
615
|
+
models.FileProxy.objects.get(name="output.txt")
|
|
616
|
+
with self.assertRaises(models.FileAttachment.DoesNotExist):
|
|
617
|
+
models.FileAttachment.objects.get(filename="extras.FileAttachment/bytes/filename/mimetype/output.txt")
|
|
618
|
+
|
|
619
|
+
# It would be great to also test the output-to-filesystem case when using JOB_FILE_IO_STORAGE=FileSystemStorage;
|
|
620
|
+
# unfortunately with FileField(storage=callable), the callable gets evaluated only at declaration time, not at
|
|
621
|
+
# usage/runtime, so override_settings(JOB_FILE_IO_STORAGE) doesn't work the way you'd hope it would.
|
|
622
|
+
|
|
623
|
+
|
|
585
624
|
class RunJobManagementCommandTest(TransactionTestCase):
|
|
586
625
|
"""Test cases for the `nautobot-server runjob` management command."""
|
|
587
626
|
|
|
@@ -48,6 +48,7 @@ from nautobot.extras.models import (
|
|
|
48
48
|
ConfigContextSchema,
|
|
49
49
|
DynamicGroup,
|
|
50
50
|
ExportTemplate,
|
|
51
|
+
ExternalIntegration,
|
|
51
52
|
FileAttachment,
|
|
52
53
|
FileProxy,
|
|
53
54
|
GitRepository,
|
|
@@ -776,6 +777,39 @@ class ExportTemplateTest(ModelTestCases.BaseModelTestCase):
|
|
|
776
777
|
nonduplicate_template.validated_save()
|
|
777
778
|
|
|
778
779
|
|
|
780
|
+
class ExternalIntegrationTest(ModelTestCases.BaseModelTestCase):
|
|
781
|
+
"""
|
|
782
|
+
Tests for the ExternalIntegration model class.
|
|
783
|
+
"""
|
|
784
|
+
|
|
785
|
+
model = ExternalIntegration
|
|
786
|
+
|
|
787
|
+
def test_remote_url_validation(self):
|
|
788
|
+
with self.assertRaises(ValidationError):
|
|
789
|
+
ei = ExternalIntegration(
|
|
790
|
+
name="Test Integration",
|
|
791
|
+
remote_url="foo://localhost",
|
|
792
|
+
)
|
|
793
|
+
ei.validated_save()
|
|
794
|
+
|
|
795
|
+
ei.remote_url = "http://localhost"
|
|
796
|
+
ei.validated_save()
|
|
797
|
+
|
|
798
|
+
def test_timeout_validation(self):
|
|
799
|
+
with self.assertRaises(ValidationError):
|
|
800
|
+
ei = ExternalIntegration(
|
|
801
|
+
name="Test Integration",
|
|
802
|
+
remote_url="http://localhost",
|
|
803
|
+
timeout=-1,
|
|
804
|
+
)
|
|
805
|
+
ei.validated_save()
|
|
806
|
+
|
|
807
|
+
ei.timeout = 0
|
|
808
|
+
ei.validated_save()
|
|
809
|
+
ei.timeout = 65536
|
|
810
|
+
ei.validated_save()
|
|
811
|
+
|
|
812
|
+
|
|
779
813
|
class FileProxyTest(ModelTestCases.BaseModelTestCase):
|
|
780
814
|
model = FileProxy
|
|
781
815
|
|
|
@@ -33,6 +33,7 @@ from nautobot.extras.models import (
|
|
|
33
33
|
CustomLink,
|
|
34
34
|
DynamicGroup,
|
|
35
35
|
ExportTemplate,
|
|
36
|
+
ExternalIntegration,
|
|
36
37
|
GitRepository,
|
|
37
38
|
GraphQLQuery,
|
|
38
39
|
Job,
|
|
@@ -693,6 +694,25 @@ class ExportTemplateTestCase(
|
|
|
693
694
|
}
|
|
694
695
|
|
|
695
696
|
|
|
697
|
+
class ExternalIntegrationTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
698
|
+
model = ExternalIntegration
|
|
699
|
+
bulk_edit_data = {"timeout": 10, "verify_ssl": True, "extra_config": r"{}"}
|
|
700
|
+
csv_data = (
|
|
701
|
+
"name,remote_url,verify_ssl,timeout",
|
|
702
|
+
"Test External Integration 1,https://example.com/test1/,False,10",
|
|
703
|
+
"Test External Integration 2,https://example.com/test2/,True,20",
|
|
704
|
+
"Test External Integration 3,https://example.com/test3/,False,30",
|
|
705
|
+
)
|
|
706
|
+
form_data = {
|
|
707
|
+
"name": "Test External Integration",
|
|
708
|
+
"remote_url": "https://example.com/test1/",
|
|
709
|
+
"verify_ssl": False,
|
|
710
|
+
"secrets_group": None,
|
|
711
|
+
"timeout": 10,
|
|
712
|
+
"extra_config": '{"foo": "bar"}',
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
|
|
696
716
|
class GitRepositoryTestCase(
|
|
697
717
|
ViewTestCases.BulkDeleteObjectsViewTestCase,
|
|
698
718
|
ViewTestCases.BulkImportObjectsViewTestCase,
|
|
@@ -1936,7 +1956,7 @@ class JobTestCase(
|
|
|
1936
1956
|
content = extract_page_body(response.content.decode(response.charset))
|
|
1937
1957
|
|
|
1938
1958
|
self.assertHttpStatus(response, 200)
|
|
1939
|
-
self.assertIn(f"
|
|
1959
|
+
self.assertIn(f"{instance.name} - Change Log", content)
|
|
1940
1960
|
|
|
1941
1961
|
|
|
1942
1962
|
class JobButtonTestCase(
|
|
@@ -2281,7 +2301,7 @@ class RelationshipAssociationTestCase(
|
|
|
2281
2301
|
),
|
|
2282
2302
|
)
|
|
2283
2303
|
vlan_status = Status.objects.get_for_model(VLAN).first()
|
|
2284
|
-
vlan_group = VLANGroup.objects.
|
|
2304
|
+
vlan_group = VLANGroup.objects.create(name="Test VLANGroup 1")
|
|
2285
2305
|
vlans = (
|
|
2286
2306
|
VLAN.objects.create(vid=1, name="VLAN 1", status=vlan_status, vlan_group=vlan_group),
|
|
2287
2307
|
VLAN.objects.create(vid=2, name="VLAN 2", status=vlan_status, vlan_group=vlan_group),
|
nautobot/extras/urls.py
CHANGED
|
@@ -26,6 +26,7 @@ from nautobot.extras.models import (
|
|
|
26
26
|
app_name = "extras"
|
|
27
27
|
|
|
28
28
|
router = NautobotUIViewSetRouter()
|
|
29
|
+
router.register("external-integrations", views.ExternalIntegrationUIViewSet)
|
|
29
30
|
router.register("job-buttons", views.JobButtonUIViewSet)
|
|
30
31
|
router.register("roles", views.RoleUIViewSet)
|
|
31
32
|
|
nautobot/extras/views.py
CHANGED
|
@@ -58,6 +58,7 @@ from .models import (
|
|
|
58
58
|
CustomLink,
|
|
59
59
|
DynamicGroup,
|
|
60
60
|
ExportTemplate,
|
|
61
|
+
ExternalIntegration,
|
|
61
62
|
GitRepository,
|
|
62
63
|
GraphQLQuery,
|
|
63
64
|
ImageAttachment,
|
|
@@ -792,6 +793,20 @@ class ExportTemplateBulkDeleteView(generic.BulkDeleteView):
|
|
|
792
793
|
table = tables.ExportTemplateTable
|
|
793
794
|
|
|
794
795
|
|
|
796
|
+
#
|
|
797
|
+
# External integrations
|
|
798
|
+
#
|
|
799
|
+
|
|
800
|
+
|
|
801
|
+
class ExternalIntegrationUIViewSet(NautobotUIViewSet):
|
|
802
|
+
bulk_update_form_class = forms.ExternalIntegrationBulkEditForm
|
|
803
|
+
filterset_class = filters.ExternalIntegrationFilterSet
|
|
804
|
+
form_class = forms.ExternalIntegrationForm
|
|
805
|
+
queryset = ExternalIntegration.objects.select_related("secrets_group")
|
|
806
|
+
serializer_class = serializers.ExternalIntegrationSerializer
|
|
807
|
+
table_class = tables.ExternalIntegrationTable
|
|
808
|
+
|
|
809
|
+
|
|
795
810
|
#
|
|
796
811
|
# Git repositories
|
|
797
812
|
#
|
nautobot/ipam/forms.py
CHANGED
|
@@ -75,6 +75,22 @@ class NamespaceForm(LocatableModelFormMixin, NautobotModelForm):
|
|
|
75
75
|
fields = ["name", "description", "location"]
|
|
76
76
|
|
|
77
77
|
|
|
78
|
+
class NamespaceBulkEditForm(
|
|
79
|
+
TagsBulkEditFormMixin,
|
|
80
|
+
LocatableModelBulkEditFormMixin,
|
|
81
|
+
NautobotBulkEditForm,
|
|
82
|
+
):
|
|
83
|
+
pk = forms.ModelMultipleChoiceField(queryset=Namespace.objects.all(), widget=forms.MultipleHiddenInput())
|
|
84
|
+
description = forms.CharField(max_length=200, required=False)
|
|
85
|
+
|
|
86
|
+
class Meta:
|
|
87
|
+
model = Namespace
|
|
88
|
+
nullable_fields = [
|
|
89
|
+
"description",
|
|
90
|
+
"location",
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
|
|
78
94
|
#
|
|
79
95
|
# VRFs
|
|
80
96
|
#
|
nautobot/ipam/models.py
CHANGED
|
@@ -257,6 +257,7 @@ class VRF(PrimaryModel):
|
|
|
257
257
|
return instance.delete()
|
|
258
258
|
|
|
259
259
|
|
|
260
|
+
@extras_features("graphql")
|
|
260
261
|
class VRFDeviceAssignment(BaseModel):
|
|
261
262
|
vrf = models.ForeignKey("ipam.VRF", on_delete=models.CASCADE, related_name="device_assignments")
|
|
262
263
|
device = models.ForeignKey(
|
|
@@ -306,6 +307,7 @@ class VRFDeviceAssignment(BaseModel):
|
|
|
306
307
|
raise ValidationError("A VRF must be associated with either a device or a virtual machine.")
|
|
307
308
|
|
|
308
309
|
|
|
310
|
+
@extras_features("graphql")
|
|
309
311
|
class VRFPrefixAssignment(BaseModel):
|
|
310
312
|
vrf = models.ForeignKey("ipam.VRF", on_delete=models.CASCADE, related_name="+")
|
|
311
313
|
prefix = models.ForeignKey("ipam.Prefix", on_delete=models.CASCADE, related_name="vrf_assignments")
|
|
@@ -1189,6 +1191,7 @@ class IPAddress(PrimaryModel):
|
|
|
1189
1191
|
return f"Multiple IPAddress objects specify this object (pk: {self.obj.pk}) as nat_inside. Please refer to nat_outside_list."
|
|
1190
1192
|
|
|
1191
1193
|
|
|
1194
|
+
@extras_features("graphql")
|
|
1192
1195
|
class IPAddressToInterface(BaseModel):
|
|
1193
1196
|
ip_address = models.ForeignKey("ipam.IPAddress", on_delete=models.CASCADE, related_name="+")
|
|
1194
1197
|
interface = models.ForeignKey(
|
nautobot/ipam/navigation.py
CHANGED
|
@@ -5,7 +5,6 @@ from nautobot.core.apps import (
|
|
|
5
5
|
NavMenuAddButton,
|
|
6
6
|
NavMenuGroup,
|
|
7
7
|
NavMenuItem,
|
|
8
|
-
NavMenuImportButton,
|
|
9
8
|
NavMenuTab,
|
|
10
9
|
)
|
|
11
10
|
|
|
@@ -33,12 +32,6 @@ menu_items = (
|
|
|
33
32
|
"ipam.add_ipaddress",
|
|
34
33
|
],
|
|
35
34
|
),
|
|
36
|
-
NavMenuImportButton(
|
|
37
|
-
link="ipam:ipaddress_import",
|
|
38
|
-
permissions=[
|
|
39
|
-
"ipam.add_ipaddress",
|
|
40
|
-
],
|
|
41
|
-
),
|
|
42
35
|
),
|
|
43
36
|
),
|
|
44
37
|
NavMenuItem(
|
|
@@ -48,14 +41,7 @@ menu_items = (
|
|
|
48
41
|
permissions=[
|
|
49
42
|
"ipam.add_ipaddresstointerface",
|
|
50
43
|
],
|
|
51
|
-
buttons=(
|
|
52
|
-
NavMenuImportButton(
|
|
53
|
-
link="ipam:ipaddresstointerface_import",
|
|
54
|
-
permissions=[
|
|
55
|
-
"ipam.add_ipaddresstointerface",
|
|
56
|
-
],
|
|
57
|
-
),
|
|
58
|
-
),
|
|
44
|
+
buttons=(),
|
|
59
45
|
),
|
|
60
46
|
),
|
|
61
47
|
),
|
|
@@ -77,12 +63,6 @@ menu_items = (
|
|
|
77
63
|
"ipam.add_prefix",
|
|
78
64
|
],
|
|
79
65
|
),
|
|
80
|
-
NavMenuImportButton(
|
|
81
|
-
link="ipam:prefix_import",
|
|
82
|
-
permissions=[
|
|
83
|
-
"ipam.add_prefix",
|
|
84
|
-
],
|
|
85
|
-
),
|
|
86
66
|
),
|
|
87
67
|
),
|
|
88
68
|
),
|
|
@@ -105,12 +85,6 @@ menu_items = (
|
|
|
105
85
|
"ipam.add_rir",
|
|
106
86
|
],
|
|
107
87
|
),
|
|
108
|
-
NavMenuImportButton(
|
|
109
|
-
link="ipam:rir_import",
|
|
110
|
-
permissions=[
|
|
111
|
-
"ipam.add_rir",
|
|
112
|
-
],
|
|
113
|
-
),
|
|
114
88
|
),
|
|
115
89
|
),
|
|
116
90
|
),
|
|
@@ -149,12 +123,6 @@ menu_items = (
|
|
|
149
123
|
"ipam.add_vrf",
|
|
150
124
|
],
|
|
151
125
|
),
|
|
152
|
-
NavMenuImportButton(
|
|
153
|
-
link="ipam:vrf_import",
|
|
154
|
-
permissions=[
|
|
155
|
-
"ipam.add_vrf",
|
|
156
|
-
],
|
|
157
|
-
),
|
|
158
126
|
),
|
|
159
127
|
),
|
|
160
128
|
NavMenuItem(
|
|
@@ -171,12 +139,6 @@ menu_items = (
|
|
|
171
139
|
"ipam.add_routetarget",
|
|
172
140
|
],
|
|
173
141
|
),
|
|
174
|
-
NavMenuImportButton(
|
|
175
|
-
link="ipam:routetarget_import",
|
|
176
|
-
permissions=[
|
|
177
|
-
"ipam.add_routetarget",
|
|
178
|
-
],
|
|
179
|
-
),
|
|
180
142
|
),
|
|
181
143
|
),
|
|
182
144
|
),
|
|
@@ -199,12 +161,6 @@ menu_items = (
|
|
|
199
161
|
"ipam.add_vlan",
|
|
200
162
|
],
|
|
201
163
|
),
|
|
202
|
-
NavMenuImportButton(
|
|
203
|
-
link="ipam:vlan_import",
|
|
204
|
-
permissions=[
|
|
205
|
-
"ipam.add_vlan",
|
|
206
|
-
],
|
|
207
|
-
),
|
|
208
164
|
),
|
|
209
165
|
),
|
|
210
166
|
NavMenuItem(
|
|
@@ -221,12 +177,6 @@ menu_items = (
|
|
|
221
177
|
"ipam.add_vlangroup",
|
|
222
178
|
],
|
|
223
179
|
),
|
|
224
|
-
NavMenuImportButton(
|
|
225
|
-
link="ipam:vlangroup_import",
|
|
226
|
-
permissions=[
|
|
227
|
-
"ipam.add_vlangroup",
|
|
228
|
-
],
|
|
229
|
-
),
|
|
230
180
|
),
|
|
231
181
|
),
|
|
232
182
|
),
|
|
@@ -242,14 +192,7 @@ menu_items = (
|
|
|
242
192
|
permissions=[
|
|
243
193
|
"ipam.view_service",
|
|
244
194
|
],
|
|
245
|
-
buttons=(
|
|
246
|
-
NavMenuImportButton(
|
|
247
|
-
link="ipam:service_import",
|
|
248
|
-
permissions=[
|
|
249
|
-
"ipam.add_service",
|
|
250
|
-
],
|
|
251
|
-
),
|
|
252
|
-
),
|
|
195
|
+
buttons=(),
|
|
253
196
|
),
|
|
254
197
|
),
|
|
255
198
|
),
|
|
@@ -6,15 +6,6 @@
|
|
|
6
6
|
<li>{{ object.parent.namespace|hyperlinked_object }}</li>
|
|
7
7
|
{% endblock extra_breadcrumbs %}
|
|
8
8
|
|
|
9
|
-
{% block masthead %}
|
|
10
|
-
<h1>
|
|
11
|
-
<span class="hover_copy"><span id="copy_title">{{ object }}</span><button type="button" class="btn btn-inline btn-default hover_copy_button" data-clipboard-target="#copy_title">
|
|
12
|
-
<span class="mdi mdi-content-copy"></span>
|
|
13
|
-
</button>
|
|
14
|
-
</span>
|
|
15
|
-
</h1>
|
|
16
|
-
{% endblock masthead %}
|
|
17
|
-
|
|
18
9
|
{% block extra_nav_tabs %}
|
|
19
10
|
{% with interface_count=object.interfaces.count %}
|
|
20
11
|
{% if interface_count %}
|
|
@@ -9,15 +9,6 @@
|
|
|
9
9
|
<li>{{ object|hyperlinked_object }}</li>
|
|
10
10
|
{% endblock breadcrumbs %}
|
|
11
11
|
|
|
12
|
-
{% block masthead %}
|
|
13
|
-
<h1>
|
|
14
|
-
<span class="hover_copy"><span id="copy_title">{{ object }}</span><button type="button" class="btn btn-inline btn-default hover_copy_button" data-clipboard-target="#copy_title">
|
|
15
|
-
<span class="mdi mdi-content-copy"></span>
|
|
16
|
-
</button>
|
|
17
|
-
</span>
|
|
18
|
-
</h1>
|
|
19
|
-
{% endblock masthead %}
|
|
20
|
-
|
|
21
12
|
{% block extra_buttons %}
|
|
22
13
|
{% if perms.ipam.add_prefix and active_tab == 'prefixes' and first_available_prefix %}
|
|
23
14
|
<a href="{% url 'ipam:prefix_add' %}?prefix={{ first_available_prefix }}&namespace={{ object.namespace.pk }}&location={{ object.location.pk }}&tenant_group={{ object.tenant.tenant_group.pk }}&tenant={{ object.tenant.pk }}" class="btn btn-success">
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
Feature: Prefixes
|
|
2
|
+
In order to manage my network IPAM data,
|
|
3
|
+
As a Network Engineer
|
|
4
|
+
I want to record in Nautobot an appropriate set of Prefixes and related data.
|
|
5
|
+
|
|
6
|
+
Background:
|
|
7
|
+
Given I have appropriate Nautobot permissions:
|
|
8
|
+
| model | permissions |
|
|
9
|
+
| ipam.namespace | add,change,delete,view |
|
|
10
|
+
| ipam.prefix | add,change,delete,view |
|
|
11
|
+
And I am logged in to Nautobot
|
|
12
|
+
|
|
13
|
+
Scenario: Creating a set of Prefixes in a custom Namespace
|
|
14
|
+
When I navigate to the "Add Namespace" view
|
|
15
|
+
And I make the following form entries:
|
|
16
|
+
| name | description |
|
|
17
|
+
| CORP | Corporate network |
|
|
18
|
+
And I submit the form
|
|
19
|
+
Then a Namespace exists in Nautobot with the following properties:
|
|
20
|
+
| name | description |
|
|
21
|
+
| CORP | Corporate network |
|
|
22
|
+
And Nautobot shows the "Namespace Detail" view for the Namespace with name "CORP"
|
|
23
|
+
# TODO: it would be nice to have the ability to create a Prefix directly from the Namespace detail view?
|
|
24
|
+
|
|
25
|
+
When I navigate to the "Add Prefix" view
|
|
26
|
+
And I make the following form entries:
|
|
27
|
+
| prefix | namespace | type | status |
|
|
28
|
+
| 10.0.0.0/8 | CORP | Container | Active |
|
|
29
|
+
And I submit the form
|
|
30
|
+
Then a Prefix exists in Nautobot with the following properties:
|
|
31
|
+
| prefix | namespace | type | status | parent |
|
|
32
|
+
| 10.0.0.0/8 | CORP | Container | Active | None |
|
|
33
|
+
And Nautobot shows the "Prefix Detail" view for the Prefix with prefix "10.0.0.0/8" and namespace "CORP"
|
|
34
|
+
And the view shows a "Utilization" of "0%"
|
|
35
|
+
|
|
36
|
+
When I click the "Clone" button
|
|
37
|
+
Then Nautobot shows the "Add Prefix" view with the following presets:
|
|
38
|
+
| namespace | type | status |
|
|
39
|
+
| CORP | Container | Active |
|
|
40
|
+
When I make the following form entries:
|
|
41
|
+
| prefix | type |
|
|
42
|
+
| 10.0.100.0/24 | Network |
|
|
43
|
+
And I submit the form
|
|
44
|
+
Then a Prefix exists in Nautobot with the following properties:
|
|
45
|
+
| prefix | namespace | type | status | parent |
|
|
46
|
+
| 10.0.100.0/24 | CORP | Network | Active | 10.0.0.0/8 |
|
|
47
|
+
And Nautobot shows the "Prefix Detail" view for the Prefix with prefix "10.0.100.0/24" and namespace "CORP"
|
|
48
|
+
And the view shows a "Utilization" of "0%"
|
|
49
|
+
And the table "Parent Prefixes" includes rows with the following properties:
|
|
50
|
+
| prefix | type |
|
|
51
|
+
| 10.0.0.0/8 | Container |
|
|
52
|
+
|
|
53
|
+
When I click the "Clone" button
|
|
54
|
+
Then Nautobot shows the "Add Prefix" view with the following presets:
|
|
55
|
+
| namespace | type | status |
|
|
56
|
+
| CORP | Network | Active |
|
|
57
|
+
When I make the following form entries:
|
|
58
|
+
| prefix | type |
|
|
59
|
+
| 10.0.0.0/16 | Container |
|
|
60
|
+
And I submit the form
|
|
61
|
+
Then a Prefix exists in Nautobot with the following properties:
|
|
62
|
+
| prefix | namespace | type | status | parent |
|
|
63
|
+
| 10.0.0.0/16 | CORP | Container | Active | 10.0.0.0/8 |
|
|
64
|
+
And Nautobot shows the "Prefix Detail" view for the Prefix with prefix "10.0.0.0/16" and namespace "CORP"
|
|
65
|
+
And the table "Parent Prefixes" includes rows with the following properties:
|
|
66
|
+
| prefix | type |
|
|
67
|
+
| 10.0.0.0/8 | Container |
|
|
68
|
+
And the tab "Child Prefixes" includes a badge with the number "1"
|
|
69
|
+
|
|
70
|
+
When I click the "Child Prefixes" tab
|
|
71
|
+
Then Nautobot shows the "Child Prefixes" tab
|
|
72
|
+
And the table "Child Prefixes" includes rows with the following properties:
|
|
73
|
+
| prefix | type | status |
|
|
74
|
+
| 10.0.0.0/18 | — | — |
|
|
75
|
+
| 10.0.64.0/19 | — | — |
|
|
76
|
+
| 10.0.96.0/22 | — | — |
|
|
77
|
+
| 10.0.100.0/24 | Network | Active |
|
|
78
|
+
|
|
79
|
+
When I click the "10.0.96.0/22" link
|
|
80
|
+
Then Nautobot shows the "Add Prefix" view with the following presets:
|
|
81
|
+
| prefix | namespace |
|
|
82
|
+
| 10.0.96.0/22 | CORP |
|
|
83
|
+
When I make the following form entries:
|
|
84
|
+
| prefix | type | status |
|
|
85
|
+
| 10.0.96.0/20 | Container | Active |
|
|
86
|
+
And I submit the form
|
|
87
|
+
Then a Prefix exists in Nautobot with the following properties:
|
|
88
|
+
| prefix | namespace | type | status | parent |
|
|
89
|
+
| 10.0.96.0/20 | CORP | Container | Active | 10.0.0.0/16 |
|
|
90
|
+
And Nautobot shows the "Prefix Detail" view for the Prefix with prefix "10.0.96.0/20" and namespace "CORP"
|
|
91
|
+
And the view shows a "Utilization" of "6%"
|
|
92
|
+
And the table "Parent Prefixes" includes rows with the following properties:
|
|
93
|
+
| prefix | type | status |
|
|
94
|
+
| 10.0.0.0/8 | Container | Active |
|
|
95
|
+
| 10.0.0.0/16 | Container | Active |
|
|
96
|
+
And the tab "Child Prefixes" includes a badge with the number "1"
|
|
97
|
+
|
|
98
|
+
When I navigate to the "Prefix List" view
|
|
99
|
+
And specify a filter of "?namespace=CORP"
|
|
100
|
+
Then the table "Prefixes" includes rows with the following properties:
|
|
101
|
+
| prefix | namespace | type | status | children | utilization |
|
|
102
|
+
| 10.0.0.0/8 | CORP | Container | Active | 3 | 0% |
|
|
103
|
+
| 10.0.0.0/16 | CORP | Container | Active | 2 | 6% |
|
|
104
|
+
| 10.0.96.0/20 | CORP | Container | Active | 1 | 6% |
|
|
105
|
+
| 10.0.100.0/24 | CORP | Network | Active | 0 | 0% |
|
|
106
|
+
|
|
107
|
+
When I click the "Import" button
|
|
108
|
+
Then Nautobot shows the "Prefix Bulk Import" view
|
|
109
|
+
When I enter the following into the "csv_data" field:
|
|
110
|
+
"""
|
|
111
|
+
prefix,status__name,type,namespace__name
|
|
112
|
+
10.0.101.0/24,Reserved,network,CORP
|
|
113
|
+
10.0.102.0/24,Reserved,network,CORP
|
|
114
|
+
10.1.0.0/16,Reserved,container,CORP
|
|
115
|
+
"""
|
|
116
|
+
And I submit the form
|
|
117
|
+
Then several Prefixes exist in Nautobot with the following properties:
|
|
118
|
+
| prefix | namespace | type | status | parent |
|
|
119
|
+
| 10.0.101.0/24 | CORP | Network | Reserved | 10.0.96.0/20 |
|
|
120
|
+
| 10.0.102.0/24 | CORP | Network | Reserved | 10.0.96.0/20 |
|
|
121
|
+
| 10.1.0.0/16 | CORP | Container | Reserved | 10.0.0.0/8 |
|
|
122
|
+
And Nautobot shows the "Prefix Import Completed" view with 3 rows
|
|
123
|
+
When I click the "View All" button
|
|
124
|
+
Then Nautobot shows the "Prefix List" view
|
|
125
|
+
When I specify a filter of "?namespace=CORP"
|
|
126
|
+
Then the table "Prefixes" includes rows with the following properties:
|
|
127
|
+
| prefix | namespace | type | status | children | utilization |
|
|
128
|
+
| 10.0.0.0/8 | CORP | Container | Active | 6 | 0% |
|
|
129
|
+
| 10.0.0.0/16 | CORP | Container | Active | 4 | 6% |
|
|
130
|
+
| 10.0.96.0/20 | CORP | Container | Active | 3 | 18% |
|
|
131
|
+
| 10.0.100.0/24 | CORP | Network | Active | 0 | 0% |
|
|
132
|
+
| 10.0.101.0/24 | CORP | Network | Reserved | 0 | 0% |
|
|
133
|
+
| 10.0.102.0/24 | CORP | Network | Reserved | 0 | 0% |
|
|
134
|
+
| 10.1.0.0/16 | CORP | Container | Reserved | 0 | 0% |
|
|
@@ -165,6 +165,7 @@ class PrefixTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyFilt
|
|
|
165
165
|
["rir", "rir__name"],
|
|
166
166
|
["role", "role__id"],
|
|
167
167
|
["role", "role__name"],
|
|
168
|
+
["status", "status__id"],
|
|
168
169
|
["status", "status__name"],
|
|
169
170
|
["type"],
|
|
170
171
|
)
|
|
@@ -796,8 +797,8 @@ class IPAddressTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyF
|
|
|
796
797
|
|
|
797
798
|
def test_present_in_vrf(self):
|
|
798
799
|
# clear out all the randomly generated route targets and vrfs before running this custom test
|
|
799
|
-
|
|
800
|
-
|
|
800
|
+
test_ip_addresses = self.queryset.filter(parent__namespace=self.namespace)
|
|
801
|
+
test_ip_addresses_pk_list = list(test_ip_addresses.values_list("pk", flat=True))
|
|
801
802
|
# With advent of `IPAddress.parent`, IPAddresses can't just be bulk deleted without clearing their
|
|
802
803
|
# `parent` first in an `update()` query which doesn't call `save()` or `fire `(pre|post)_save` signals.
|
|
803
804
|
unwanted_ips = self.queryset.exclude(pk__in=test_ip_addresses_pk_list)
|
|
@@ -815,12 +816,6 @@ class IPAddressTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyF
|
|
|
815
816
|
VRF.objects.create(name="VRF 2", rd="65000:200", namespace=self.namespace),
|
|
816
817
|
VRF.objects.create(name="VRF 3", rd="65000:300", namespace=self.namespace),
|
|
817
818
|
)
|
|
818
|
-
test_ip_addresses[0].parent.namespace = self.namespace
|
|
819
|
-
test_ip_addresses[0].validated_save()
|
|
820
|
-
test_ip_addresses[1].parent.namespace = self.namespace
|
|
821
|
-
test_ip_addresses[1].validated_save()
|
|
822
|
-
test_ip_addresses[2].parent.namespace = self.namespace
|
|
823
|
-
test_ip_addresses[2].validated_save()
|
|
824
819
|
vrfs[0].import_targets.add(route_targets[0], route_targets[1], route_targets[2])
|
|
825
820
|
vrfs[1].export_targets.add(route_targets[1])
|
|
826
821
|
vrfs[2].export_targets.add(route_targets[2])
|
|
@@ -855,7 +850,7 @@ class IPAddressTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyF
|
|
|
855
850
|
|
|
856
851
|
def test_status(self):
|
|
857
852
|
statuses = list(Status.objects.get_for_model(IPAddress).filter(ip_addresses__isnull=False)[:2])
|
|
858
|
-
params = {"status": [statuses[0].name, statuses[1].
|
|
853
|
+
params = {"status": [statuses[0].name, statuses[1].id]}
|
|
859
854
|
self.assertQuerysetEqualAndNotEmpty(
|
|
860
855
|
self.filterset(params, self.queryset).qs, self.queryset.filter(status__in=statuses)
|
|
861
856
|
)
|
|
@@ -1114,7 +1109,7 @@ class VLANTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyFilter
|
|
|
1114
1109
|
|
|
1115
1110
|
def test_status(self):
|
|
1116
1111
|
statuses = list(Status.objects.get_for_model(VLAN).filter(vlans__isnull=False).distinct())[:2]
|
|
1117
|
-
params = {"status": [statuses[0].name, statuses[1].
|
|
1112
|
+
params = {"status": [statuses[0].name, statuses[1].id]}
|
|
1118
1113
|
self.assertQuerysetEqual(self.filterset(params, self.queryset).qs, self.queryset.filter(status__in=statuses))
|
|
1119
1114
|
|
|
1120
1115
|
def test_search(self):
|
|
@@ -50,12 +50,14 @@ class NamespaceTestCase(
|
|
|
50
50
|
ViewTestCases.DeleteObjectViewTestCase,
|
|
51
51
|
ViewTestCases.ListObjectsViewTestCase,
|
|
52
52
|
ViewTestCases.BulkImportObjectsViewTestCase,
|
|
53
|
+
ViewTestCases.BulkEditObjectsViewTestCase,
|
|
54
|
+
ViewTestCases.BulkDeleteObjectsViewTestCase,
|
|
53
55
|
):
|
|
54
56
|
model = Namespace
|
|
55
57
|
|
|
56
58
|
@classmethod
|
|
57
59
|
def setUpTestData(cls):
|
|
58
|
-
locations = Location.objects.
|
|
60
|
+
locations = Location.objects.get_for_model(Namespace)
|
|
59
61
|
|
|
60
62
|
cls.form_data = {"name": "Namespace X", "location": locations[0].pk, "description": "A new Namespace"}
|
|
61
63
|
|
|
@@ -66,6 +68,11 @@ class NamespaceTestCase(
|
|
|
66
68
|
"Namespace 6,",
|
|
67
69
|
)
|
|
68
70
|
|
|
71
|
+
cls.bulk_edit_data = {
|
|
72
|
+
"description": "New description",
|
|
73
|
+
"location": locations[1].pk,
|
|
74
|
+
}
|
|
75
|
+
|
|
69
76
|
|
|
70
77
|
class VRFTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
71
78
|
model = VRF
|
nautobot/ipam/views.py
CHANGED
|
@@ -72,10 +72,13 @@ class NamespaceUIViewSet(
|
|
|
72
72
|
view_mixins.ObjectDestroyViewMixin,
|
|
73
73
|
view_mixins.ObjectChangeLogViewMixin,
|
|
74
74
|
view_mixins.ObjectBulkCreateViewMixin,
|
|
75
|
+
view_mixins.ObjectBulkDestroyViewMixin,
|
|
76
|
+
view_mixins.ObjectBulkUpdateViewMixin,
|
|
75
77
|
view_mixins.ObjectNotesViewMixin,
|
|
76
78
|
):
|
|
77
79
|
lookup_field = "pk"
|
|
78
80
|
form_class = forms.NamespaceForm
|
|
81
|
+
bulk_update_form_class = forms.NamespaceBulkEditForm
|
|
79
82
|
filterset_class = filters.NamespaceFilterSet
|
|
80
83
|
queryset = Namespace.objects.all()
|
|
81
84
|
serializer_class = serializers.NamespaceSerializer
|