nautobot 2.3.0b1__py3-none-any.whl → 2.3.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of nautobot might be problematic. Click here for more details.
- nautobot/cloud/factory.py +2 -0
- nautobot/cloud/filters.py +3 -0
- nautobot/cloud/forms.py +8 -2
- nautobot/cloud/migrations/0001_initial.py +1 -1
- nautobot/cloud/models.py +1 -2
- nautobot/cloud/tables.py +1 -17
- nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +1 -7
- nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +11 -0
- nautobot/cloud/templates/cloud/cloudservice_retrieve.html +4 -0
- nautobot/cloud/tests/test_filters.py +12 -0
- nautobot/cloud/tests/test_views.py +17 -0
- nautobot/cloud/views.py +1 -1
- nautobot/core/celery/__init__.py +5 -2
- nautobot/core/celery/schedulers.py +18 -0
- nautobot/core/filters.py +15 -1
- nautobot/core/forms/forms.py +10 -2
- nautobot/core/graphql/generators.py +2 -2
- nautobot/core/graphql/schema.py +6 -14
- nautobot/core/jobs/__init__.py +4 -1
- nautobot/core/management/commands/generate_test_data.py +2 -2
- nautobot/core/models/__init__.py +2 -2
- nautobot/core/settings.py +13 -2
- nautobot/core/settings.yaml +19 -5
- nautobot/core/tables.py +4 -1
- nautobot/core/templates/generic/object_retrieve.html +6 -6
- nautobot/core/templates/home.html +4 -3
- nautobot/core/templates/inc/computed_fields/panel_data.html +36 -24
- nautobot/core/templates/inc/object_details_advanced_panel.html +1 -1
- nautobot/core/templates/nautobot_config.py.j2 +15 -0
- nautobot/core/templatetags/buttons.py +1 -1
- nautobot/core/testing/filters.py +12 -1
- nautobot/core/tests/integration/test_general_functionality.py +1 -1
- nautobot/core/tests/test_jobs.py +74 -1
- nautobot/core/views/__init__.py +1 -1
- nautobot/core/views/generic.py +1 -1
- nautobot/core/views/mixins.py +1 -1
- nautobot/core/views/utils.py +11 -9
- nautobot/dcim/factory.py +7 -4
- nautobot/dcim/filters/__init__.py +4 -0
- nautobot/dcim/forms.py +24 -0
- nautobot/dcim/migrations/0061_module_models.py +1 -0
- nautobot/dcim/models/device_components.py +7 -0
- nautobot/dcim/models/devices.py +18 -19
- nautobot/dcim/models/racks.py +0 -1
- nautobot/dcim/tables/devices.py +24 -10
- nautobot/dcim/tables/devicetypes.py +1 -1
- nautobot/dcim/templates/dcim/device/base.html +1 -1
- nautobot/dcim/templates/dcim/device.html +15 -3
- nautobot/dcim/templates/dcim/deviceredundancygroup_retrieve.html +6 -0
- nautobot/dcim/templates/dcim/moduletype_retrieve.html +17 -0
- nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +15 -3
- nautobot/dcim/tests/test_api.py +2 -0
- nautobot/dcim/tests/test_filters.py +14 -7
- nautobot/dcim/tests/test_forms.py +54 -0
- nautobot/dcim/tests/test_models.py +40 -1
- nautobot/dcim/tests/test_views.py +45 -2
- nautobot/dcim/utils.py +9 -6
- nautobot/dcim/views.py +4 -1
- nautobot/extras/api/serializers.py +2 -1
- nautobot/extras/api/views.py +7 -59
- nautobot/extras/factory.py +50 -12
- nautobot/extras/filters/__init__.py +18 -3
- nautobot/extras/forms/base.py +10 -4
- nautobot/extras/forms/forms.py +7 -0
- nautobot/extras/forms/mixins.py +2 -2
- nautobot/extras/homepage.py +12 -2
- nautobot/extras/jobs.py +2 -2
- nautobot/extras/management/__init__.py +3 -0
- nautobot/extras/migrations/0111_metadata.py +4 -4
- nautobot/extras/migrations/0114_computedfield_grouping.py +17 -0
- nautobot/extras/migrations/0115_scheduledjob_time_zone.py +23 -0
- nautobot/extras/models/customfields.py +54 -0
- nautobot/extras/models/jobs.py +105 -9
- nautobot/extras/models/metadata.py +18 -18
- nautobot/extras/models/models.py +2 -0
- nautobot/extras/signals.py +14 -1
- nautobot/extras/tables.py +77 -18
- nautobot/extras/templates/extras/computedfield.html +4 -0
- nautobot/extras/templates/extras/job_detail.html +11 -0
- nautobot/extras/templates/extras/scheduledjob.html +13 -2
- nautobot/extras/tests/test_api.py +33 -27
- nautobot/extras/tests/test_filters.py +57 -1
- nautobot/extras/tests/test_jobs.py +2 -2
- nautobot/extras/tests/test_models.py +319 -19
- nautobot/extras/tests/test_views.py +26 -5
- nautobot/extras/utils.py +35 -6
- nautobot/extras/views.py +35 -51
- nautobot/ipam/api/views.py +9 -2
- nautobot/ipam/choices.py +17 -0
- nautobot/ipam/factory.py +6 -0
- nautobot/ipam/filters.py +2 -2
- nautobot/ipam/forms.py +6 -4
- nautobot/ipam/migrations/0048_vrf_status.py +23 -0
- nautobot/ipam/migrations/0049_vrf_data_migration.py +25 -0
- nautobot/ipam/models.py +11 -20
- nautobot/ipam/querysets.py +26 -0
- nautobot/ipam/tables.py +7 -2
- nautobot/ipam/templates/ipam/vrf.html +4 -0
- nautobot/ipam/templates/ipam/vrf_edit.html +1 -0
- nautobot/ipam/tests/test_api.py +33 -3
- nautobot/ipam/tests/test_models.py +89 -2
- nautobot/ipam/tests/test_views.py +3 -0
- nautobot/ipam/views.py +10 -15
- nautobot/project-static/css/base.css +7 -0
- nautobot/project-static/docs/404.html +18 -18
- nautobot/project-static/docs/apps/index.html +18 -18
- nautobot/project-static/docs/apps/nautobot-apps.html +18 -18
- nautobot/project-static/docs/assets/stylesheets/main.3cba04c6.min.css +1 -0
- nautobot/project-static/docs/assets/stylesheets/main.3cba04c6.min.css.map +1 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +66 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +66 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +34 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +82 -63
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +75 -111
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +34 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +161 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +21 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +34 -18
- nautobot/project-static/docs/development/apps/api/configuration-view.html +18 -18
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +18 -18
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +18 -18
- nautobot/project-static/docs/development/apps/api/models/global-search.html +18 -18
- nautobot/project-static/docs/development/apps/api/models/graphql.html +18 -18
- nautobot/project-static/docs/development/apps/api/models/index.html +33 -22
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +18 -18
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +18 -18
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +18 -18
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +18 -18
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +18 -18
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +18 -18
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +18 -18
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +18 -18
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +18 -18
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +18 -18
- nautobot/project-static/docs/development/apps/api/prometheus.html +18 -18
- nautobot/project-static/docs/development/apps/api/setup.html +18 -18
- nautobot/project-static/docs/development/apps/api/testing.html +18 -18
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +18 -18
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +18 -18
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +18 -18
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +18 -18
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/base-template.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/index.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/notes.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/urls.html +18 -18
- nautobot/project-static/docs/development/apps/index.html +18 -18
- nautobot/project-static/docs/development/apps/migration/code-updates.html +18 -18
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +18 -18
- nautobot/project-static/docs/development/apps/migration/from-v1.html +18 -18
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +18 -18
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +18 -18
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +18 -18
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +18 -18
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +18 -18
- nautobot/project-static/docs/development/core/application-registry.html +18 -18
- nautobot/project-static/docs/development/core/best-practices.html +18 -18
- nautobot/project-static/docs/development/core/bootstrap-ui.html +18 -18
- nautobot/project-static/docs/development/core/caching.html +18 -18
- nautobot/project-static/docs/development/core/controllers.html +18 -18
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +18 -18
- nautobot/project-static/docs/development/core/generic-views.html +18 -18
- nautobot/project-static/docs/development/core/getting-started.html +18 -18
- nautobot/project-static/docs/development/core/homepage.html +18 -18
- nautobot/project-static/docs/development/core/index.html +29 -18
- nautobot/project-static/docs/development/core/model-checklist.html +26 -20
- nautobot/project-static/docs/development/core/model-features.html +18 -18
- nautobot/project-static/docs/development/core/natural-keys.html +18 -18
- nautobot/project-static/docs/development/core/navigation-menu.html +18 -18
- nautobot/project-static/docs/development/core/release-checklist.html +18 -18
- nautobot/project-static/docs/development/core/role-internals.html +18 -18
- nautobot/project-static/docs/development/core/settings.html +18 -18
- nautobot/project-static/docs/development/core/style-guide.html +19 -19
- nautobot/project-static/docs/development/core/templates.html +18 -18
- nautobot/project-static/docs/development/core/testing.html +18 -18
- nautobot/project-static/docs/development/core/user-preferences.html +18 -18
- nautobot/project-static/docs/development/index.html +18 -18
- nautobot/project-static/docs/development/jobs/index.html +393 -379
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +18 -18
- nautobot/project-static/docs/index.html +9032 -13
- nautobot/project-static/docs/models/extras/metadatachoice.html +3 -3
- nautobot/project-static/docs/models/extras/metadatatype.html +3 -3
- nautobot/project-static/docs/models/extras/objectmetadata.html +3 -3
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +18 -18
- nautobot/project-static/docs/overview/design_philosophy.html +20 -20
- nautobot/project-static/docs/overview/index.html +13 -9032
- nautobot/project-static/docs/release-notes/index.html +252 -19
- nautobot/project-static/docs/release-notes/version-1.0.html +18 -18
- nautobot/project-static/docs/release-notes/version-1.1.html +18 -18
- nautobot/project-static/docs/release-notes/version-1.2.html +18 -18
- nautobot/project-static/docs/release-notes/version-1.3.html +18 -18
- nautobot/project-static/docs/release-notes/version-1.4.html +18 -18
- nautobot/project-static/docs/release-notes/version-1.5.html +18 -18
- nautobot/project-static/docs/release-notes/version-1.6.html +18 -18
- nautobot/project-static/docs/release-notes/version-2.0.html +18 -18
- nautobot/project-static/docs/release-notes/version-2.1.html +18 -18
- nautobot/project-static/docs/release-notes/version-2.2.html +248 -111
- nautobot/project-static/docs/release-notes/version-2.3.html +775 -91
- nautobot/project-static/docs/requirements.txt +3 -3
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +278 -278
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +18 -18
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +18 -18
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +18 -18
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +18 -18
- nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +55 -23
- nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +18 -18
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +18 -18
- nautobot/project-static/docs/user-guide/administration/guides/caching.html +18 -18
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +22 -18
- nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +18 -18
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +18 -18
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +18 -18
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +18 -18
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +18 -18
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +18 -18
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +18 -18
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +18 -18
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +69 -82
- nautobot/project-static/docs/user-guide/administration/installation/index.html +24 -24
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +60 -52
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +80 -87
- nautobot/project-static/docs/user-guide/administration/installation/services.html +37 -44
- nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +18 -18
- nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +18 -18
- nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +18 -18
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +18 -18
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +18 -18
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +76 -24
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +18 -18
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +18 -18
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +18 -18
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +18 -18
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +18 -18
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +18 -18
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +18 -18
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +18 -18
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +18 -18
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +19 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +19 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +62 -18
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +18 -18
- nautobot/project-static/docs/user-guide/index.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +21 -21
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +36 -36
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +33 -33
- nautobot/project-static/docs/user-guide/platform-functionality/{metadata.html → objectmetadata.html} +197 -84
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +21 -21
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +18 -18
- nautobot/project-static/js/homepage_layout.js +3 -0
- nautobot/tenancy/templates/tenancy/tenant.html +4 -4
- nautobot/virtualization/models.py +0 -2
- nautobot/virtualization/tables.py +2 -5
- {nautobot-2.3.0b1.dist-info → nautobot-2.3.2.dist-info}/METADATA +3 -3
- {nautobot-2.3.0b1.dist-info → nautobot-2.3.2.dist-info}/RECORD +397 -393
- nautobot/project-static/docs/assets/stylesheets/main.76a95c52.min.css +0 -1
- nautobot/project-static/docs/assets/stylesheets/main.76a95c52.min.css.map +0 -1
- {nautobot-2.3.0b1.dist-info → nautobot-2.3.2.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.3.0b1.dist-info → nautobot-2.3.2.dist-info}/NOTICE +0 -0
- {nautobot-2.3.0b1.dist-info → nautobot-2.3.2.dist-info}/WHEEL +0 -0
- {nautobot-2.3.0b1.dist-info → nautobot-2.3.2.dist-info}/entry_points.txt +0 -0
nautobot/ipam/tests/test_api.py
CHANGED
|
@@ -13,7 +13,7 @@ from nautobot.core.testing import APITestCase, APIViewTestCases, disable_warning
|
|
|
13
13
|
from nautobot.core.testing.api import APITransactionTestCase
|
|
14
14
|
from nautobot.dcim.choices import InterfaceTypeChoices
|
|
15
15
|
from nautobot.dcim.models import Device, DeviceType, Interface, Location, LocationType, Manufacturer
|
|
16
|
-
from nautobot.extras.models import Role, Status
|
|
16
|
+
from nautobot.extras.models import CustomField, Role, Status
|
|
17
17
|
from nautobot.ipam import choices
|
|
18
18
|
from nautobot.ipam.models import (
|
|
19
19
|
IPAddress,
|
|
@@ -84,11 +84,14 @@ class VRFTest(APIViewTestCases.APIViewTestCase):
|
|
|
84
84
|
@classmethod
|
|
85
85
|
def setUpTestData(cls):
|
|
86
86
|
namespace = Namespace.objects.first()
|
|
87
|
+
vrf_statuses = Status.objects.get_for_model(VRF)
|
|
88
|
+
|
|
87
89
|
cls.create_data = [
|
|
88
90
|
{
|
|
89
91
|
"namespace": namespace.pk,
|
|
90
92
|
"name": "VRF 4",
|
|
91
93
|
"rd": "65000:4",
|
|
94
|
+
"status": vrf_statuses.first().pk,
|
|
92
95
|
},
|
|
93
96
|
{
|
|
94
97
|
"namespace": namespace.pk,
|
|
@@ -98,10 +101,12 @@ class VRFTest(APIViewTestCases.APIViewTestCase):
|
|
|
98
101
|
{
|
|
99
102
|
"name": "VRF 6",
|
|
100
103
|
"rd": "65000:6",
|
|
104
|
+
"status": vrf_statuses.last().pk,
|
|
101
105
|
},
|
|
102
106
|
]
|
|
103
107
|
cls.bulk_update_data = {
|
|
104
108
|
"description": "New description",
|
|
109
|
+
"status": vrf_statuses.last().pk,
|
|
105
110
|
}
|
|
106
111
|
|
|
107
112
|
|
|
@@ -332,6 +337,8 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
|
|
|
332
337
|
cls.statuses = Status.objects.get_for_model(Prefix)
|
|
333
338
|
cls.status = cls.statuses[0]
|
|
334
339
|
cls.locations = Location.objects.get_for_model(Prefix)
|
|
340
|
+
cls.custom_field = CustomField.objects.create(key="prefixcf", label="Prefix Custom Field", type="text")
|
|
341
|
+
cls.custom_field.content_types.add(ContentType.objects.get_for_model(Prefix))
|
|
335
342
|
cls.create_data = [
|
|
336
343
|
{
|
|
337
344
|
"prefix": "192.168.4.0/24",
|
|
@@ -346,6 +353,7 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
|
|
|
346
353
|
"rir": rir.pk,
|
|
347
354
|
"type": choices.PrefixTypeChoices.TYPE_NETWORK,
|
|
348
355
|
"namespace": cls.namespace.pk,
|
|
356
|
+
"custom_fields": {"prefixcf": "hello world"},
|
|
349
357
|
},
|
|
350
358
|
{
|
|
351
359
|
"prefix": "192.168.6.0/24",
|
|
@@ -457,12 +465,16 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
|
|
|
457
465
|
"prefix_length": child_prefix_length,
|
|
458
466
|
"status": self.status.pk,
|
|
459
467
|
"description": f"Test Prefix {i + 1}",
|
|
468
|
+
"custom_fields": {"prefixcf": f"value {i+1}"},
|
|
460
469
|
}
|
|
461
470
|
response = self.client.post(url, data, format="json", **self.header)
|
|
462
471
|
self.assertHttpStatus(response, status.HTTP_201_CREATED)
|
|
463
472
|
self.assertEqual(response.data["prefix"], str(prefixes_to_be_created[i]))
|
|
464
473
|
self.assertEqual(str(response.data["namespace"]["url"]), self.absolute_api_url(prefix.namespace))
|
|
465
474
|
self.assertEqual(response.data["description"], data["description"])
|
|
475
|
+
self.assertIn("custom_fields", response.data)
|
|
476
|
+
self.assertIn("prefixcf", response.data["custom_fields"])
|
|
477
|
+
self.assertEqual(response.data["custom_fields"]["prefixcf"], data["custom_fields"]["prefixcf"])
|
|
466
478
|
|
|
467
479
|
# Try to create one more prefix, and expect a HTTP 204 response.
|
|
468
480
|
# This feels wrong to me (shouldn't it be a 4xx or 5xx?) but it's how the API has historically behaved.
|
|
@@ -501,6 +513,7 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
|
|
|
501
513
|
"prefix_length": child_prefix_length,
|
|
502
514
|
"description": "Test Prefix 1",
|
|
503
515
|
"status": self.status.pk,
|
|
516
|
+
"custom_fields": {"prefixcf": "value 1"},
|
|
504
517
|
},
|
|
505
518
|
{
|
|
506
519
|
"prefix_length": child_prefix_length,
|
|
@@ -537,6 +550,9 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
|
|
|
537
550
|
response = self.client.post(url, data[:4], format="json", **self.header)
|
|
538
551
|
self.assertHttpStatus(response, status.HTTP_201_CREATED)
|
|
539
552
|
self.assertEqual(len(response.data), 4)
|
|
553
|
+
self.assertIn("custom_fields", response.data[0])
|
|
554
|
+
self.assertIn("prefixcf", response.data[0]["custom_fields"])
|
|
555
|
+
self.assertEqual("value 1", response.data[0]["custom_fields"]["prefixcf"])
|
|
540
556
|
|
|
541
557
|
def test_list_available_ips(self):
|
|
542
558
|
"""
|
|
@@ -571,6 +587,8 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
|
|
|
571
587
|
type=choices.PrefixTypeChoices.TYPE_NETWORK,
|
|
572
588
|
status=self.status,
|
|
573
589
|
)
|
|
590
|
+
cf = CustomField.objects.create(key="ipcf", label="IP Custom Field", type="text")
|
|
591
|
+
cf.content_types.add(ContentType.objects.get_for_model(IPAddress))
|
|
574
592
|
url = reverse("ipam-api:prefix-available-ips", kwargs={"pk": prefix.pk})
|
|
575
593
|
self.add_permissions("ipam.view_prefix", "ipam.add_ipaddress", "extras.view_status")
|
|
576
594
|
|
|
@@ -579,11 +597,15 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
|
|
|
579
597
|
data = {
|
|
580
598
|
"description": f"Test IP {i}",
|
|
581
599
|
"status": self.status.pk,
|
|
600
|
+
"custom_fields": {"ipcf": f"value {i}"},
|
|
582
601
|
}
|
|
583
602
|
response = self.client.post(url, data, format="json", **self.header)
|
|
584
603
|
self.assertHttpStatus(response, status.HTTP_201_CREATED)
|
|
585
604
|
self.assertEqual(str(response.data["parent"]["url"]), self.absolute_api_url(prefix))
|
|
586
605
|
self.assertEqual(response.data["description"], data["description"])
|
|
606
|
+
self.assertIn("custom_fields", response.data)
|
|
607
|
+
self.assertIn("ipcf", response.data["custom_fields"])
|
|
608
|
+
self.assertEqual(f"value {i}", response.data["custom_fields"]["ipcf"])
|
|
587
609
|
|
|
588
610
|
# Try to create one more IP
|
|
589
611
|
response = self.client.post(url, {"status": self.status.pk}, format="json", **self.header)
|
|
@@ -601,21 +623,29 @@ class PrefixTest(APIViewTestCases.APIViewTestCase):
|
|
|
601
623
|
namespace=self.namespace,
|
|
602
624
|
status=self.status,
|
|
603
625
|
)
|
|
626
|
+
cf = CustomField.objects.create(key="ipcf", label="IP Custom Field", type="text")
|
|
627
|
+
cf.content_types.add(ContentType.objects.get_for_model(IPAddress))
|
|
604
628
|
url = reverse("ipam-api:prefix-available-ips", kwargs={"pk": prefix.pk})
|
|
605
629
|
self.add_permissions("ipam.view_prefix", "ipam.add_ipaddress", "extras.view_status")
|
|
606
630
|
|
|
607
631
|
# Try to create seven IPs (only six are available)
|
|
608
|
-
data = [
|
|
632
|
+
data = [
|
|
633
|
+
{"description": f"Test IP {i}", "status": self.status.pk, "custom_fields": {"ipcf": str(i)}}
|
|
634
|
+
for i in range(1, 8)
|
|
635
|
+
] # 7 IPs
|
|
609
636
|
response = self.client.post(url, data, format="json", **self.header)
|
|
610
637
|
# This feels wrong to me (shouldn't it be a 4xx or 5xx?) but it's how the API has historically behaved.
|
|
611
638
|
self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
|
|
612
639
|
self.assertIn("detail", response.data)
|
|
613
640
|
|
|
614
641
|
# Create all six available IPs in a single request
|
|
615
|
-
data = [
|
|
642
|
+
data = data[:6]
|
|
616
643
|
response = self.client.post(url, data, format="json", **self.header)
|
|
617
644
|
self.assertHttpStatus(response, status.HTTP_201_CREATED)
|
|
618
645
|
self.assertEqual(len(response.data), 6)
|
|
646
|
+
self.assertIn("custom_fields", response.data[0])
|
|
647
|
+
self.assertIn("ipcf", response.data[0]["custom_fields"])
|
|
648
|
+
self.assertEqual("1", response.data[0]["custom_fields"]["ipcf"])
|
|
619
649
|
|
|
620
650
|
|
|
621
651
|
class PrefixLocationAssignmentTest(APIViewTestCases.APIViewTestCase):
|
|
@@ -962,6 +962,92 @@ class TestIPAddress(ModelTestCases.BaseModelTestCase):
|
|
|
962
962
|
self.status = Status.objects.get(name="Active")
|
|
963
963
|
self.prefix = Prefix.objects.create(prefix="192.0.2.0/24", status=self.status, namespace=self.namespace)
|
|
964
964
|
|
|
965
|
+
def test_get_or_create(self):
|
|
966
|
+
"""Assert `get_or_create` method to permit specifying a namespace as an alternative to a parent prefix."""
|
|
967
|
+
default_namespace = get_default_namespace()
|
|
968
|
+
namespace = Namespace.objects.create(name="Test Namespace")
|
|
969
|
+
|
|
970
|
+
ipaddr_status = Status.objects.get_for_model(IPAddress).first()
|
|
971
|
+
prefix_status = Status.objects.get_for_model(Prefix).first()
|
|
972
|
+
|
|
973
|
+
parent = Prefix.objects.create(prefix="10.1.1.0/24", namespace=namespace, status=prefix_status)
|
|
974
|
+
default_namespace_parent = Prefix.objects.create(
|
|
975
|
+
prefix="10.0.0.0/24", namespace=default_namespace, status=prefix_status
|
|
976
|
+
)
|
|
977
|
+
|
|
978
|
+
ipaddress = IPAddress.objects.create(address="10.1.1.1/24", namespace=namespace, status=ipaddr_status)
|
|
979
|
+
default_namespace_ipaddress = IPAddress.objects.create(
|
|
980
|
+
address="10.0.0.1/24", namespace=default_namespace, status=ipaddr_status
|
|
981
|
+
)
|
|
982
|
+
mask_length = 24
|
|
983
|
+
|
|
984
|
+
with self.subTest("Assert retrieve"):
|
|
985
|
+
ip_obj, created = IPAddress.objects.get_or_create(
|
|
986
|
+
host=ipaddress.host,
|
|
987
|
+
mask_length=mask_length,
|
|
988
|
+
namespace=namespace,
|
|
989
|
+
status=ipaddr_status,
|
|
990
|
+
)
|
|
991
|
+
self.assertEqual(ip_obj, ipaddress)
|
|
992
|
+
self.assertFalse(created)
|
|
993
|
+
|
|
994
|
+
ip_obj, created = IPAddress.objects.get_or_create(host=ipaddress.host, status=ipaddr_status)
|
|
995
|
+
self.assertEqual(ip_obj.status, ipaddr_status)
|
|
996
|
+
self.assertFalse(created)
|
|
997
|
+
|
|
998
|
+
with self.subTest(
|
|
999
|
+
"Assert get_or_create utilizes default namespace when retrieving parent if no namespace is provided"
|
|
1000
|
+
):
|
|
1001
|
+
ip_obj, created = IPAddress.objects.get_or_create(
|
|
1002
|
+
host=default_namespace_ipaddress.host,
|
|
1003
|
+
mask_length=default_namespace_ipaddress.mask_length,
|
|
1004
|
+
status=ipaddr_status,
|
|
1005
|
+
)
|
|
1006
|
+
self.assertEqual(ip_obj, default_namespace_ipaddress)
|
|
1007
|
+
self.assertFalse(created)
|
|
1008
|
+
|
|
1009
|
+
with self.subTest("Assert create"):
|
|
1010
|
+
new_host = "10.0.0.2"
|
|
1011
|
+
ip_obj, created = IPAddress.objects.get_or_create(
|
|
1012
|
+
host=new_host,
|
|
1013
|
+
mask_length=mask_length,
|
|
1014
|
+
status=ipaddr_status,
|
|
1015
|
+
)
|
|
1016
|
+
self.assertEqual(ip_obj.host, new_host)
|
|
1017
|
+
self.assertEqual(ip_obj.mask_length, mask_length)
|
|
1018
|
+
self.assertEqual(ip_obj.parent, default_namespace_parent)
|
|
1019
|
+
self.assertEqual(ip_obj.parent.namespace, default_namespace)
|
|
1020
|
+
self.assertTrue(created)
|
|
1021
|
+
|
|
1022
|
+
with self.subTest("Assert create explicitly defining a non default namespace"):
|
|
1023
|
+
new_host = "10.1.1.2"
|
|
1024
|
+
ip_obj, created = IPAddress.objects.get_or_create(
|
|
1025
|
+
host=new_host, mask_length=mask_length, status=ipaddr_status, namespace=namespace
|
|
1026
|
+
)
|
|
1027
|
+
self.assertEqual(ip_obj.host, new_host)
|
|
1028
|
+
self.assertEqual(ip_obj.mask_length, mask_length)
|
|
1029
|
+
self.assertEqual(ip_obj.parent, parent)
|
|
1030
|
+
self.assertEqual(ip_obj.parent.namespace, namespace)
|
|
1031
|
+
self.assertTrue(created)
|
|
1032
|
+
|
|
1033
|
+
with self.subTest("Assert passing invalid host/mask_length"):
|
|
1034
|
+
with self.assertRaises(ValidationError) as err:
|
|
1035
|
+
IPAddress.objects.get_or_create(
|
|
1036
|
+
host="0.000.0", mask_length=mask_length, status=ipaddr_status, namespace=namespace
|
|
1037
|
+
)
|
|
1038
|
+
self.assertIn(
|
|
1039
|
+
"Enter a valid IPv4 or IPv6 address.",
|
|
1040
|
+
str(err.exception),
|
|
1041
|
+
)
|
|
1042
|
+
with self.assertRaises(ValidationError) as err:
|
|
1043
|
+
IPAddress.objects.get_or_create(
|
|
1044
|
+
host=ipaddress.host, mask_length=5712, status=ipaddr_status, namespace=namespace
|
|
1045
|
+
)
|
|
1046
|
+
self.assertIn(
|
|
1047
|
+
f"{ipaddress.host}/5712 does not appear to be an IPv4 or IPv6 network.",
|
|
1048
|
+
str(err.exception),
|
|
1049
|
+
)
|
|
1050
|
+
|
|
965
1051
|
def test_create_field_population(self):
|
|
966
1052
|
"""Test that the various ways of creating an IPAddress result in correctly populated fields."""
|
|
967
1053
|
if self.namespace != get_default_namespace():
|
|
@@ -1003,8 +1089,9 @@ class TestIPAddress(ModelTestCases.BaseModelTestCase):
|
|
|
1003
1089
|
def test_duplicate_global_unique(self):
|
|
1004
1090
|
"""Test that duplicate IPs in the same Namespace raises an error."""
|
|
1005
1091
|
IPAddress.objects.create(address="192.0.2.1/24", status=self.status, namespace=self.namespace)
|
|
1006
|
-
|
|
1007
|
-
|
|
1092
|
+
duplicate_ip = IPAddress(address="192.0.2.1/24", status=self.status, namespace=self.namespace)
|
|
1093
|
+
with self.assertRaises(ValidationError):
|
|
1094
|
+
duplicate_ip.full_clean()
|
|
1008
1095
|
|
|
1009
1096
|
def test_multiple_nat_outside_list(self):
|
|
1010
1097
|
"""
|
|
@@ -73,6 +73,7 @@ class VRFTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
|
73
73
|
tenants = Tenant.objects.all()[:2]
|
|
74
74
|
namespace = Prefix.objects.first().namespace
|
|
75
75
|
prefixes = Prefix.objects.filter(namespace=namespace)
|
|
76
|
+
vrf_statuses = Status.objects.get_for_model(VRF)
|
|
76
77
|
|
|
77
78
|
cls.form_data = {
|
|
78
79
|
"name": "VRF X",
|
|
@@ -82,9 +83,11 @@ class VRFTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
|
82
83
|
"description": "A new VRF",
|
|
83
84
|
"prefixes": [prefixes[1].id],
|
|
84
85
|
"tags": [t.pk for t in Tag.objects.get_for_model(VRF)],
|
|
86
|
+
"status": vrf_statuses.first().pk,
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
cls.bulk_edit_data = {
|
|
90
|
+
"status": vrf_statuses.first().pk,
|
|
88
91
|
"tenant": tenants[1].pk,
|
|
89
92
|
"description": "New description",
|
|
90
93
|
"namespace": prefixes[0].namespace.id,
|
nautobot/ipam/views.py
CHANGED
|
@@ -15,7 +15,7 @@ from django.views.generic import View
|
|
|
15
15
|
from django_tables2 import RequestConfig
|
|
16
16
|
import netaddr
|
|
17
17
|
|
|
18
|
-
from nautobot.cloud.tables import
|
|
18
|
+
from nautobot.cloud.tables import CloudNetworkTable
|
|
19
19
|
from nautobot.core.models.querysets import count_related
|
|
20
20
|
from nautobot.core.utils.config import get_settings_or_config
|
|
21
21
|
from nautobot.core.utils.permissions import get_permission_for_model
|
|
@@ -250,7 +250,7 @@ class VRFView(generic.ObjectView):
|
|
|
250
250
|
|
|
251
251
|
prefixes = instance.prefixes.restrict(request.user, "view")
|
|
252
252
|
prefix_count = prefixes.count()
|
|
253
|
-
prefix_table = tables.PrefixTable(prefixes.select_related("namespace"))
|
|
253
|
+
prefix_table = tables.PrefixTable(prefixes.select_related("namespace"), hide_hierarchy_ui=True)
|
|
254
254
|
|
|
255
255
|
# devices = instance.devices.restrict(request.user, "view")
|
|
256
256
|
# device_count = devices.count()
|
|
@@ -390,7 +390,7 @@ class RIRView(generic.ObjectView):
|
|
|
390
390
|
# Prefixes
|
|
391
391
|
assigned_prefixes = Prefix.objects.restrict(request.user, "view").filter(rir=instance).select_related("tenant")
|
|
392
392
|
|
|
393
|
-
assigned_prefix_table = tables.PrefixTable(assigned_prefixes)
|
|
393
|
+
assigned_prefix_table = tables.PrefixTable(assigned_prefixes, hide_hierarchy_ui=True)
|
|
394
394
|
|
|
395
395
|
paginate = {
|
|
396
396
|
"paginator_class": EnhancedPaginator,
|
|
@@ -456,8 +456,9 @@ class PrefixView(generic.ObjectView):
|
|
|
456
456
|
vrfs = instance.vrf_assignments.restrict(request.user, "view")
|
|
457
457
|
vrf_table = tables.VRFPrefixAssignmentTable(vrfs, orderable=False)
|
|
458
458
|
|
|
459
|
-
cloud_networks = instance.
|
|
460
|
-
cloud_network_table =
|
|
459
|
+
cloud_networks = instance.cloud_networks.restrict(request.user, "view")
|
|
460
|
+
cloud_network_table = CloudNetworkTable(cloud_networks, orderable=False)
|
|
461
|
+
cloud_network_table.exclude = ("actions", "assigned_prefix_count", "circuit_count", "cloud_service_count")
|
|
461
462
|
|
|
462
463
|
return {
|
|
463
464
|
"vrf_table": vrf_table,
|
|
@@ -484,7 +485,7 @@ class PrefixPrefixesView(generic.ObjectView):
|
|
|
484
485
|
if child_prefixes and request.GET.get("show_available", "true") == "true":
|
|
485
486
|
child_prefixes = add_available_prefixes(instance.prefix, child_prefixes)
|
|
486
487
|
|
|
487
|
-
prefix_table = tables.PrefixDetailTable(child_prefixes)
|
|
488
|
+
prefix_table = tables.PrefixDetailTable(child_prefixes, hide_hierarchy_ui=True)
|
|
488
489
|
prefix_table.exclude = ("namespace",)
|
|
489
490
|
if request.user.has_perm("ipam.change_prefix") or request.user.has_perm("ipam.delete_prefix"):
|
|
490
491
|
prefix_table.columns.show("pk")
|
|
@@ -934,14 +935,8 @@ class IPAddressAssignView(view_mixins.GetReturnURLMixin, generic.ObjectView):
|
|
|
934
935
|
ip_addresses = IPAddress.objects.restrict(request.user, "view").filter(pk__in=pks)
|
|
935
936
|
interface.ip_addresses.add(*ip_addresses)
|
|
936
937
|
return redirect(self.get_return_url(request))
|
|
937
|
-
|
|
938
|
-
return
|
|
939
|
-
request,
|
|
940
|
-
"ipam/ipaddress_assign.html",
|
|
941
|
-
{
|
|
942
|
-
"return_url": self.get_return_url(request),
|
|
943
|
-
},
|
|
944
|
-
)
|
|
938
|
+
messages.error(request, "Please select at least one IP Address from the table.")
|
|
939
|
+
return redirect(request.get_full_path())
|
|
945
940
|
|
|
946
941
|
|
|
947
942
|
class IPAddressMergeView(view_mixins.GetReturnURLMixin, view_mixins.ObjectPermissionRequiredMixin, View):
|
|
@@ -1318,7 +1313,7 @@ class VLANView(generic.ObjectView):
|
|
|
1318
1313
|
"namespace",
|
|
1319
1314
|
)
|
|
1320
1315
|
)
|
|
1321
|
-
prefix_table = tables.PrefixTable(list(prefixes))
|
|
1316
|
+
prefix_table = tables.PrefixTable(list(prefixes), hide_hierarchy_ui=True)
|
|
1322
1317
|
prefix_table.exclude = ("vlan",)
|
|
1323
1318
|
|
|
1324
1319
|
return {"prefix_table": prefix_table, **super().get_extra_context(request, instance)}
|
|
@@ -300,6 +300,7 @@ table.report th a {
|
|
|
300
300
|
}
|
|
301
301
|
.panel table {
|
|
302
302
|
margin-bottom: 0;
|
|
303
|
+
overflow: hidden;
|
|
303
304
|
}
|
|
304
305
|
.panel .table th {
|
|
305
306
|
border-bottom-width: 1px;
|
|
@@ -861,6 +862,12 @@ td span.hover_copy:hover .hover_copy_button {
|
|
|
861
862
|
.collapse-icon {
|
|
862
863
|
float: right;
|
|
863
864
|
cursor: pointer !important;
|
|
865
|
+
transition: transform 0.3s ease;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
/* Rotates element 180 degrees */
|
|
869
|
+
.rotated180 {
|
|
870
|
+
transform: rotate(180deg);
|
|
864
871
|
}
|
|
865
872
|
|
|
866
873
|
/* Draggable homepage panels fade in effect on page load */
|
|
@@ -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.31">
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
<link rel="stylesheet" href="/projects/core/en/stable/assets/stylesheets/main.
|
|
23
|
+
<link rel="stylesheet" href="/projects/core/en/stable/assets/stylesheets/main.3cba04c6.min.css">
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
<link rel="stylesheet" href="/projects/core/en/stable/assets/stylesheets/palette.06af60db.min.css">
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
<style>:root{--md-admonition-icon--example:url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.
|
|
35
|
+
<style>:root{--md-admonition-icon--example:url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M288 0H128c-17.7 0-32 14.3-32 32s14.3 32 32 32v132.8c0 11.8-3.3 23.5-9.5 33.5L10.3 406.2C3.6 417.2 0 429.7 0 442.6 0 480.9 31.1 512 69.4 512h309.2c38.3 0 69.4-31.1 69.4-69.4 0-12.8-3.6-25.4-10.3-36.4L329.5 230.4c-6.2-10.1-9.5-21.7-9.5-33.5V64c17.7 0 32-14.3 32-32S337.7 0 320 0h-32zm-96 196.8V64h64v132.8c0 23.7 6.6 46.9 19 67.1l34.5 56.1h-171l34.5-56.1c12.4-20.2 19-43.4 19-67.1z"/></svg>');}</style>
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
|
|
@@ -197,7 +197,7 @@
|
|
|
197
197
|
<a href="https://github.com/nautobot/nautobot" title="Go to repository" class="md-source" data-md-component="source">
|
|
198
198
|
<div class="md-source__icon md-icon">
|
|
199
199
|
|
|
200
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.
|
|
200
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
|
|
201
201
|
</div>
|
|
202
202
|
<div class="md-source__repository">
|
|
203
203
|
GitHub
|
|
@@ -218,7 +218,7 @@
|
|
|
218
218
|
|
|
219
219
|
|
|
220
220
|
<li class="md-tabs__item">
|
|
221
|
-
<a href="/projects/core/en/stable/
|
|
221
|
+
<a href="/projects/core/en/stable/index.html" class="md-tabs__link">
|
|
222
222
|
|
|
223
223
|
|
|
224
224
|
|
|
@@ -355,7 +355,7 @@
|
|
|
355
355
|
<a href="https://github.com/nautobot/nautobot" title="Go to repository" class="md-source" data-md-component="source">
|
|
356
356
|
<div class="md-source__icon md-icon">
|
|
357
357
|
|
|
358
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.
|
|
358
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
|
|
359
359
|
</div>
|
|
360
360
|
<div class="md-source__repository">
|
|
361
361
|
GitHub
|
|
@@ -387,7 +387,7 @@
|
|
|
387
387
|
|
|
388
388
|
|
|
389
389
|
<div class="md-nav__link md-nav__container">
|
|
390
|
-
<a href="/projects/core/en/stable/
|
|
390
|
+
<a href="/projects/core/en/stable/index.html" class="md-nav__link ">
|
|
391
391
|
|
|
392
392
|
|
|
393
393
|
<span class="md-ellipsis">
|
|
@@ -5131,11 +5131,11 @@
|
|
|
5131
5131
|
|
|
5132
5132
|
|
|
5133
5133
|
<li class="md-nav__item">
|
|
5134
|
-
<a href="/projects/core/en/stable/user-guide/platform-functionality/
|
|
5134
|
+
<a href="/projects/core/en/stable/user-guide/platform-functionality/napalm.html" class="md-nav__link">
|
|
5135
5135
|
|
|
5136
5136
|
|
|
5137
5137
|
<span class="md-ellipsis">
|
|
5138
|
-
|
|
5138
|
+
NAPALM
|
|
5139
5139
|
</span>
|
|
5140
5140
|
|
|
5141
5141
|
|
|
@@ -5152,11 +5152,11 @@
|
|
|
5152
5152
|
|
|
5153
5153
|
|
|
5154
5154
|
<li class="md-nav__item">
|
|
5155
|
-
<a href="/projects/core/en/stable/user-guide/platform-functionality/
|
|
5155
|
+
<a href="/projects/core/en/stable/user-guide/platform-functionality/note.html" class="md-nav__link">
|
|
5156
5156
|
|
|
5157
5157
|
|
|
5158
5158
|
<span class="md-ellipsis">
|
|
5159
|
-
|
|
5159
|
+
Notes
|
|
5160
5160
|
</span>
|
|
5161
5161
|
|
|
5162
5162
|
|
|
@@ -5173,11 +5173,11 @@
|
|
|
5173
5173
|
|
|
5174
5174
|
|
|
5175
5175
|
<li class="md-nav__item">
|
|
5176
|
-
<a href="/projects/core/en/stable/user-guide/platform-functionality/
|
|
5176
|
+
<a href="/projects/core/en/stable/user-guide/platform-functionality/objectmetadata.html" class="md-nav__link">
|
|
5177
5177
|
|
|
5178
5178
|
|
|
5179
5179
|
<span class="md-ellipsis">
|
|
5180
|
-
|
|
5180
|
+
Object Metadata
|
|
5181
5181
|
</span>
|
|
5182
5182
|
|
|
5183
5183
|
|
|
@@ -8667,7 +8667,7 @@
|
|
|
8667
8667
|
|
|
8668
8668
|
|
|
8669
8669
|
<a href="https://blog.networktocode.com/blog/tags/nautobot" target="_blank" rel="noopener" title="Network to Code Blog" class="md-social__link">
|
|
8670
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.
|
|
8670
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M0 64c0-17.7 14.3-32 32-32 229.8 0 416 186.2 416 416 0 17.7-14.3 32-32 32s-32-14.3-32-32C384 253.6 226.4 96 32 96 14.3 96 0 81.7 0 64zm0 352a64 64 0 1 1 128 0 64 64 0 1 1-128 0zm32-256c159.1 0 288 128.9 288 288 0 17.7-14.3 32-32 32s-32-14.3-32-32c0-123.7-100.3-224-224-224-17.7 0-32-14.3-32-32s14.3-32 32-32z"/></svg>
|
|
8671
8671
|
</a>
|
|
8672
8672
|
|
|
8673
8673
|
|
|
@@ -8675,7 +8675,7 @@
|
|
|
8675
8675
|
|
|
8676
8676
|
|
|
8677
8677
|
<a href="https://www.youtube.com/playlist?list=PLjA0bhxgryJ2Ts4GJMDA-tPzVWEncv4pb" target="_blank" rel="noopener" title="Nautobot Videos" class="md-social__link">
|
|
8678
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Free 6.
|
|
8678
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z"/></svg>
|
|
8679
8679
|
</a>
|
|
8680
8680
|
|
|
8681
8681
|
|
|
@@ -8683,7 +8683,7 @@
|
|
|
8683
8683
|
|
|
8684
8684
|
|
|
8685
8685
|
<a href="https://www.networktocode.com/community/" target="_blank" rel="noopener" title="Network to Code Community" class="md-social__link">
|
|
8686
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.
|
|
8686
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M94.12 315.1c0 25.9-21.16 47.06-47.06 47.06S0 341 0 315.1c0-25.9 21.16-47.06 47.06-47.06h47.06v47.06zm23.72 0c0-25.9 21.16-47.06 47.06-47.06s47.06 21.16 47.06 47.06v117.84c0 25.9-21.16 47.06-47.06 47.06s-47.06-21.16-47.06-47.06V315.1zm47.06-188.98c-25.9 0-47.06-21.16-47.06-47.06S139 32 164.9 32s47.06 21.16 47.06 47.06v47.06H164.9zm0 23.72c25.9 0 47.06 21.16 47.06 47.06s-21.16 47.06-47.06 47.06H47.06C21.16 243.96 0 222.8 0 196.9s21.16-47.06 47.06-47.06H164.9zm188.98 47.06c0-25.9 21.16-47.06 47.06-47.06 25.9 0 47.06 21.16 47.06 47.06s-21.16 47.06-47.06 47.06h-47.06V196.9zm-23.72 0c0 25.9-21.16 47.06-47.06 47.06-25.9 0-47.06-21.16-47.06-47.06V79.06c0-25.9 21.16-47.06 47.06-47.06 25.9 0 47.06 21.16 47.06 47.06V196.9zM283.1 385.88c25.9 0 47.06 21.16 47.06 47.06 0 25.9-21.16 47.06-47.06 47.06-25.9 0-47.06-21.16-47.06-47.06v-47.06h47.06zm0-23.72c-25.9 0-47.06-21.16-47.06-47.06 0-25.9 21.16-47.06 47.06-47.06h117.84c25.9 0 47.06 21.16 47.06 47.06 0 25.9-21.16 47.06-47.06 47.06H283.1z"/></svg>
|
|
8687
8687
|
</a>
|
|
8688
8688
|
|
|
8689
8689
|
|
|
@@ -8691,7 +8691,7 @@
|
|
|
8691
8691
|
|
|
8692
8692
|
|
|
8693
8693
|
<a href="https://github.com/nautobot/nautobot" target="_blank" rel="noopener" title="GitHub Repo" class="md-social__link">
|
|
8694
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.
|
|
8694
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
|
|
8695
8695
|
</a>
|
|
8696
8696
|
|
|
8697
8697
|
|
|
@@ -8699,7 +8699,7 @@
|
|
|
8699
8699
|
|
|
8700
8700
|
|
|
8701
8701
|
<a href="https://twitter.com/networktocode" target="_blank" rel="noopener" title="Network to Code Twitter" class="md-social__link">
|
|
8702
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.
|
|
8702
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>
|
|
8703
8703
|
</a>
|
|
8704
8704
|
|
|
8705
8705
|
</div>
|