nautobot 2.2.6__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/core/api/mixins.py +6 -1
- nautobot/core/api/schema.py +3 -1
- nautobot/core/celery/__init__.py +1 -1
- nautobot/core/tests/runner.py +10 -0
- nautobot/extras/models/groups.py +9 -2
- nautobot/extras/tests/test_dynamicgroups.py +8 -1
- nautobot/extras/views.py +1 -1
- nautobot/ipam/api/serializers.py +46 -16
- nautobot/ipam/api/views.py +29 -16
- nautobot/ipam/tests/test_api.py +15 -20
- nautobot/project-static/docs/404.html +2 -2
- nautobot/project-static/docs/apps/index.html +2 -2
- nautobot/project-static/docs/apps/nautobot-apps.html +2 -2
- nautobot/project-static/docs/assets/javascripts/{bundle.ad660dcc.min.js → bundle.fe8b6f2b.min.js} +4 -4
- nautobot/project-static/docs/assets/javascripts/{bundle.ad660dcc.min.js.map → bundle.fe8b6f2b.min.js.map} +3 -3
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +2 -2
- nautobot/project-static/docs/development/apps/api/configuration-view.html +2 -2
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +2 -2
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +2 -2
- nautobot/project-static/docs/development/apps/api/models/global-search.html +2 -2
- nautobot/project-static/docs/development/apps/api/models/graphql.html +2 -2
- nautobot/project-static/docs/development/apps/api/models/index.html +2 -2
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +2 -2
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +2 -2
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +2 -2
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +2 -2
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +2 -2
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +2 -2
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +2 -2
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +2 -2
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +2 -2
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +2 -2
- nautobot/project-static/docs/development/apps/api/prometheus.html +2 -2
- nautobot/project-static/docs/development/apps/api/setup.html +2 -2
- nautobot/project-static/docs/development/apps/api/testing.html +2 -2
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +2 -2
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +2 -2
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +2 -2
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +2 -2
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/base-template.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/index.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/notes.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/urls.html +2 -2
- nautobot/project-static/docs/development/apps/index.html +2 -2
- nautobot/project-static/docs/development/apps/migration/code-updates.html +2 -2
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +2 -2
- nautobot/project-static/docs/development/apps/migration/from-v1.html +2 -2
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +2 -2
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +2 -2
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +2 -2
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +2 -2
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +2 -2
- nautobot/project-static/docs/development/core/application-registry.html +2 -2
- nautobot/project-static/docs/development/core/best-practices.html +2 -2
- nautobot/project-static/docs/development/core/bootstrap-ui.html +2 -2
- nautobot/project-static/docs/development/core/caching.html +2 -2
- nautobot/project-static/docs/development/core/controllers.html +2 -2
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +2 -2
- nautobot/project-static/docs/development/core/generic-views.html +2 -2
- nautobot/project-static/docs/development/core/getting-started.html +4 -5
- nautobot/project-static/docs/development/core/homepage.html +2 -2
- nautobot/project-static/docs/development/core/index.html +2 -2
- nautobot/project-static/docs/development/core/model-checklist.html +2 -2
- nautobot/project-static/docs/development/core/model-features.html +2 -2
- nautobot/project-static/docs/development/core/natural-keys.html +2 -2
- nautobot/project-static/docs/development/core/navigation-menu.html +2 -2
- nautobot/project-static/docs/development/core/release-checklist.html +2 -2
- nautobot/project-static/docs/development/core/role-internals.html +2 -2
- nautobot/project-static/docs/development/core/settings.html +2 -2
- nautobot/project-static/docs/development/core/style-guide.html +2 -2
- nautobot/project-static/docs/development/core/templates.html +2 -2
- nautobot/project-static/docs/development/core/testing.html +15 -3
- nautobot/project-static/docs/development/core/user-preferences.html +2 -2
- nautobot/project-static/docs/development/index.html +2 -2
- nautobot/project-static/docs/development/jobs/index.html +2 -2
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +2 -2
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +2 -2
- nautobot/project-static/docs/overview/design_philosophy.html +2 -2
- nautobot/project-static/docs/overview/index.html +2 -2
- nautobot/project-static/docs/release-notes/index.html +2 -2
- nautobot/project-static/docs/release-notes/version-1.0.html +2 -2
- nautobot/project-static/docs/release-notes/version-1.1.html +2 -2
- nautobot/project-static/docs/release-notes/version-1.2.html +2 -2
- nautobot/project-static/docs/release-notes/version-1.3.html +2 -2
- nautobot/project-static/docs/release-notes/version-1.4.html +2 -2
- nautobot/project-static/docs/release-notes/version-1.5.html +2 -2
- nautobot/project-static/docs/release-notes/version-1.6.html +2 -2
- nautobot/project-static/docs/release-notes/version-2.0.html +2 -2
- nautobot/project-static/docs/release-notes/version-2.1.html +2 -2
- nautobot/project-static/docs/release-notes/version-2.2.html +202 -77
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +256 -256
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +2 -2
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +2 -2
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +2 -2
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +2 -2
- nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +2 -2
- nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +2 -2
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +2 -2
- nautobot/project-static/docs/user-guide/administration/guides/caching.html +2 -2
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +2 -2
- nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +2 -2
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +2 -2
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +2 -2
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +2 -2
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +2 -2
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +2 -2
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +2 -2
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +2 -2
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +2 -2
- nautobot/project-static/docs/user-guide/administration/installation/index.html +2 -2
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +2 -2
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +2 -2
- nautobot/project-static/docs/user-guide/administration/installation/services.html +2 -2
- nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +2 -2
- nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +2 -2
- nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +2 -2
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +2 -2
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +2 -2
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +2 -2
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +2 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +2 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +2 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +2 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +2 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +2 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +2 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +2 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +2 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +2 -2
- nautobot/project-static/docs/user-guide/index.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +2 -2
- nautobot/project-static/js/connection_toggles.js +7 -6
- {nautobot-2.2.6.dist-info → nautobot-2.2.7.dist-info}/METADATA +2 -2
- {nautobot-2.2.6.dist-info → nautobot-2.2.7.dist-info}/RECORD +280 -280
- {nautobot-2.2.6.dist-info → nautobot-2.2.7.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.2.6.dist-info → nautobot-2.2.7.dist-info}/NOTICE +0 -0
- {nautobot-2.2.6.dist-info → nautobot-2.2.7.dist-info}/WHEEL +0 -0
- {nautobot-2.2.6.dist-info → nautobot-2.2.7.dist-info}/entry_points.txt +0 -0
nautobot/core/api/mixins.py
CHANGED
|
@@ -6,7 +6,7 @@ from django.core.exceptions import (
|
|
|
6
6
|
MultipleObjectsReturned,
|
|
7
7
|
ObjectDoesNotExist,
|
|
8
8
|
)
|
|
9
|
-
from django.db.models import AutoField
|
|
9
|
+
from django.db.models import AutoField, Model
|
|
10
10
|
from rest_framework.exceptions import ValidationError
|
|
11
11
|
|
|
12
12
|
from nautobot.core.api.utils import dict_to_filter_params
|
|
@@ -70,6 +70,11 @@ class WritableSerializerMixin:
|
|
|
70
70
|
# Strip the trailing slash and split on slashes, taking the last value as the PK.
|
|
71
71
|
data = data.rstrip("/").split("/")[-1]
|
|
72
72
|
|
|
73
|
+
# If we're passing the validated_data from one serializer as input to another serializer,
|
|
74
|
+
# data might already be a model instance:
|
|
75
|
+
if isinstance(data, Model):
|
|
76
|
+
return {"pk": data.pk}
|
|
77
|
+
|
|
73
78
|
try:
|
|
74
79
|
# The int case here is taking into account for the User model we inherit from django
|
|
75
80
|
pk = int(data) if isinstance(queryset.model._meta.pk, AutoField) else uuid.UUID(str(data))
|
nautobot/core/api/schema.py
CHANGED
|
@@ -4,7 +4,7 @@ import re
|
|
|
4
4
|
from drf_spectacular.contrib.django_filters import DjangoFilterExtension
|
|
5
5
|
from drf_spectacular.extensions import OpenApiSerializerFieldExtension
|
|
6
6
|
from drf_spectacular.openapi import AutoSchema
|
|
7
|
-
from drf_spectacular.plumbing import build_array_type, build_media_type_object, get_doc, is_serializer
|
|
7
|
+
from drf_spectacular.plumbing import build_array_type, build_media_type_object, get_doc, is_serializer, list_hash
|
|
8
8
|
from drf_spectacular.serializers import PolymorphicProxySerializerExtension
|
|
9
9
|
from rest_framework import serializers
|
|
10
10
|
from rest_framework.relations import ManyRelatedField
|
|
@@ -359,6 +359,8 @@ class ChoiceFieldFix(OpenApiSerializerFieldExtension):
|
|
|
359
359
|
return {
|
|
360
360
|
"type": value_type,
|
|
361
361
|
"enum": list(choices.keys()),
|
|
362
|
+
# Used to deduplicate enums with the same set of choices, since drf-spectacular 0.27.2
|
|
363
|
+
"x-spec-enum-id": list_hash([(k, v) for k, v in choices.items() if k not in ("", None)]),
|
|
362
364
|
}
|
|
363
365
|
else:
|
|
364
366
|
return {
|
nautobot/core/celery/__init__.py
CHANGED
|
@@ -109,7 +109,7 @@ def _import_jobs_from_git_repositories():
|
|
|
109
109
|
and not GitRepository.objects.filter(slug=filename).exists()
|
|
110
110
|
):
|
|
111
111
|
logger.warning("Deleting unmanaged (leftover?) Git repository clone at %s", filepath)
|
|
112
|
-
shutil.rmtree(filepath)
|
|
112
|
+
shutil.rmtree(filepath, ignore_errors=True)
|
|
113
113
|
|
|
114
114
|
# Make sure all GitRepository records that include Jobs have up-to-date git clones, and load their jobs
|
|
115
115
|
for repo in GitRepository.objects.filter(provided_contents__contains="extras.job"):
|
nautobot/core/tests/runner.py
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import copy
|
|
2
|
+
import hashlib
|
|
2
3
|
|
|
3
4
|
from django.conf import settings
|
|
4
5
|
from django.core.management import call_command
|
|
5
6
|
from django.db import connections
|
|
7
|
+
from django.db.migrations.recorder import MigrationRecorder
|
|
6
8
|
from django.test.runner import _init_worker, DiscoverRunner, ParallelTestSuite
|
|
7
9
|
from django.test.utils import get_unique_databases_and_mirrors, NullTimeKeeper, override_settings
|
|
8
10
|
import yaml
|
|
@@ -113,6 +115,14 @@ class NautobotTestRunner(DiscoverRunner):
|
|
|
113
115
|
command += ["--seed", settings.TEST_FACTORY_SEED]
|
|
114
116
|
if self.cache_test_fixtures:
|
|
115
117
|
command += ["--cache-test-fixtures"]
|
|
118
|
+
# Use the list of applied migrations as a unique hash to keep fixtures from differing
|
|
119
|
+
# branches/releases of Nautobot in separate files.
|
|
120
|
+
hexdigest = hashlib.shake_128(
|
|
121
|
+
",".join(
|
|
122
|
+
sorted(f"{m.app}.{m.name}" for m in MigrationRecorder.Migration.objects.all())
|
|
123
|
+
).encode("utf-8")
|
|
124
|
+
).hexdigest(10)
|
|
125
|
+
command += ["--fixture-file", f"development/factory_dump.{hexdigest}.json"]
|
|
116
126
|
with time_keeper.timed(f' Pre-populating test database "{alias}" with factory data...'):
|
|
117
127
|
db_command = [*command, "--database", alias]
|
|
118
128
|
call_command(*db_command)
|
nautobot/extras/models/groups.py
CHANGED
|
@@ -597,10 +597,17 @@ class DynamicGroup(OrganizationalModel):
|
|
|
597
597
|
query |= filter_field.generate_query(gq_value)
|
|
598
598
|
|
|
599
599
|
# For vanilla multiple-choice filters, we want all values in a set union (boolean OR)
|
|
600
|
-
# because we want ANY of the filter values to match.
|
|
600
|
+
# because we want ANY of the filter values to match. Unless the filter field is explicitly
|
|
601
|
+
# conjoining the values, in which case we want a set intersection (boolean AND). We know this isn't right
|
|
602
|
+
# since the resulting query actually does tag.name == tag_1 AND tag.name == tag_2, but django_filter does
|
|
603
|
+
# not use Q evaluation for conjoined filters. This function is only used for the display, and the display
|
|
604
|
+
# is good enough to get the point across.
|
|
601
605
|
elif isinstance(filter_field, django_filters.MultipleChoiceFilter):
|
|
602
606
|
for v in value:
|
|
603
|
-
|
|
607
|
+
if filter_field.conjoined:
|
|
608
|
+
query &= models.Q(**filter_field.get_filter_predicate(v))
|
|
609
|
+
else:
|
|
610
|
+
query |= models.Q(**filter_field.get_filter_predicate(v))
|
|
604
611
|
|
|
605
612
|
# The method `get_filter_predicate()` is only available on instances or subclasses
|
|
606
613
|
# of `MultipleChoiceFilter`, so we must construct a lookup if a filter is not
|
|
@@ -646,7 +646,7 @@ class DynamicGroupModelTest(DynamicGroupTestBase): # TODO: BaseModelTestCase mi
|
|
|
646
646
|
|
|
647
647
|
queryset = group.get_queryset()
|
|
648
648
|
|
|
649
|
-
# Assert that both querysets
|
|
649
|
+
# Assert that both querysets return the same results
|
|
650
650
|
group_qs = queryset.filter(multi_query)
|
|
651
651
|
device_qs = Device.objects.filter(location__name__in=multi_value)
|
|
652
652
|
self.assertQuerySetEqual(group_qs, device_qs)
|
|
@@ -659,6 +659,13 @@ class DynamicGroupModelTest(DynamicGroupTestBase): # TODO: BaseModelTestCase mi
|
|
|
659
659
|
interface_qs = Device.objects.filter(interfaces__isnull=True)
|
|
660
660
|
self.assertQuerySetEqual(solo_qs, interface_qs)
|
|
661
661
|
|
|
662
|
+
# Tags are conjoined in the TagFilterSet, ensure that tags__name is using AND. We know this isn't right
|
|
663
|
+
# since the resulting query actually does tag.name == tag_1 AND tag.name == tag_2, but django_filter does
|
|
664
|
+
# not use Q evaluation for conjoined filters. This function is only used for the display, and the display
|
|
665
|
+
# is good enough to get the point across.
|
|
666
|
+
tags_query = group.generate_query_for_filter(filter_field=fs.filters["tags"], value=["tag_1", "tag_2"])
|
|
667
|
+
self.assertEqual(str(tags_query), "(AND: ('tags__name', 'tag_1'), ('tags__name', 'tag_2'))")
|
|
668
|
+
|
|
662
669
|
# Test that a nested field_name w/ `generate_query` works as expected. This is explicitly to
|
|
663
670
|
# test a regression w/ nested name-related values such as `DeviceFilterSet.manufacturer` which
|
|
664
671
|
# filters on `device_type__manufacturer`.
|
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/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)
|
|
@@ -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
|
|
|
@@ -7913,7 +7913,7 @@
|
|
|
7913
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>
|
|
7914
7914
|
|
|
7915
7915
|
|
|
7916
|
-
<script src="/projects/core/en/stable/assets/javascripts/bundle.
|
|
7916
|
+
<script src="/projects/core/en/stable/assets/javascripts/bundle.fe8b6f2b.min.js"></script>
|
|
7917
7917
|
|
|
7918
7918
|
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
|
|
7919
7919
|
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
<link rel="icon" href="../assets/favicon.ico">
|
|
21
|
-
<meta name="generator" content="mkdocs-1.6.0, mkdocs-material-9.5.
|
|
21
|
+
<meta name="generator" content="mkdocs-1.6.0, mkdocs-material-9.5.28">
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
|
|
@@ -8080,7 +8080,7 @@
|
|
|
8080
8080
|
<script id="__config" type="application/json">{"base": "..", "features": ["content.code.copy", "content.tabs.link", "navigation.footer", "navigation.tabs", "navigation.tabs.sticky", "navigation.tracking", "search.highlight", "search.share", "search.suggest"], "search": "../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>
|
|
8081
8081
|
|
|
8082
8082
|
|
|
8083
|
-
<script src="../assets/javascripts/bundle.
|
|
8083
|
+
<script src="../assets/javascripts/bundle.fe8b6f2b.min.js"></script>
|
|
8084
8084
|
|
|
8085
8085
|
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
|
|
8086
8086
|
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
<link rel="icon" href="../assets/favicon.ico">
|
|
19
|
-
<meta name="generator" content="mkdocs-1.6.0, mkdocs-material-9.5.
|
|
19
|
+
<meta name="generator" content="mkdocs-1.6.0, mkdocs-material-9.5.28">
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
|
|
@@ -8014,7 +8014,7 @@
|
|
|
8014
8014
|
<script id="__config" type="application/json">{"base": "..", "features": ["content.code.copy", "content.tabs.link", "navigation.footer", "navigation.tabs", "navigation.tabs.sticky", "navigation.tracking", "search.highlight", "search.share", "search.suggest"], "search": "../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>
|
|
8015
8015
|
|
|
8016
8016
|
|
|
8017
|
-
<script src="../assets/javascripts/bundle.
|
|
8017
|
+
<script src="../assets/javascripts/bundle.fe8b6f2b.min.js"></script>
|
|
8018
8018
|
|
|
8019
8019
|
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
|
|
8020
8020
|
|