nautobot 2.2.5__py3-none-any.whl → 2.2.7__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/api.py +2 -0
- nautobot/apps/models.py +2 -0
- nautobot/core/api/fields.py +13 -0
- nautobot/core/api/mixins.py +6 -1
- nautobot/core/api/schema.py +3 -1
- nautobot/core/api/serializers.py +7 -1
- nautobot/core/celery/__init__.py +1 -1
- nautobot/core/management/commands/generate_test_data.py +128 -158
- nautobot/core/models/fields.py +15 -0
- nautobot/core/tests/runner.py +10 -0
- nautobot/core/tests/test_utils.py +48 -1
- nautobot/core/utils/git.py +121 -49
- nautobot/core/utils/module_loading.py +10 -2
- nautobot/dcim/factory.py +1 -1
- nautobot/dcim/tests/test_models.py +2 -0
- nautobot/extras/datasources/git.py +133 -135
- nautobot/extras/datasources/utils.py +3 -0
- nautobot/extras/filters/__init__.py +1 -0
- nautobot/extras/forms/forms.py +16 -3
- nautobot/extras/jobs.py +9 -1
- nautobot/extras/migrations/0107_laxurlfield.py +28 -0
- nautobot/extras/migrations/0108_jobbutton_enabled.py +17 -0
- nautobot/extras/models/datasources.py +6 -4
- nautobot/extras/models/groups.py +9 -2
- nautobot/extras/models/jobs.py +30 -0
- nautobot/extras/models/models.py +2 -4
- nautobot/extras/tables.py +3 -0
- nautobot/extras/templates/extras/jobbutton_retrieve.html +6 -2
- nautobot/extras/templatetags/job_buttons.py +2 -2
- nautobot/extras/tests/git_data/01-valid-files/__init__.py +0 -0
- nautobot/extras/tests/git_data/01-valid-files/config_context_schemas/schema-1.yaml +18 -0
- nautobot/extras/tests/git_data/01-valid-files/config_contexts/context.yaml +12 -0
- nautobot/extras/tests/git_data/01-valid-files/config_contexts/devices/test-device.json +3 -0
- nautobot/extras/tests/git_data/01-valid-files/config_contexts/locations/Test Location.json +7 -0
- nautobot/extras/tests/git_data/01-valid-files/export_templates/dcim/device/template.j2 +3 -0
- nautobot/extras/tests/git_data/01-valid-files/export_templates/dcim/device/template2.html +4 -0
- nautobot/extras/tests/git_data/01-valid-files/export_templates/ipam/vlan/template.j2 +3 -0
- nautobot/extras/tests/git_data/01-valid-files/jobs/__init__.py +5 -0
- nautobot/extras/tests/git_data/01-valid-files/jobs/my_job.py +16 -0
- nautobot/extras/tests/git_data/02-invalid-files/__init__.py +0 -0
- nautobot/extras/tests/git_data/02-invalid-files/config_context_schemas/badschema1.json +2 -0
- nautobot/extras/tests/git_data/02-invalid-files/config_context_schemas/badschema2.json +1 -0
- nautobot/extras/tests/git_data/02-invalid-files/config_contexts/badcontext1.json +2 -0
- nautobot/extras/tests/git_data/02-invalid-files/config_contexts/badcontext2.json +1 -0
- nautobot/extras/tests/git_data/02-invalid-files/config_contexts/badcontext3.json +3 -0
- nautobot/extras/tests/git_data/02-invalid-files/config_contexts/devices/nosuchdevice.json +1 -0
- nautobot/extras/tests/git_data/02-invalid-files/dcim/template.j2 +0 -0
- nautobot/extras/tests/git_data/02-invalid-files/devices/template.j2 +0 -0
- nautobot/extras/tests/git_data/02-invalid-files/export_templates/dcim/nosuchmodel/template.j2 +3 -0
- nautobot/extras/tests/git_data/02-invalid-files/export_templates/nosuchapp/device/template.j2 +3 -0
- nautobot/extras/tests/git_data/02-invalid-files/jobs/__init__.py +2 -0
- nautobot/extras/tests/git_data/02-invalid-files/jobs/importerror.py +1 -0
- nautobot/extras/tests/git_data/02-invalid-files/jobs/syntaxerror.py +1 -0
- nautobot/extras/tests/git_helper.py +76 -0
- nautobot/extras/tests/test_api.py +28 -11
- nautobot/extras/tests/test_datasources.py +94 -276
- nautobot/extras/tests/test_dynamicgroups.py +8 -1
- nautobot/extras/tests/test_models.py +8 -3
- nautobot/extras/tests/test_views.py +21 -7
- nautobot/extras/views.py +1 -1
- nautobot/ipam/api/serializers.py +46 -16
- nautobot/ipam/api/views.py +29 -16
- nautobot/ipam/filters.py +9 -1
- nautobot/ipam/forms.py +8 -0
- nautobot/ipam/tables.py +1 -1
- nautobot/ipam/tests/test_api.py +15 -20
- nautobot/ipam/tests/test_filters.py +15 -0
- nautobot/project-static/docs/404.html +83 -8
- nautobot/project-static/docs/apps/index.html +96 -10
- nautobot/project-static/docs/apps/nautobot-apps.html +96 -10
- nautobot/project-static/docs/assets/app-icons/icon-CapacityMetrics.svg +1 -0
- nautobot/project-static/docs/assets/app-icons/icon-CircuitMaintenance.png +0 -0
- nautobot/project-static/docs/assets/javascripts/{bundle.ebd0bdb7.min.js → bundle.fe8b6f2b.min.js} +4 -4
- nautobot/project-static/docs/assets/javascripts/{bundle.ebd0bdb7.min.js.map → bundle.fe8b6f2b.min.js.map} +3 -3
- nautobot/project-static/docs/assets/javascripts/glightbox.min.js +1 -0
- nautobot/project-static/docs/assets/stylesheets/glightbox.min.css +1 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +96 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +96 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +96 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +96 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +96 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +96 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +96 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +96 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +96 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +96 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +96 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +96 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +96 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +96 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +156 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +96 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +96 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +96 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +106 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +96 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +96 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +143 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +96 -10
- nautobot/project-static/docs/development/apps/api/configuration-view.html +96 -10
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +96 -10
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +96 -10
- nautobot/project-static/docs/development/apps/api/models/global-search.html +96 -10
- nautobot/project-static/docs/development/apps/api/models/graphql.html +96 -10
- nautobot/project-static/docs/development/apps/api/models/index.html +96 -10
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +96 -10
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +96 -10
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +96 -10
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +96 -10
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +96 -10
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +96 -10
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +96 -10
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +96 -10
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +96 -10
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +96 -10
- nautobot/project-static/docs/development/apps/api/prometheus.html +96 -10
- nautobot/project-static/docs/development/apps/api/setup.html +96 -10
- nautobot/project-static/docs/development/apps/api/testing.html +96 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +96 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +96 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +96 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +96 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +96 -10
- nautobot/project-static/docs/development/apps/api/views/base-template.html +96 -10
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +96 -10
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +96 -10
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +96 -10
- nautobot/project-static/docs/development/apps/api/views/index.html +96 -10
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +96 -10
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +96 -10
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +96 -10
- nautobot/project-static/docs/development/apps/api/views/notes.html +96 -10
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +96 -10
- nautobot/project-static/docs/development/apps/api/views/urls.html +96 -10
- nautobot/project-static/docs/development/apps/index.html +96 -10
- nautobot/project-static/docs/development/apps/migration/code-updates.html +97 -11
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +96 -10
- nautobot/project-static/docs/development/apps/migration/from-v1.html +96 -10
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +96 -10
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +96 -10
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +96 -10
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +96 -10
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +96 -10
- nautobot/project-static/docs/development/core/application-registry.html +96 -10
- nautobot/project-static/docs/development/core/best-practices.html +96 -10
- nautobot/project-static/docs/development/core/bootstrap-ui.html +96 -10
- nautobot/project-static/docs/development/core/caching.html +96 -10
- nautobot/project-static/docs/development/core/controllers.html +96 -10
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +96 -10
- nautobot/project-static/docs/development/core/generic-views.html +96 -10
- nautobot/project-static/docs/development/core/getting-started.html +98 -13
- nautobot/project-static/docs/development/core/homepage.html +96 -10
- nautobot/project-static/docs/development/core/index.html +96 -10
- nautobot/project-static/docs/development/core/model-checklist.html +96 -10
- nautobot/project-static/docs/development/core/model-features.html +96 -10
- nautobot/project-static/docs/development/core/natural-keys.html +96 -10
- nautobot/project-static/docs/development/core/navigation-menu.html +96 -10
- nautobot/project-static/docs/development/core/release-checklist.html +96 -10
- nautobot/project-static/docs/development/core/role-internals.html +96 -10
- nautobot/project-static/docs/development/core/settings.html +96 -10
- nautobot/project-static/docs/development/core/style-guide.html +96 -10
- nautobot/project-static/docs/development/core/templates.html +96 -10
- nautobot/project-static/docs/development/core/testing.html +109 -11
- nautobot/project-static/docs/development/core/user-preferences.html +96 -10
- nautobot/project-static/docs/development/index.html +96 -10
- nautobot/project-static/docs/development/jobs/index.html +96 -10
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +96 -10
- nautobot/project-static/docs/index.html +13 -8362
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +8229 -0
- nautobot/project-static/docs/overview/design_philosophy.html +8158 -0
- nautobot/project-static/docs/overview/index.html +8230 -0
- nautobot/project-static/docs/release-notes/index.html +96 -10
- nautobot/project-static/docs/release-notes/version-1.0.html +96 -10
- nautobot/project-static/docs/release-notes/version-1.1.html +96 -10
- nautobot/project-static/docs/release-notes/version-1.2.html +96 -10
- nautobot/project-static/docs/release-notes/version-1.3.html +96 -10
- nautobot/project-static/docs/release-notes/version-1.4.html +96 -10
- nautobot/project-static/docs/release-notes/version-1.5.html +96 -10
- nautobot/project-static/docs/release-notes/version-1.6.html +96 -10
- nautobot/project-static/docs/release-notes/version-2.0.html +96 -10
- nautobot/project-static/docs/release-notes/version-2.1.html +96 -10
- nautobot/project-static/docs/release-notes/version-2.2.html +516 -131
- nautobot/project-static/docs/requirements.txt +2 -1
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +268 -258
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +96 -10
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +96 -10
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +96 -10
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +96 -10
- nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +96 -10
- nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +96 -10
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +96 -10
- nautobot/project-static/docs/user-guide/administration/guides/caching.html +96 -10
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +96 -10
- nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +96 -10
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +96 -10
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +96 -10
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +96 -10
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +96 -10
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +96 -10
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +96 -10
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +96 -10
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +96 -10
- nautobot/project-static/docs/user-guide/administration/installation/index.html +96 -10
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +96 -10
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +96 -10
- nautobot/project-static/docs/user-guide/administration/installation/services.html +96 -10
- nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +96 -10
- nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +96 -10
- nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +96 -10
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +96 -10
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +96 -10
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +96 -10
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +96 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +96 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +96 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +96 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +96 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +96 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +96 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +96 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/tables/v2-code-location-changes.yaml +1 -1
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +97 -11
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +96 -10
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +96 -10
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +96 -10
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +96 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +96 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +96 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +96 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +96 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +96 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +96 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +96 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +96 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +96 -10
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +96 -10
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +96 -10
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +96 -10
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +96 -10
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +96 -10
- nautobot/project-static/docs/user-guide/index.html +99 -13
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +97 -11
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +101 -14
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +96 -10
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +96 -10
- nautobot/project-static/js/connection_toggles.js +7 -6
- {nautobot-2.2.5.dist-info → nautobot-2.2.7.dist-info}/METADATA +2 -2
- {nautobot-2.2.5.dist-info → nautobot-2.2.7.dist-info}/RECORD +344 -311
- nautobot/extras/tests/test_git.py +0 -23
- {nautobot-2.2.5.dist-info → nautobot-2.2.7.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.2.5.dist-info → nautobot-2.2.7.dist-info}/NOTICE +0 -0
- {nautobot-2.2.5.dist-info → nautobot-2.2.7.dist-info}/WHEEL +0 -0
- {nautobot-2.2.5.dist-info → nautobot-2.2.7.dist-info}/entry_points.txt +0 -0
|
@@ -254,7 +254,7 @@ class ConfigContextTest(ModelTestCases.BaseModelTestCase):
|
|
|
254
254
|
slug="test_git_repo",
|
|
255
255
|
remote_url="http://localhost/git.git",
|
|
256
256
|
)
|
|
257
|
-
repo.
|
|
257
|
+
repo.validated_save()
|
|
258
258
|
|
|
259
259
|
with self.assertRaises(ValidationError):
|
|
260
260
|
nonduplicate_context = ConfigContext(name="context 1", weight=300, data={"a": "22"}, owner=repo)
|
|
@@ -864,7 +864,7 @@ class ExportTemplateTest(ModelTestCases.BaseModelTestCase):
|
|
|
864
864
|
slug="test_git_repo",
|
|
865
865
|
remote_url="http://localhost/git.git",
|
|
866
866
|
)
|
|
867
|
-
repo.
|
|
867
|
+
repo.validated_save()
|
|
868
868
|
|
|
869
869
|
with self.assertRaises(ValidationError):
|
|
870
870
|
nonduplicate_template = ExportTemplate(
|
|
@@ -888,7 +888,7 @@ class ExternalIntegrationTest(ModelTestCases.BaseModelTestCase):
|
|
|
888
888
|
)
|
|
889
889
|
ei.validated_save()
|
|
890
890
|
|
|
891
|
-
ei.remote_url = "http://
|
|
891
|
+
ei.remote_url = "http://some-local-host"
|
|
892
892
|
ei.validated_save()
|
|
893
893
|
|
|
894
894
|
def test_timeout_validation(self):
|
|
@@ -1045,6 +1045,11 @@ class GitRepositoryTest(ModelTestCases.BaseModelTestCase):
|
|
|
1045
1045
|
repo.validated_save()
|
|
1046
1046
|
self.assertIn("Please choose a different slug", str(handler.exception))
|
|
1047
1047
|
|
|
1048
|
+
def test_remote_url_hostname(self):
|
|
1049
|
+
"""Confirm that a bare hostname (no domain name) can be used for a remote URL."""
|
|
1050
|
+
self.repo.remote_url = "http://some-private-host/example.git"
|
|
1051
|
+
self.repo.validated_save()
|
|
1052
|
+
|
|
1048
1053
|
|
|
1049
1054
|
class JobModelTest(ModelTestCases.BaseModelTestCase):
|
|
1050
1055
|
"""
|
|
@@ -996,7 +996,7 @@ class GitRepositoryTestCase(
|
|
|
996
996
|
# Create four GitRepository records
|
|
997
997
|
repos = (
|
|
998
998
|
GitRepository(name="Repo 1", slug="repo_1", remote_url="https://example.com/repo1.git"),
|
|
999
|
-
GitRepository(name="Repo 2", slug="repo_2", remote_url="https://
|
|
999
|
+
GitRepository(name="Repo 2", slug="repo_2", remote_url="https://some-local-host/repo2.git"),
|
|
1000
1000
|
GitRepository(name="Repo 3", slug="repo_3", remote_url="https://example.com/repo3.git"),
|
|
1001
1001
|
GitRepository(name="Repo 4", remote_url="https://example.com/repo4.git", secrets_group=secrets_groups[0]),
|
|
1002
1002
|
)
|
|
@@ -1006,7 +1006,7 @@ class GitRepositoryTestCase(
|
|
|
1006
1006
|
cls.form_data = {
|
|
1007
1007
|
"name": "A new Git repository",
|
|
1008
1008
|
"slug": "a_new_git_repository",
|
|
1009
|
-
"remote_url": "http://
|
|
1009
|
+
"remote_url": "http://another-local-host/a_new_git_repository.git",
|
|
1010
1010
|
"branch": "develop",
|
|
1011
1011
|
"_token": "1234567890abcdef1234567890abcdef",
|
|
1012
1012
|
"secrets_group": secrets_groups[1].pk,
|
|
@@ -2329,23 +2329,30 @@ class JobButtonTestCase(
|
|
|
2329
2329
|
|
|
2330
2330
|
@classmethod
|
|
2331
2331
|
def setUpTestData(cls):
|
|
2332
|
+
jbr_simple = Job.objects.get(job_class_name="TestJobButtonReceiverSimple")
|
|
2333
|
+
jbr_simple.enabled = True
|
|
2334
|
+
jbr_simple.save()
|
|
2335
|
+
jbr_complex = Job.objects.get(job_class_name="TestJobButtonReceiverComplex")
|
|
2336
|
+
jbr_complex.enabled = True
|
|
2337
|
+
jbr_complex.save()
|
|
2338
|
+
|
|
2332
2339
|
job_buttons = (
|
|
2333
2340
|
JobButton.objects.create(
|
|
2334
2341
|
name="JobButton1",
|
|
2335
2342
|
text="JobButton1",
|
|
2336
|
-
job=
|
|
2343
|
+
job=jbr_simple,
|
|
2337
2344
|
confirmation=True,
|
|
2338
2345
|
),
|
|
2339
2346
|
JobButton.objects.create(
|
|
2340
2347
|
name="JobButton2",
|
|
2341
2348
|
text="JobButton2",
|
|
2342
|
-
job=
|
|
2349
|
+
job=jbr_simple,
|
|
2343
2350
|
confirmation=False,
|
|
2344
2351
|
),
|
|
2345
2352
|
JobButton.objects.create(
|
|
2346
2353
|
name="JobButton3",
|
|
2347
2354
|
text="JobButton3",
|
|
2348
|
-
job=
|
|
2355
|
+
job=jbr_complex,
|
|
2349
2356
|
confirmation=True,
|
|
2350
2357
|
weight=50,
|
|
2351
2358
|
),
|
|
@@ -2359,7 +2366,7 @@ class JobButtonTestCase(
|
|
|
2359
2366
|
"content_types": [location_ct.pk],
|
|
2360
2367
|
"name": "jobbutton-4",
|
|
2361
2368
|
"text": "jobbutton text 4",
|
|
2362
|
-
"job":
|
|
2369
|
+
"job": jbr_complex.pk,
|
|
2363
2370
|
"weight": 100,
|
|
2364
2371
|
"button_class": "default",
|
|
2365
2372
|
"confirmation": False,
|
|
@@ -2374,6 +2381,9 @@ class JobButtonRenderingTestCase(TestCase):
|
|
|
2374
2381
|
def setUp(self):
|
|
2375
2382
|
super().setUp()
|
|
2376
2383
|
self.job = Job.objects.get(job_class_name="TestJobButtonReceiverSimple")
|
|
2384
|
+
self.job.enabled = True
|
|
2385
|
+
self.job.save()
|
|
2386
|
+
|
|
2377
2387
|
self.job_button_1 = JobButton(
|
|
2378
2388
|
name="JobButton 1",
|
|
2379
2389
|
text="JobButton {{ obj.name }}",
|
|
@@ -2383,10 +2393,14 @@ class JobButtonRenderingTestCase(TestCase):
|
|
|
2383
2393
|
self.job_button_1.validated_save()
|
|
2384
2394
|
self.job_button_1.content_types.add(ContentType.objects.get_for_model(LocationType))
|
|
2385
2395
|
|
|
2396
|
+
job_2 = Job.objects.get(job_class_name="TestJobButtonReceiverComplex")
|
|
2397
|
+
job_2.enabled = True
|
|
2398
|
+
job_2.save()
|
|
2399
|
+
|
|
2386
2400
|
self.job_button_2 = JobButton(
|
|
2387
2401
|
name="JobButton 2",
|
|
2388
2402
|
text="Click me!",
|
|
2389
|
-
job=
|
|
2403
|
+
job=job_2,
|
|
2390
2404
|
confirmation=False,
|
|
2391
2405
|
)
|
|
2392
2406
|
self.job_button_2.validated_save()
|
nautobot/extras/views.py
CHANGED
|
@@ -1069,7 +1069,7 @@ def check_and_call_git_repository_function(request, pk, func):
|
|
|
1069
1069
|
# Allow execution only if a worker process is running.
|
|
1070
1070
|
if not get_worker_count():
|
|
1071
1071
|
messages.error(request, "Unable to run job: Celery worker process not running.")
|
|
1072
|
-
return redirect(
|
|
1072
|
+
return redirect(reverse("extras:gitrepository", args=(pk,)), permanent=False)
|
|
1073
1073
|
else:
|
|
1074
1074
|
repository = get_object_or_404(GitRepository.objects.restrict(request.user, "change"), pk=pk)
|
|
1075
1075
|
job_result = func(repository, request.user)
|
nautobot/ipam/api/serializers.py
CHANGED
|
@@ -321,27 +321,30 @@ class PrefixLocationAssignmentSerializer(ValidatedModelSerializer):
|
|
|
321
321
|
fields = "__all__"
|
|
322
322
|
|
|
323
323
|
|
|
324
|
-
class PrefixLengthSerializer(
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
324
|
+
class PrefixLengthSerializer(PrefixLegacySerializer):
|
|
325
|
+
"""
|
|
326
|
+
Input serializer for POST to /api/ipam/prefixes/<id>/available-prefixes/, i.e. allocating one or more sub-prefixes.
|
|
327
|
+
|
|
328
|
+
Since setting of multiple locations on create is not supported, this uses the legacy single-location option.
|
|
329
|
+
"""
|
|
330
|
+
|
|
331
|
+
prefix_length = serializers.IntegerField(required=True)
|
|
332
|
+
|
|
333
|
+
class Meta(PrefixLegacySerializer.Meta):
|
|
334
|
+
fields = PrefixLegacySerializer.Meta.fields.copy()
|
|
335
|
+
fields.remove("prefix")
|
|
336
|
+
fields.remove("network")
|
|
337
|
+
fields.remove("broadcast")
|
|
338
|
+
fields.remove("parent")
|
|
339
|
+
fields.remove("ip_version")
|
|
340
|
+
fields.remove("namespace")
|
|
340
341
|
|
|
341
342
|
|
|
342
343
|
class AvailablePrefixSerializer(serializers.Serializer):
|
|
343
344
|
"""
|
|
344
345
|
Representation of a prefix which does not exist in the database.
|
|
346
|
+
|
|
347
|
+
Response serializer for a GET to /api/ipam/prefixes/<id>/available-prefixes/.
|
|
345
348
|
"""
|
|
346
349
|
|
|
347
350
|
ip_version = serializers.IntegerField(read_only=True)
|
|
@@ -437,6 +440,8 @@ class IPAddressSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
|
|
|
437
440
|
class AvailableIPSerializer(serializers.Serializer):
|
|
438
441
|
"""
|
|
439
442
|
Representation of an IP address which does not exist in the database.
|
|
443
|
+
|
|
444
|
+
Response serializer for a GET to /api/ipam/prefixes/<id>/available-ips/.
|
|
440
445
|
"""
|
|
441
446
|
|
|
442
447
|
ip_version = serializers.IntegerField(read_only=True)
|
|
@@ -451,6 +456,31 @@ class AvailableIPSerializer(serializers.Serializer):
|
|
|
451
456
|
)
|
|
452
457
|
|
|
453
458
|
|
|
459
|
+
class IPAllocationSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
|
|
460
|
+
"""
|
|
461
|
+
Input serializer for POST to /api/ipam/prefixes/<id>/available-ips/, i.e. allocating addresses from a prefix.
|
|
462
|
+
"""
|
|
463
|
+
|
|
464
|
+
class Meta:
|
|
465
|
+
model = IPAddress
|
|
466
|
+
fields = (
|
|
467
|
+
# not address/namespace/parent as those are implied by the selected prefix
|
|
468
|
+
"status",
|
|
469
|
+
"type",
|
|
470
|
+
"dns_name",
|
|
471
|
+
"description",
|
|
472
|
+
"role",
|
|
473
|
+
"tenant",
|
|
474
|
+
"nat_inside",
|
|
475
|
+
"tags",
|
|
476
|
+
"custom_fields",
|
|
477
|
+
)
|
|
478
|
+
|
|
479
|
+
def validate(self, data):
|
|
480
|
+
data["mask_length"] = self.context["prefix"].prefix_length
|
|
481
|
+
return super().validate(data)
|
|
482
|
+
|
|
483
|
+
|
|
454
484
|
#
|
|
455
485
|
# IP address to interface
|
|
456
486
|
#
|
nautobot/ipam/api/views.py
CHANGED
|
@@ -121,8 +121,6 @@ class PrefixViewSet(NautobotModelViewSet):
|
|
|
121
121
|
filterset_class = filters.PrefixFilterSet
|
|
122
122
|
|
|
123
123
|
def get_serializer_class(self):
|
|
124
|
-
if self.action == "available_prefixes" and self.request.method == "POST":
|
|
125
|
-
return serializers.PrefixLengthSerializer
|
|
126
124
|
if (
|
|
127
125
|
not getattr(self, "swagger_fake_view", False)
|
|
128
126
|
and self.request.major_version == 2
|
|
@@ -159,7 +157,11 @@ class PrefixViewSet(NautobotModelViewSet):
|
|
|
159
157
|
raise self.LocationIncompatibleLegacyBehavior from e
|
|
160
158
|
|
|
161
159
|
@extend_schema(methods=["get"], responses={200: serializers.AvailablePrefixSerializer(many=True)})
|
|
162
|
-
@extend_schema(
|
|
160
|
+
@extend_schema(
|
|
161
|
+
methods=["post"],
|
|
162
|
+
request=serializers.PrefixLengthSerializer,
|
|
163
|
+
responses={201: serializers.PrefixSerializer(many=True)},
|
|
164
|
+
)
|
|
163
165
|
@action(
|
|
164
166
|
detail=True,
|
|
165
167
|
name="Available Prefixes",
|
|
@@ -169,10 +171,10 @@ class PrefixViewSet(NautobotModelViewSet):
|
|
|
169
171
|
)
|
|
170
172
|
def available_prefixes(self, request, pk=None):
|
|
171
173
|
"""
|
|
172
|
-
A convenience method for
|
|
174
|
+
A convenience method for listing and/or allocating available child prefixes within a parent.
|
|
173
175
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
+
This uses a Redis lock to prevent this API from being invoked in parallel, in order to avoid a race condition
|
|
177
|
+
if multiple clients tried to simultaneously request allocation from the same parent prefix.
|
|
176
178
|
"""
|
|
177
179
|
prefix = get_object_or_404(self.queryset, pk=pk)
|
|
178
180
|
if request.method == "POST":
|
|
@@ -214,9 +216,9 @@ class PrefixViewSet(NautobotModelViewSet):
|
|
|
214
216
|
# Initialize the serializer with a list or a single object depending on what was requested
|
|
215
217
|
context = {"request": request, "depth": 0}
|
|
216
218
|
if isinstance(request.data, list):
|
|
217
|
-
serializer =
|
|
219
|
+
serializer = self.get_serializer_class()(data=requested_prefixes, many=True, context=context)
|
|
218
220
|
else:
|
|
219
|
-
serializer =
|
|
221
|
+
serializer = self.get_serializer_class()(data=requested_prefixes[0], context=context)
|
|
220
222
|
|
|
221
223
|
# Create the new Prefix(es)
|
|
222
224
|
serializer.is_valid(raise_exception=True)
|
|
@@ -238,8 +240,8 @@ class PrefixViewSet(NautobotModelViewSet):
|
|
|
238
240
|
@extend_schema(methods=["get"], responses={200: serializers.AvailableIPSerializer(many=True)})
|
|
239
241
|
@extend_schema(
|
|
240
242
|
methods=["post"],
|
|
241
|
-
responses={201: serializers.
|
|
242
|
-
request=serializers.
|
|
243
|
+
responses={201: serializers.IPAddressSerializer(many=True)},
|
|
244
|
+
request=serializers.IPAllocationSerializer(many=True),
|
|
243
245
|
)
|
|
244
246
|
@action(
|
|
245
247
|
detail=True,
|
|
@@ -251,12 +253,13 @@ class PrefixViewSet(NautobotModelViewSet):
|
|
|
251
253
|
)
|
|
252
254
|
def available_ips(self, request, pk=None):
|
|
253
255
|
"""
|
|
254
|
-
A convenience method for
|
|
255
|
-
|
|
256
|
-
|
|
256
|
+
A convenience method for listing and/or allocating available IP addresses within a prefix.
|
|
257
|
+
|
|
258
|
+
By default, the number of IPs returned will be equivalent to PAGINATE_COUNT.
|
|
259
|
+
An arbitrary limit (up to MAX_PAGE_SIZE, if set) may be passed, however results will not be paginated.
|
|
257
260
|
|
|
258
|
-
|
|
259
|
-
|
|
261
|
+
This uses a Redis lock to prevent this API from being invoked in parallel, in order to avoid a race condition
|
|
262
|
+
if multiple clients tried to simultaneously request allocation from the same parent prefix.
|
|
260
263
|
"""
|
|
261
264
|
prefix = get_object_or_404(Prefix.objects.restrict(request.user), pk=pk)
|
|
262
265
|
|
|
@@ -266,7 +269,17 @@ class PrefixViewSet(NautobotModelViewSet):
|
|
|
266
269
|
"nautobot.ipam.api.views.available_ips", blocking_timeout=5, timeout=settings.REDIS_LOCK_TIMEOUT
|
|
267
270
|
):
|
|
268
271
|
# Normalize to a list of objects
|
|
269
|
-
|
|
272
|
+
serializer = serializers.IPAllocationSerializer(
|
|
273
|
+
data=request.data if isinstance(request.data, list) else [request.data],
|
|
274
|
+
many=True,
|
|
275
|
+
context={
|
|
276
|
+
"request": request,
|
|
277
|
+
"prefix": prefix,
|
|
278
|
+
},
|
|
279
|
+
)
|
|
280
|
+
serializer.is_valid(raise_exception=True)
|
|
281
|
+
|
|
282
|
+
requested_ips = serializer.validated_data
|
|
270
283
|
|
|
271
284
|
# Determine if the requested number of IPs is available
|
|
272
285
|
available_ips = prefix.get_available_ips()
|
nautobot/ipam/filters.py
CHANGED
|
@@ -433,11 +433,19 @@ class IPAddressFilterSet(
|
|
|
433
433
|
method="_has_interface_assignments",
|
|
434
434
|
label="Has Interface Assignments",
|
|
435
435
|
)
|
|
436
|
+
nat_inside = django_filters.ModelMultipleChoiceFilter(
|
|
437
|
+
queryset=IPAddress.objects.all(),
|
|
438
|
+
label="NAT (Inside)",
|
|
439
|
+
)
|
|
440
|
+
has_nat_inside = RelatedMembershipBooleanFilter(
|
|
441
|
+
field_name="nat_inside",
|
|
442
|
+
label="Has NAT Inside",
|
|
443
|
+
)
|
|
436
444
|
ip_version = django_filters.NumberFilter()
|
|
437
445
|
|
|
438
446
|
class Meta:
|
|
439
447
|
model = IPAddress
|
|
440
|
-
fields = ["id", "dns_name", "type", "tags", "mask_length"]
|
|
448
|
+
fields = ["id", "dns_name", "type", "tags", "mask_length", "nat_inside"]
|
|
441
449
|
|
|
442
450
|
def generate_query__has_interface_assignments(self, value):
|
|
443
451
|
"""Helper method used by DynamicGroups and by _assigned_to_interface method."""
|
nautobot/ipam/forms.py
CHANGED
|
@@ -664,6 +664,8 @@ class IPAddressFilterForm(NautobotFilterForm, TenancyFilterForm, StatusModelFilt
|
|
|
664
664
|
"role",
|
|
665
665
|
"tenant_group",
|
|
666
666
|
"tenant",
|
|
667
|
+
"nat_inside",
|
|
668
|
+
"has_nat_inside",
|
|
667
669
|
]
|
|
668
670
|
q = forms.CharField(required=False, label="Search")
|
|
669
671
|
parent = forms.CharField(
|
|
@@ -700,6 +702,12 @@ class IPAddressFilterForm(NautobotFilterForm, TenancyFilterForm, StatusModelFilt
|
|
|
700
702
|
widget=StaticSelect2(),
|
|
701
703
|
)
|
|
702
704
|
tags = TagFilterField(model)
|
|
705
|
+
nat_inside = DynamicModelChoiceField(queryset=IPAddress.objects.all(), required=False, label="NAT Inside Address")
|
|
706
|
+
has_nat_inside = forms.NullBooleanField(
|
|
707
|
+
required=False,
|
|
708
|
+
label="Has NAT Inside",
|
|
709
|
+
widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES),
|
|
710
|
+
)
|
|
703
711
|
|
|
704
712
|
|
|
705
713
|
#
|
nautobot/ipam/tables.py
CHANGED
|
@@ -473,7 +473,7 @@ class IPAddressTable(StatusTableMixin, RoleTableMixin, BaseTable):
|
|
|
473
473
|
|
|
474
474
|
|
|
475
475
|
class IPAddressDetailTable(IPAddressTable):
|
|
476
|
-
nat_inside = tables.Column(linkify=True,
|
|
476
|
+
nat_inside = tables.Column(linkify=True, verbose_name="NAT (Inside)")
|
|
477
477
|
tenant = TenantColumn()
|
|
478
478
|
tags = TagColumn(url_name="ipam:ipaddress_list")
|
|
479
479
|
assigned = BooleanColumn(accessor="assigned_count")
|
nautobot/ipam/tests/test_api.py
CHANGED
|
@@ -454,7 +454,6 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
|
|
|
454
454
|
for i in range(4):
|
|
455
455
|
data = {
|
|
456
456
|
"prefix_length": child_prefix_length,
|
|
457
|
-
"namespace": self.namespace.pk,
|
|
458
457
|
"status": self.status.pk,
|
|
459
458
|
"description": f"Test Prefix {i + 1}",
|
|
460
459
|
}
|
|
@@ -464,13 +463,18 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
|
|
|
464
463
|
self.assertEqual(str(response.data["namespace"]["url"]), self.absolute_api_url(prefix.namespace))
|
|
465
464
|
self.assertEqual(response.data["description"], data["description"])
|
|
466
465
|
|
|
467
|
-
# Try to create one more prefix
|
|
468
|
-
|
|
466
|
+
# Try to create one more prefix, and expect a HTTP 204 response.
|
|
467
|
+
# This feels wrong to me (shouldn't it be a 4xx or 5xx?) but it's how the API has historically behaved.
|
|
468
|
+
response = self.client.post(
|
|
469
|
+
url, {"prefix_length": child_prefix_length, "status": self.status.pk}, format="json", **self.header
|
|
470
|
+
)
|
|
469
471
|
self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
|
|
470
472
|
self.assertIn("detail", response.data)
|
|
471
473
|
|
|
472
|
-
#
|
|
473
|
-
response = self.client.post(
|
|
474
|
+
# Invalid data does trigger a HTTP 400 response.
|
|
475
|
+
response = self.client.post(
|
|
476
|
+
url, {"prefix_length": "hello", "status": self.status.pk}, format="json", **self.header
|
|
477
|
+
)
|
|
474
478
|
self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
|
|
475
479
|
self.assertIn("prefix_length", response.data[0])
|
|
476
480
|
|
|
@@ -495,35 +499,31 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
|
|
|
495
499
|
{
|
|
496
500
|
"prefix_length": child_prefix_length,
|
|
497
501
|
"description": "Test Prefix 1",
|
|
498
|
-
"namespace": self.namespace.pk,
|
|
499
502
|
"status": self.status.pk,
|
|
500
503
|
},
|
|
501
504
|
{
|
|
502
505
|
"prefix_length": child_prefix_length,
|
|
503
506
|
"description": "Test Prefix 2",
|
|
504
|
-
"namespace": self.namespace.pk,
|
|
505
507
|
"status": self.status.pk,
|
|
506
508
|
},
|
|
507
509
|
{
|
|
508
510
|
"prefix_length": child_prefix_length,
|
|
509
511
|
"description": "Test Prefix 3",
|
|
510
|
-
"namespace": self.namespace.pk,
|
|
511
512
|
"status": self.status.pk,
|
|
512
513
|
},
|
|
513
514
|
{
|
|
514
515
|
"prefix_length": child_prefix_length,
|
|
515
516
|
"description": "Test Prefix 4",
|
|
516
|
-
"namespace": self.namespace.pk,
|
|
517
517
|
"status": self.status.pk,
|
|
518
518
|
},
|
|
519
519
|
{
|
|
520
520
|
"prefix_length": child_prefix_length,
|
|
521
521
|
"description": "Test Prefix 5",
|
|
522
|
-
"namespace": self.namespace.pk,
|
|
523
522
|
"status": self.status.pk,
|
|
524
523
|
},
|
|
525
524
|
]
|
|
526
525
|
response = self.client.post(url, data, format="json", **self.header)
|
|
526
|
+
# This feels wrong to me (shouldn't it be a 4xx or 5xx?) but it's how the API has historically behaved.
|
|
527
527
|
self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
|
|
528
528
|
self.assertIn("detail", response.data)
|
|
529
529
|
|
|
@@ -577,7 +577,6 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
|
|
|
577
577
|
for i in range(1, 7):
|
|
578
578
|
data = {
|
|
579
579
|
"description": f"Test IP {i}",
|
|
580
|
-
"namespace": self.namespace.pk,
|
|
581
580
|
"status": self.status.pk,
|
|
582
581
|
}
|
|
583
582
|
response = self.client.post(url, data, format="json", **self.header)
|
|
@@ -586,7 +585,8 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
|
|
|
586
585
|
self.assertEqual(response.data["description"], data["description"])
|
|
587
586
|
|
|
588
587
|
# Try to create one more IP
|
|
589
|
-
response = self.client.post(url, {}, format="json", **self.header)
|
|
588
|
+
response = self.client.post(url, {"status": self.status.pk}, format="json", **self.header)
|
|
589
|
+
# This feels wrong to me (shouldn't it be a 4xx or 5xx?) but it's how the API has historically behaved.
|
|
590
590
|
self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
|
|
591
591
|
self.assertIn("detail", response.data)
|
|
592
592
|
|
|
@@ -604,19 +604,14 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
|
|
|
604
604
|
self.add_permissions("ipam.view_prefix", "ipam.add_ipaddress", "extras.view_status")
|
|
605
605
|
|
|
606
606
|
# Try to create seven IPs (only six are available)
|
|
607
|
-
data = [
|
|
608
|
-
{"description": f"Test IP {i}", "namespace": self.namespace.pk, "status": self.status.pk}
|
|
609
|
-
for i in range(1, 8)
|
|
610
|
-
] # 7 IPs
|
|
607
|
+
data = [{"description": f"Test IP {i}", "status": self.status.pk} for i in range(1, 8)] # 7 IPs
|
|
611
608
|
response = self.client.post(url, data, format="json", **self.header)
|
|
609
|
+
# This feels wrong to me (shouldn't it be a 4xx or 5xx?) but it's how the API has historically behaved.
|
|
612
610
|
self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
|
|
613
611
|
self.assertIn("detail", response.data)
|
|
614
612
|
|
|
615
613
|
# Create all six available IPs in a single request
|
|
616
|
-
data = [
|
|
617
|
-
{"description": f"Test IP {i}", "namespace": self.namespace.pk, "status": self.status.pk}
|
|
618
|
-
for i in range(1, 7)
|
|
619
|
-
] # 6 IPs
|
|
614
|
+
data = [{"description": f"Test IP {i}", "status": self.status.pk} for i in range(1, 7)] # 6 IPs
|
|
620
615
|
response = self.client.post(url, data, format="json", **self.header)
|
|
621
616
|
self.assertHttpStatus(response, status.HTTP_201_CREATED)
|
|
622
617
|
self.assertEqual(len(response.data), 6)
|
|
@@ -462,6 +462,7 @@ class IPAddressTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyF
|
|
|
462
462
|
queryset = IPAddress.objects.all()
|
|
463
463
|
filterset = IPAddressFilterSet
|
|
464
464
|
tenancy_related_name = "ip_addresses"
|
|
465
|
+
generic_filter_tests = (["nat_inside", "nat_inside__id"],)
|
|
465
466
|
|
|
466
467
|
@classmethod
|
|
467
468
|
def setUpTestData(cls):
|
|
@@ -638,6 +639,20 @@ class IPAddressTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyF
|
|
|
638
639
|
status=statuses[0],
|
|
639
640
|
namespace=cls.namespace,
|
|
640
641
|
)
|
|
642
|
+
IPAddress.objects.create(
|
|
643
|
+
address="10.1.1.1/32",
|
|
644
|
+
tenant=None,
|
|
645
|
+
status=statuses[0],
|
|
646
|
+
namespace=cls.namespace,
|
|
647
|
+
nat_inside=ip0,
|
|
648
|
+
)
|
|
649
|
+
IPAddress.objects.create(
|
|
650
|
+
address="10.2.2.2/32",
|
|
651
|
+
tenant=None,
|
|
652
|
+
status=statuses[0],
|
|
653
|
+
namespace=cls.namespace,
|
|
654
|
+
nat_inside=ip1,
|
|
655
|
+
)
|
|
641
656
|
|
|
642
657
|
def test_search(self):
|
|
643
658
|
ipv4_octets = self.ipv4_address.host.split(".")
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
<link rel="icon" href="/projects/core/en/stable/assets/favicon.ico">
|
|
15
|
-
<meta name="generator" content="mkdocs-1.6.0, mkdocs-material-9.5.
|
|
15
|
+
<meta name="generator" content="mkdocs-1.6.0, mkdocs-material-9.5.28">
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
|
|
92
92
|
<header class="md-header md-header--shadow md-header--lifted" data-md-component="header">
|
|
93
93
|
<nav class="md-header__inner md-grid" aria-label="Header">
|
|
94
|
-
<a href="/projects/core/en/stable
|
|
94
|
+
<a href="/projects/core/en/stable/." title="Nautobot Documentation" class="md-header__button md-logo" aria-label="Nautobot Documentation" data-md-component="logo">
|
|
95
95
|
|
|
96
96
|
<img src="/projects/core/en/stable/assets/nautobot_logo.svg" alt="logo">
|
|
97
97
|
|
|
@@ -180,7 +180,7 @@
|
|
|
180
180
|
|
|
181
181
|
</form>
|
|
182
182
|
<div class="md-search__output">
|
|
183
|
-
<div class="md-search__scrollwrap" data-md-scrollfix>
|
|
183
|
+
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
|
|
184
184
|
<div class="md-search-result" data-md-component="search-result">
|
|
185
185
|
<div class="md-search-result__meta">
|
|
186
186
|
Initializing search
|
|
@@ -218,7 +218,7 @@
|
|
|
218
218
|
|
|
219
219
|
|
|
220
220
|
<li class="md-tabs__item">
|
|
221
|
-
<a href="/projects/core/en/stable/index.html" class="md-tabs__link">
|
|
221
|
+
<a href="/projects/core/en/stable/overview/index.html" class="md-tabs__link">
|
|
222
222
|
|
|
223
223
|
|
|
224
224
|
|
|
@@ -343,7 +343,7 @@
|
|
|
343
343
|
|
|
344
344
|
<nav class="md-nav md-nav--primary md-nav--lifted" aria-label="Navigation" data-md-level="0">
|
|
345
345
|
<label class="md-nav__title" for="__drawer">
|
|
346
|
-
<a href="/projects/core/en/stable
|
|
346
|
+
<a href="/projects/core/en/stable/." title="Nautobot Documentation" class="md-nav__button md-logo" aria-label="Nautobot Documentation" data-md-component="logo">
|
|
347
347
|
|
|
348
348
|
<img src="/projects/core/en/stable/assets/nautobot_logo.svg" alt="logo">
|
|
349
349
|
|
|
@@ -371,19 +371,94 @@
|
|
|
371
371
|
|
|
372
372
|
|
|
373
373
|
|
|
374
|
-
|
|
375
|
-
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
<li class="md-nav__item md-nav__item--nested">
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_1" >
|
|
376
386
|
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
<div class="md-nav__link md-nav__container">
|
|
390
|
+
<a href="/projects/core/en/stable/overview/index.html" class="md-nav__link ">
|
|
391
|
+
|
|
377
392
|
|
|
378
393
|
<span class="md-ellipsis">
|
|
379
394
|
Overview
|
|
380
395
|
</span>
|
|
381
396
|
|
|
382
397
|
|
|
398
|
+
</a>
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
<label class="md-nav__link " for="__nav_1" id="__nav_1_label" tabindex="0">
|
|
402
|
+
<span class="md-nav__icon md-icon"></span>
|
|
403
|
+
</label>
|
|
404
|
+
|
|
405
|
+
</div>
|
|
406
|
+
|
|
407
|
+
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_1_label" aria-expanded="false">
|
|
408
|
+
<label class="md-nav__title" for="__nav_1">
|
|
409
|
+
<span class="md-nav__icon md-icon"></span>
|
|
410
|
+
Overview
|
|
411
|
+
</label>
|
|
412
|
+
<ul class="md-nav__list" data-md-scrollfix>
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
<li class="md-nav__item">
|
|
421
|
+
<a href="/projects/core/en/stable/overview/design_philosophy.html" class="md-nav__link">
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
<span class="md-ellipsis">
|
|
425
|
+
Design Philosophy
|
|
426
|
+
</span>
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
</a>
|
|
430
|
+
</li>
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
<li class="md-nav__item">
|
|
442
|
+
<a href="/projects/core/en/stable/overview/application_stack.html" class="md-nav__link">
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
<span class="md-ellipsis">
|
|
446
|
+
Application Stack
|
|
447
|
+
</span>
|
|
448
|
+
|
|
449
|
+
|
|
383
450
|
</a>
|
|
384
451
|
</li>
|
|
385
452
|
|
|
386
453
|
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
</ul>
|
|
457
|
+
</nav>
|
|
458
|
+
|
|
459
|
+
</li>
|
|
460
|
+
|
|
461
|
+
|
|
387
462
|
|
|
388
463
|
|
|
389
464
|
|
|
@@ -7838,7 +7913,7 @@
|
|
|
7838
7913
|
<script id="__config" type="application/json">{"base": "/projects/core/en/stable/", "features": ["content.code.copy", "content.tabs.link", "navigation.footer", "navigation.tabs", "navigation.tabs.sticky", "navigation.tracking", "search.highlight", "search.share", "search.suggest"], "search": "/projects/core/en/stable/assets/javascripts/workers/search.b8dbb3d2.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
|
|
7839
7914
|
|
|
7840
7915
|
|
|
7841
|
-
<script src="/projects/core/en/stable/assets/javascripts/bundle.
|
|
7916
|
+
<script src="/projects/core/en/stable/assets/javascripts/bundle.fe8b6f2b.min.js"></script>
|
|
7842
7917
|
|
|
7843
7918
|
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
|
|
7844
7919
|
|