nautobot 2.2.8__py3-none-any.whl → 2.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of nautobot might be problematic. Click here for more details.
- nautobot/apps/forms.py +4 -0
- nautobot/apps/models.py +10 -1
- nautobot/circuits/__init__.py +0 -1
- nautobot/circuits/apps.py +1 -0
- nautobot/circuits/factory.py +15 -3
- nautobot/circuits/filters.py +13 -0
- nautobot/circuits/forms.py +13 -0
- nautobot/circuits/migrations/0021_alter_circuit_status_alter_circuittermination__path.py +32 -0
- nautobot/circuits/migrations/0022_circuittermination_cloud_network.py +25 -0
- nautobot/circuits/models.py +16 -3
- nautobot/circuits/tables.py +16 -2
- nautobot/circuits/templates/circuits/circuittermination_create.html +10 -2
- nautobot/circuits/templates/circuits/circuittermination_retrieve.html +6 -0
- nautobot/circuits/templates/circuits/inc/circuit_termination.html +6 -1
- nautobot/circuits/tests/test_api.py +7 -5
- nautobot/circuits/tests/test_filters.py +12 -5
- nautobot/circuits/tests/test_models.py +33 -2
- nautobot/circuits/views.py +2 -3
- nautobot/cloud/__init__.py +0 -0
- nautobot/cloud/api/__init__.py +0 -0
- nautobot/cloud/api/serializers.py +54 -0
- nautobot/cloud/api/urls.py +16 -0
- nautobot/cloud/api/views.py +48 -0
- nautobot/cloud/apps.py +13 -0
- nautobot/cloud/factory.py +113 -0
- nautobot/cloud/filters.py +187 -0
- nautobot/cloud/forms.py +339 -0
- nautobot/cloud/homepage.py +43 -0
- nautobot/cloud/migrations/0001_initial.py +304 -0
- nautobot/cloud/migrations/__init__.py +0 -0
- nautobot/cloud/models.py +246 -0
- nautobot/cloud/navigation.py +85 -0
- nautobot/cloud/tables.py +157 -0
- nautobot/cloud/templates/cloud/cloudaccount_retrieve.html +43 -0
- nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +122 -0
- nautobot/cloud/templates/cloud/cloudnetwork_update.html +33 -0
- nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +111 -0
- nautobot/cloud/templates/cloud/cloudservice_retrieve.html +69 -0
- nautobot/cloud/templates/cloud/cloudservice_update.html +25 -0
- nautobot/cloud/tests/__init__.py +0 -0
- nautobot/cloud/tests/test_api.py +248 -0
- nautobot/cloud/tests/test_filters.py +125 -0
- nautobot/cloud/tests/test_models.py +43 -0
- nautobot/cloud/tests/test_views.py +153 -0
- nautobot/cloud/urls.py +14 -0
- nautobot/cloud/views.py +181 -0
- nautobot/core/__init__.py +0 -3
- nautobot/core/api/metadata.py +1 -0
- nautobot/core/api/parsers.py +7 -1
- nautobot/core/api/urls.py +1 -0
- nautobot/core/api/utils.py +1 -0
- nautobot/core/api/views.py +4 -0
- nautobot/core/apps/__init__.py +6 -3
- nautobot/core/constants.py +8 -0
- nautobot/core/factory.py +32 -1
- nautobot/core/filters.py +110 -14
- nautobot/core/forms/fields.py +10 -4
- nautobot/core/forms/forms.py +11 -3
- nautobot/core/forms/widgets.py +18 -1
- nautobot/core/graphql/generators.py +2 -2
- nautobot/core/graphql/schema.py +28 -7
- nautobot/core/jobs/__init__.py +20 -3
- nautobot/core/jobs/cleanup.py +100 -0
- nautobot/core/jobs/groups.py +38 -0
- nautobot/core/management/commands/generate_test_data.py +116 -3
- nautobot/core/models/__init__.py +34 -9
- nautobot/core/models/generics.py +19 -3
- nautobot/core/models/name_color_content_types.py +7 -28
- nautobot/core/models/querysets.py +4 -3
- nautobot/core/models/tree_queries.py +1 -1
- nautobot/core/models/utils.py +21 -5
- nautobot/core/settings.py +15 -19
- nautobot/core/settings.yaml +48 -13
- nautobot/core/settings_funcs.py +103 -0
- nautobot/core/tables.py +130 -56
- nautobot/core/templates/admin/search_form.html +1 -1
- nautobot/core/templates/buttons/add.html +11 -3
- nautobot/core/templates/buttons/consolidated_bulk_action_buttons.html +13 -0
- nautobot/core/templates/buttons/consolidated_detail_view_action_buttons.html +13 -0
- nautobot/core/templates/buttons/export.html +101 -53
- nautobot/core/templates/buttons/job_import.html +11 -3
- nautobot/core/templates/generic/object_bulk_destroy.html +3 -1
- nautobot/core/templates/generic/object_bulk_update.html +3 -1
- nautobot/core/templates/generic/object_changelog.html +0 -9
- nautobot/core/templates/generic/object_list.html +156 -17
- nautobot/core/templates/generic/object_retrieve.html +80 -16
- nautobot/core/templates/inc/extras_features_edit_form_fields.html +8 -0
- nautobot/core/templates/inc/javascript.html +2 -0
- nautobot/core/templates/inc/media.html +2 -2
- nautobot/core/templates/inc/nav_menu.html +1 -0
- nautobot/core/templates/inc/paginator.html +7 -7
- nautobot/core/templates/inc/search_panel.html +2 -2
- nautobot/core/templates/inc/table.html +2 -2
- nautobot/core/templates/nautobot_config.py.j2 +28 -8
- nautobot/core/templates/utilities/templatetags/dynamic_group_assignment_modal.html +37 -0
- nautobot/core/templates/utilities/templatetags/filter_form_modal.html +2 -2
- nautobot/core/templates/utilities/templatetags/saved_view_modal.html +38 -0
- nautobot/core/templates/utilities/theme_preview.html +25 -8
- nautobot/core/templates/utilities/worker_status.html +152 -0
- nautobot/core/templatetags/buttons.py +335 -38
- nautobot/core/templatetags/form_helpers.py +1 -1
- nautobot/core/templatetags/helpers.py +181 -11
- nautobot/core/testing/api.py +5 -4
- nautobot/core/testing/filters.py +63 -14
- nautobot/core/testing/mixins.py +46 -0
- nautobot/core/testing/models.py +22 -0
- nautobot/core/testing/schema.py +4 -8
- nautobot/core/testing/views.py +31 -14
- nautobot/core/tests/integration/test_general_functionality.py +1 -1
- nautobot/core/tests/integration/test_import_objects_ui.py +1 -0
- nautobot/core/tests/integration/test_swagger.py +1 -1
- nautobot/core/tests/nautobot_config.py +0 -1
- nautobot/core/tests/runner.py +2 -2
- nautobot/core/tests/test_api.py +1 -0
- nautobot/core/tests/test_authentication.py +7 -2
- nautobot/core/tests/test_filters.py +11 -9
- nautobot/core/tests/test_forms.py +9 -0
- nautobot/core/tests/test_graphql.py +27 -16
- nautobot/core/tests/test_jobs.py +204 -2
- nautobot/core/tests/test_tables.py +3 -1
- nautobot/core/tests/test_templatetags_helpers.py +12 -5
- nautobot/core/tests/test_templatetags_netutils.py +3 -3
- nautobot/core/tests/test_utils.py +31 -20
- nautobot/core/tests/test_views.py +6 -6
- nautobot/core/urls.py +8 -3
- nautobot/core/utils/deprecation.py +29 -0
- nautobot/core/utils/filtering.py +12 -9
- nautobot/core/utils/lookup.py +37 -2
- nautobot/core/utils/requests.py +4 -1
- nautobot/core/views/__init__.py +137 -24
- nautobot/core/views/generic.py +119 -67
- nautobot/core/views/mixins.py +105 -36
- nautobot/core/views/paginator.py +9 -3
- nautobot/core/views/renderers.py +121 -56
- nautobot/core/views/utils.py +81 -1
- nautobot/dcim/__init__.py +0 -1
- nautobot/dcim/api/serializers.py +180 -44
- nautobot/dcim/api/urls.py +7 -3
- nautobot/dcim/api/views.py +53 -7
- nautobot/dcim/apps.py +3 -0
- nautobot/dcim/choices.py +25 -0
- nautobot/dcim/constants.py +7 -0
- nautobot/dcim/factory.py +252 -18
- nautobot/dcim/filters/__init__.py +373 -193
- nautobot/dcim/filters/mixins.py +274 -1
- nautobot/dcim/forms.py +834 -121
- nautobot/dcim/graphql/types.py +2 -2
- nautobot/dcim/homepage.py +1 -1
- nautobot/dcim/migrations/0059_add_role_field_to_interface_models.py +27 -0
- nautobot/dcim/migrations/0060_alter_cable_status_alter_consoleport__path_and_more.py +303 -0
- nautobot/dcim/migrations/0061_module_models.py +862 -0
- nautobot/dcim/migrations/0062_module_data_migration.py +25 -0
- nautobot/dcim/models/__init__.py +8 -0
- nautobot/dcim/models/cables.py +15 -0
- nautobot/dcim/models/device_component_templates.py +207 -53
- nautobot/dcim/models/device_components.py +282 -99
- nautobot/dcim/models/devices.py +472 -13
- nautobot/dcim/models/racks.py +0 -1
- nautobot/dcim/navigation.py +47 -0
- nautobot/dcim/signals.py +3 -3
- nautobot/dcim/tables/__init__.py +35 -23
- nautobot/dcim/tables/devices.py +248 -47
- nautobot/dcim/tables/devicetypes.py +65 -9
- nautobot/dcim/tables/racks.py +5 -1
- nautobot/dcim/tables/template_code.py +46 -26
- nautobot/dcim/templates/dcim/cable_connect.html +76 -3
- nautobot/dcim/templates/dcim/console_port_connection_list.html +7 -5
- nautobot/dcim/templates/dcim/device/base.html +14 -6
- nautobot/dcim/templates/dcim/device/consoleports.html +2 -3
- nautobot/dcim/templates/dcim/device/consoleserverports.html +2 -3
- nautobot/dcim/templates/dcim/device/devicebays.html +6 -7
- nautobot/dcim/templates/dcim/device/frontports.html +2 -3
- nautobot/dcim/templates/dcim/device/interfaces.html +2 -3
- nautobot/dcim/templates/dcim/device/inventory.html +2 -3
- nautobot/dcim/templates/dcim/device/modulebays.html +49 -0
- nautobot/dcim/templates/dcim/device/poweroutlets.html +2 -3
- nautobot/dcim/templates/dcim/device/powerports.html +2 -3
- nautobot/dcim/templates/dcim/device/rearports.html +2 -3
- nautobot/dcim/templates/dcim/device.html +45 -1
- nautobot/dcim/templates/dcim/device_component.html +13 -5
- nautobot/dcim/templates/dcim/device_list.html +2 -1
- nautobot/dcim/templates/dcim/deviceredundancygroup_retrieve.html +6 -0
- nautobot/dcim/templates/dcim/devicetype.html +99 -98
- nautobot/dcim/templates/dcim/devicetype_list.html +8 -16
- nautobot/dcim/templates/dcim/inc/devicetype_component_table.html +1 -1
- nautobot/dcim/templates/dcim/inc/moduletype_component_table.html +39 -0
- nautobot/dcim/templates/dcim/interface.html +17 -2
- nautobot/dcim/templates/dcim/interface_connection_list.html +7 -5
- nautobot/dcim/templates/dcim/interface_edit.html +1 -0
- nautobot/dcim/templates/dcim/manufacturer.html +24 -0
- nautobot/dcim/templates/dcim/module/base.html +97 -0
- nautobot/dcim/templates/dcim/module_bulk_destroy.html +5 -0
- nautobot/dcim/templates/dcim/module_consoleports.html +53 -0
- nautobot/dcim/templates/dcim/module_consoleserverports.html +53 -0
- nautobot/dcim/templates/dcim/module_destroy.html +5 -0
- nautobot/dcim/templates/dcim/module_frontports.html +53 -0
- nautobot/dcim/templates/dcim/module_interfaces.html +57 -0
- nautobot/dcim/templates/dcim/module_list.html +20 -0
- nautobot/dcim/templates/dcim/module_modulebays.html +49 -0
- nautobot/dcim/templates/dcim/module_poweroutlets.html +53 -0
- nautobot/dcim/templates/dcim/module_powerports.html +53 -0
- nautobot/dcim/templates/dcim/module_rearports.html +53 -0
- nautobot/dcim/templates/dcim/module_retrieve.html +63 -0
- nautobot/dcim/templates/dcim/module_update.html +71 -0
- nautobot/dcim/templates/dcim/modulebay_bulk_destroy.html +5 -0
- nautobot/dcim/templates/dcim/modulebay_destroy.html +8 -0
- nautobot/dcim/templates/dcim/modulebay_retrieve.html +101 -0
- nautobot/dcim/templates/dcim/moduletype_list.html +11 -0
- nautobot/dcim/templates/dcim/moduletype_retrieve.html +159 -0
- nautobot/dcim/templates/dcim/power_port_connection_list.html +7 -5
- nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +65 -19
- nautobot/dcim/tests/integration/test_cable_connect_form.py +4 -4
- nautobot/dcim/tests/test_api.py +693 -208
- nautobot/dcim/tests/test_filters.py +843 -217
- nautobot/dcim/tests/test_models.py +1103 -8
- nautobot/dcim/tests/test_views.py +1525 -343
- nautobot/dcim/urls.py +17 -2
- nautobot/dcim/utils.py +2 -3
- nautobot/dcim/views.py +1109 -113
- nautobot/extras/__init__.py +0 -1
- nautobot/extras/api/serializers.py +115 -3
- nautobot/extras/api/urls.py +12 -0
- nautobot/extras/api/views.py +73 -59
- nautobot/extras/apps.py +2 -2
- nautobot/extras/choices.py +43 -0
- nautobot/extras/context_managers.py +13 -8
- nautobot/extras/datasources/git.py +2 -0
- nautobot/extras/factory.py +460 -9
- nautobot/extras/filters/__init__.py +174 -3
- nautobot/extras/filters/mixins.py +46 -43
- nautobot/extras/forms/base.py +24 -5
- nautobot/extras/forms/forms.py +227 -8
- nautobot/extras/forms/mixins.py +93 -0
- nautobot/extras/graphql/types.py +23 -10
- nautobot/extras/homepage.py +26 -3
- nautobot/extras/jobs.py +2 -2
- nautobot/extras/management/__init__.py +1 -0
- nautobot/extras/management/commands/refresh_dynamic_group_member_caches.py +1 -16
- nautobot/extras/migrations/0021_customfield_changelog_data.py +1 -0
- nautobot/extras/migrations/0109_dynamicgroup_group_type_dynamicgroup_tags_and_more.py +108 -0
- nautobot/extras/migrations/0110_alter_configcontext_cluster_groups_and_more.py +111 -0
- nautobot/extras/migrations/0111_metadata.py +162 -0
- nautobot/extras/migrations/0112_dynamic_group_group_type_data_migration.py +28 -0
- nautobot/extras/migrations/0113_saved_views.py +77 -0
- nautobot/extras/models/__init__.py +15 -1
- nautobot/extras/models/change_logging.py +3 -3
- nautobot/extras/models/contacts.py +4 -0
- nautobot/extras/models/customfields.py +18 -3
- nautobot/extras/models/groups.py +389 -225
- nautobot/extras/models/jobs.py +87 -3
- nautobot/extras/models/metadata.py +441 -0
- nautobot/extras/models/mixins.py +72 -62
- nautobot/extras/models/models.py +118 -9
- nautobot/extras/models/relationships.py +9 -2
- nautobot/extras/models/tags.py +13 -2
- nautobot/extras/navigation.py +57 -0
- nautobot/extras/plugins/__init__.py +3 -1
- nautobot/extras/querysets.py +30 -66
- nautobot/extras/signals.py +109 -101
- nautobot/extras/tables.py +201 -17
- nautobot/extras/templates/extras/dynamicgroup.html +44 -15
- nautobot/extras/templates/extras/dynamicgroup_edit.html +2 -0
- nautobot/extras/templates/extras/job.html +1 -1
- nautobot/extras/templates/extras/job_detail.html +11 -0
- nautobot/extras/templates/extras/jobresult.html +61 -74
- nautobot/extras/templates/extras/metadatatype_create.html +89 -0
- nautobot/extras/templates/extras/metadatatype_retrieve.html +67 -0
- nautobot/extras/templates/extras/object_dynamicgroups.html +7 -0
- nautobot/extras/templates/extras/objectchange_list.html +0 -12
- nautobot/extras/templates/extras/plugins_list.html +1 -3
- nautobot/extras/templates/extras/role_retrieve.html +48 -0
- nautobot/extras/templates/extras/staticgroupassociation_retrieve.html +20 -0
- nautobot/extras/tests/integration/test_customfields.py +1 -0
- nautobot/extras/tests/test_api.py +509 -23
- nautobot/extras/tests/test_changelog.py +20 -9
- nautobot/extras/tests/test_context_managers.py +22 -15
- nautobot/extras/tests/test_datasources.py +13 -1
- nautobot/extras/tests/test_dynamicgroups.py +201 -171
- nautobot/extras/tests/test_filters.py +211 -12
- nautobot/extras/tests/test_jobs.py +6 -6
- nautobot/extras/tests/test_models.py +501 -4
- nautobot/extras/tests/test_relationships.py +1 -0
- nautobot/extras/tests/test_views.py +586 -8
- nautobot/extras/tests/test_webhooks.py +1 -1
- nautobot/extras/urls.py +5 -0
- nautobot/extras/utils.py +85 -16
- nautobot/extras/views.py +562 -122
- nautobot/ipam/__init__.py +0 -1
- nautobot/ipam/apps.py +1 -0
- nautobot/ipam/factory.py +17 -19
- nautobot/ipam/filters.py +13 -0
- nautobot/ipam/forms.py +8 -4
- nautobot/ipam/graphql/types.py +2 -2
- nautobot/ipam/migrations/0047_alter_ipaddress_role_alter_ipaddress_status_and_more.py +59 -0
- nautobot/ipam/models.py +20 -20
- nautobot/ipam/querysets.py +1 -1
- nautobot/ipam/signals.py +4 -2
- nautobot/ipam/tables.py +5 -0
- nautobot/ipam/templates/ipam/ipaddress_interfaces.html +1 -1
- nautobot/ipam/templates/ipam/ipaddress_vm_interfaces.html +1 -1
- nautobot/ipam/templates/ipam/prefix.html +1 -0
- nautobot/ipam/tests/test_api.py +37 -18
- nautobot/ipam/tests/test_filters.py +26 -2
- nautobot/ipam/tests/test_models.py +9 -2
- nautobot/ipam/tests/test_querysets.py +1 -1
- nautobot/ipam/tests/test_views.py +3 -2
- nautobot/ipam/urls.py +2 -2
- nautobot/ipam/views.py +20 -34
- nautobot/project-static/css/base.css +21 -0
- nautobot/project-static/css/dark.css +11 -0
- nautobot/project-static/docs/404.html +894 -90
- nautobot/project-static/docs/apps/index.html +894 -90
- nautobot/project-static/docs/apps/nautobot-apps.html +894 -90
- nautobot/project-static/docs/assets/_mkdocstrings.css +5 -0
- 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 +921 -122
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +906 -103
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +1620 -905
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +937 -146
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +979 -190
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +903 -101
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +899 -95
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +993 -195
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +976 -133
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +1080 -274
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +1244 -336
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +1729 -877
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +1166 -383
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +2090 -1376
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +2248 -1424
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +914 -113
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +965 -165
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +1012 -225
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +1915 -1279
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +1848 -1104
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +906 -103
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +2335 -1701
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +1804 -1026
- nautobot/project-static/docs/development/apps/api/configuration-view.html +894 -90
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +894 -90
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +894 -90
- nautobot/project-static/docs/development/apps/api/models/global-search.html +894 -90
- nautobot/project-static/docs/development/apps/api/models/graphql.html +894 -90
- nautobot/project-static/docs/development/apps/api/models/index.html +944 -92
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +894 -90
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +894 -90
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +894 -90
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +894 -90
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +894 -90
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +894 -90
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +894 -90
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +894 -90
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +894 -90
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +894 -90
- nautobot/project-static/docs/development/apps/api/prometheus.html +894 -90
- nautobot/project-static/docs/development/apps/api/setup.html +894 -90
- nautobot/project-static/docs/development/apps/api/testing.html +894 -90
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +894 -90
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +894 -90
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +894 -90
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +894 -90
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/base-template.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/index.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/notes.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/urls.html +894 -90
- nautobot/project-static/docs/development/apps/index.html +894 -90
- nautobot/project-static/docs/development/apps/migration/code-updates.html +894 -90
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +894 -90
- nautobot/project-static/docs/development/apps/migration/from-v1.html +894 -90
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +894 -90
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +894 -90
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +894 -90
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +894 -90
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +894 -90
- nautobot/project-static/docs/development/core/application-registry.html +894 -90
- nautobot/project-static/docs/development/core/best-practices.html +895 -90
- nautobot/project-static/docs/development/core/bootstrap-ui.html +894 -90
- nautobot/project-static/docs/development/core/caching.html +894 -90
- nautobot/project-static/docs/development/core/controllers.html +894 -90
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +894 -90
- nautobot/project-static/docs/development/core/generic-views.html +894 -90
- nautobot/project-static/docs/development/core/getting-started.html +894 -90
- nautobot/project-static/docs/development/core/homepage.html +894 -90
- nautobot/project-static/docs/development/core/index.html +905 -90
- nautobot/project-static/docs/development/core/model-checklist.html +903 -91
- nautobot/project-static/docs/development/core/model-features.html +894 -90
- nautobot/project-static/docs/development/core/natural-keys.html +894 -90
- nautobot/project-static/docs/development/core/navigation-menu.html +894 -90
- nautobot/project-static/docs/development/core/release-checklist.html +897 -93
- nautobot/project-static/docs/development/core/role-internals.html +894 -90
- nautobot/project-static/docs/development/core/settings.html +894 -90
- nautobot/project-static/docs/development/core/style-guide.html +895 -91
- nautobot/project-static/docs/development/core/templates.html +906 -91
- nautobot/project-static/docs/development/core/testing.html +894 -90
- nautobot/project-static/docs/development/core/user-preferences.html +894 -90
- nautobot/project-static/docs/development/index.html +894 -90
- nautobot/project-static/docs/development/jobs/index.html +1271 -453
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +894 -90
- nautobot/project-static/docs/index.html +9032 -13
- nautobot/project-static/docs/media/models/cloud_aws_direct_connect_dark.png +0 -0
- nautobot/project-static/docs/media/models/cloud_aws_direct_connect_light.png +0 -0
- nautobot/project-static/docs/models/cloud/cloudaccount.html +15 -0
- nautobot/project-static/docs/models/cloud/cloudnetwork.html +15 -0
- nautobot/project-static/docs/models/cloud/cloudnetworkprefixassignment.html +15 -0
- nautobot/project-static/docs/models/cloud/cloudresourcetype.html +15 -0
- nautobot/project-static/docs/models/cloud/cloudservice.html +15 -0
- nautobot/project-static/docs/models/cloud/cloudservicenetworkassignment.html +15 -0
- nautobot/project-static/docs/models/dcim/module.html +15 -0
- nautobot/project-static/docs/models/dcim/modulebay.html +15 -0
- nautobot/project-static/docs/models/dcim/modulebaytemplate.html +15 -0
- nautobot/project-static/docs/models/dcim/moduletype.html +15 -0
- nautobot/project-static/docs/models/extras/metadatachoice.html +15 -0
- nautobot/project-static/docs/models/extras/metadatatype.html +15 -0
- nautobot/project-static/docs/models/extras/objectmetadata.html +15 -0
- nautobot/project-static/docs/models/extras/role.html +15 -0
- nautobot/project-static/docs/models/extras/savedview.html +15 -0
- nautobot/project-static/docs/models/extras/staticgroupassociation.html +15 -0
- nautobot/project-static/docs/models/extras/status.html +15 -0
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +902 -91
- nautobot/project-static/docs/overview/design_philosophy.html +896 -92
- nautobot/project-static/docs/overview/index.html +13 -8228
- nautobot/project-static/docs/release-notes/index.html +1131 -94
- nautobot/project-static/docs/release-notes/version-1.0.html +894 -90
- nautobot/project-static/docs/release-notes/version-1.1.html +894 -90
- nautobot/project-static/docs/release-notes/version-1.2.html +894 -90
- nautobot/project-static/docs/release-notes/version-1.3.html +894 -90
- nautobot/project-static/docs/release-notes/version-1.4.html +894 -90
- nautobot/project-static/docs/release-notes/version-1.5.html +895 -91
- nautobot/project-static/docs/release-notes/version-1.6.html +895 -91
- nautobot/project-static/docs/release-notes/version-2.0.html +894 -90
- nautobot/project-static/docs/release-notes/version-2.1.html +894 -90
- nautobot/project-static/docs/release-notes/version-2.2.html +1137 -196
- nautobot/project-static/docs/release-notes/version-2.3.html +9954 -0
- nautobot/project-static/docs/requirements.txt +5 -5
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +335 -260
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +894 -90
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +894 -90
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +894 -90
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +894 -90
- nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +1025 -175
- nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +894 -90
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +894 -90
- nautobot/project-static/docs/user-guide/administration/guides/caching.html +894 -90
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +902 -90
- nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +894 -90
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +894 -90
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +894 -90
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +894 -90
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +894 -90
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +894 -90
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +894 -90
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +894 -90
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +946 -155
- nautobot/project-static/docs/user-guide/administration/installation/index.html +903 -95
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +936 -124
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +956 -159
- nautobot/project-static/docs/user-guide/administration/installation/services.html +915 -114
- nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +910 -101
- nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +894 -90
- nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +894 -90
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +894 -90
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +894 -90
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +977 -121
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +894 -90
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +894 -90
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +894 -90
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +894 -90
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +894 -90
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +894 -90
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +894 -90
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +894 -90
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +894 -90
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +895 -91
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +898 -90
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +897 -93
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +8984 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +8828 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +8829 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +8828 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +8829 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +8833 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +8828 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +925 -107
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +925 -107
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +920 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +925 -107
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +915 -107
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +922 -118
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +923 -119
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +920 -116
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +916 -107
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +928 -110
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +938 -120
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +930 -108
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +939 -121
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +930 -112
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +920 -116
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +923 -119
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +925 -117
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +8828 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +8846 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +8843 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +8823 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +918 -114
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +942 -85
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +926 -108
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +945 -88
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +923 -105
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +931 -127
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +920 -116
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +924 -106
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +926 -108
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +938 -90
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +899 -91
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +899 -91
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +903 -98
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +899 -91
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/clear-view-button.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/cleared-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/config-table-columns-to-locations.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/configure-button.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/create-saved-view-success.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/current-saved-view-drop-down-menu.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/default-location-list-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/dropdown-button-after-new-saved-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/filter-application-to-locations.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/filter-button.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/global-default-location-list-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/location-list-view-with-saved-views.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/navigation-menu.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/save-as-new-view-drop-down.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/save-view-modal.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-buttons.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-success.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-view-unchecked.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-different-user.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-modal-unchecked.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/set-as-my-default-button.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/set-as-my-default-success.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/unsaved-saved-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/updated-saved-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +894 -90
- nautobot/project-static/docs/user-guide/index.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +1260 -787
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +897 -93
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +898 -90
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +897 -93
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +9061 -0
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +897 -93
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +897 -93
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +9137 -0
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +897 -93
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +8933 -0
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +952 -123
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +894 -90
- nautobot/project-static/js/forms.js +71 -0
- nautobot/project-static/js/table_sorting_indicator.js +46 -0
- nautobot/project-static/js/tableconfig.js +6 -1
- nautobot/project-static/materialdesignicons-7.4.47/css/materialdesignicons.min.css +3 -0
- nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/fonts/materialdesignicons-webfont.eot +0 -0
- nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/fonts/materialdesignicons-webfont.ttf +0 -0
- nautobot/project-static/materialdesignicons-7.4.47/fonts/materialdesignicons-webfont.woff +0 -0
- nautobot/project-static/materialdesignicons-7.4.47/fonts/materialdesignicons-webfont.woff2 +0 -0
- nautobot/tenancy/__init__.py +0 -1
- nautobot/tenancy/apps.py +1 -0
- nautobot/tenancy/factory.py +3 -2
- nautobot/tenancy/filters/__init__.py +1 -0
- nautobot/tenancy/forms.py +1 -1
- nautobot/tenancy/templates/tenancy/tenant.html +24 -20
- nautobot/tenancy/views.py +11 -10
- nautobot/users/__init__.py +0 -1
- nautobot/users/api/serializers.py +1 -1
- nautobot/users/api/views.py +4 -2
- nautobot/users/apps.py +3 -2
- nautobot/users/factory.py +3 -3
- nautobot/users/migrations/0010_user_default_saved_views.py +20 -0
- nautobot/users/models.py +12 -0
- nautobot/users/tests/test_filters.py +6 -3
- nautobot/users/urls.py +8 -0
- nautobot/virtualization/__init__.py +0 -1
- nautobot/virtualization/apps.py +1 -0
- nautobot/virtualization/filters.py +6 -1
- nautobot/virtualization/forms.py +11 -3
- nautobot/virtualization/graphql/types.py +2 -2
- nautobot/virtualization/migrations/0029_add_role_field_to_interface_models.py +27 -0
- nautobot/virtualization/migrations/0030_alter_virtualmachine_local_config_context_data_owner_content_type_and_more.py +67 -0
- nautobot/virtualization/models.py +0 -2
- nautobot/virtualization/tables.py +12 -8
- nautobot/virtualization/templates/virtualization/virtualmachine.html +1 -1
- nautobot/virtualization/templates/virtualization/vminterface.html +7 -1
- nautobot/virtualization/templates/virtualization/vminterface_edit.html +1 -0
- nautobot/virtualization/tests/test_api.py +9 -4
- nautobot/virtualization/tests/test_filters.py +22 -0
- nautobot/virtualization/tests/test_models.py +7 -3
- nautobot/virtualization/tests/test_views.py +19 -3
- nautobot/virtualization/urls.py +2 -2
- nautobot/virtualization/views.py +10 -32
- {nautobot-2.2.8.dist-info → nautobot-2.3.0.dist-info}/METADATA +21 -19
- {nautobot-2.2.8.dist-info → nautobot-2.3.0.dist-info}/RECORD +684 -564
- 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/project-static/materialdesignicons-6.5.95/.github/ISSUE_TEMPLATE.md +0 -3
- nautobot/project-static/materialdesignicons-6.5.95/README.md +0 -25
- nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.css +0 -26654
- nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.css.map +0 -16
- nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.min.css +0 -3
- nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.min.css.map +0 -16
- nautobot/project-static/materialdesignicons-6.5.95/fonts/materialdesignicons-webfont.woff +0 -0
- nautobot/project-static/materialdesignicons-6.5.95/fonts/materialdesignicons-webfont.woff2 +0 -0
- nautobot/project-static/materialdesignicons-6.5.95/package.json +0 -28
- nautobot/project-static/materialdesignicons-6.5.95/preview.html +0 -717
- nautobot/project-static/materialdesignicons-6.5.95/scss/_animated.scss +0 -27
- nautobot/project-static/materialdesignicons-6.5.95/scss/_core.scss +0 -10
- nautobot/project-static/materialdesignicons-6.5.95/scss/_extras.scss +0 -65
- nautobot/project-static/materialdesignicons-6.5.95/scss/_functions.scss +0 -20
- nautobot/project-static/materialdesignicons-6.5.95/scss/_icons.scss +0 -10
- nautobot/project-static/materialdesignicons-6.5.95/scss/_path.scss +0 -10
- nautobot/project-static/materialdesignicons-6.5.95/scss/_variables.scss +0 -6606
- nautobot/project-static/materialdesignicons-6.5.95/scss/materialdesignicons.scss +0 -8
- /nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/LICENSE +0 -0
- {nautobot-2.2.8.dist-info → nautobot-2.3.0.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.2.8.dist-info → nautobot-2.3.0.dist-info}/NOTICE +0 -0
- {nautobot-2.2.8.dist-info → nautobot-2.3.0.dist-info}/WHEEL +0 -0
- {nautobot-2.2.8.dist-info → nautobot-2.3.0.dist-info}/entry_points.txt +0 -0
nautobot/extras/querysets.py
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
from django.conf import settings
|
|
2
2
|
from django.contrib.contenttypes.models import ContentType
|
|
3
|
-
from django.core.cache import cache
|
|
4
3
|
from django.db.models import F, Model, OuterRef, Q, Subquery
|
|
5
4
|
from django.db.models.functions import JSONObject
|
|
6
5
|
|
|
7
6
|
from nautobot.core.models.query_functions import EmptyGroupByJSONBAgg
|
|
8
7
|
from nautobot.core.models.querysets import RestrictedQuerySet
|
|
9
|
-
from nautobot.core.utils.config import get_settings_or_config
|
|
10
8
|
from nautobot.extras.models.tags import TaggedItem
|
|
11
9
|
|
|
12
10
|
|
|
@@ -85,10 +83,10 @@ class ConfigContextModelQuerySet(RestrictedQuerySet):
|
|
|
85
83
|
"""
|
|
86
84
|
Attach the subquery annotation to the base queryset.
|
|
87
85
|
|
|
88
|
-
|
|
89
|
-
we include "weight" and "name" into the result so that we can
|
|
86
|
+
Note that the underlying function of our JSONBAgg in MySQL, `JSONARRAY_AGG`, does not support an `ordering`,
|
|
87
|
+
unlike PostgreSQL's implementation. This is why we include "weight" and "name" into the result so that we can
|
|
88
|
+
sort it within Python to ensure correctness.
|
|
90
89
|
|
|
91
|
-
TODO This method does not accurately reflect location inheritance because of the reasons stated in _get_config_context_filters()
|
|
92
90
|
Do not use this method by itself, use get_config_context() method directly on ConfigContextModel instead.
|
|
93
91
|
"""
|
|
94
92
|
from nautobot.extras.models import ConfigContext
|
|
@@ -96,7 +94,6 @@ class ConfigContextModelQuerySet(RestrictedQuerySet):
|
|
|
96
94
|
return self.annotate(
|
|
97
95
|
config_context_data=Subquery(
|
|
98
96
|
ConfigContext.objects.filter(self._get_config_context_filters())
|
|
99
|
-
.order_by("weight", "name")
|
|
100
97
|
.annotate(
|
|
101
98
|
_data=EmptyGroupByJSONBAgg(
|
|
102
99
|
JSONObject(
|
|
@@ -107,15 +104,13 @@ class ConfigContextModelQuerySet(RestrictedQuerySet):
|
|
|
107
104
|
)
|
|
108
105
|
)
|
|
109
106
|
.values("_data")
|
|
107
|
+
.order_by()
|
|
110
108
|
)
|
|
111
109
|
).distinct()
|
|
112
110
|
|
|
113
111
|
def _get_config_context_filters(self):
|
|
114
112
|
"""
|
|
115
113
|
This method is constructing the set of Q objects for the specific object types.
|
|
116
|
-
Note that locations filters are not included in the method because the filter needs the
|
|
117
|
-
ability to query the ancestors for a particular tree node for subquery and we lost it since
|
|
118
|
-
moving from mptt to django-tree-queries https://github.com/matthiask/django-tree-queries/issues/54.
|
|
119
114
|
"""
|
|
120
115
|
tag_query_filters = {
|
|
121
116
|
"object_id": OuterRef(OuterRef("pk")),
|
|
@@ -163,81 +158,50 @@ class ConfigContextModelQuerySet(RestrictedQuerySet):
|
|
|
163
158
|
|
|
164
159
|
|
|
165
160
|
class DynamicGroupQuerySet(RestrictedQuerySet):
|
|
166
|
-
"""Queryset for `DynamicGroup` objects that provides
|
|
161
|
+
"""Queryset for `DynamicGroup` objects that provides `get_for_object` and `get_for_model` methods."""
|
|
162
|
+
|
|
163
|
+
def get_for_model(self, model):
|
|
164
|
+
"""
|
|
165
|
+
Return all DynamicGroups assignable to the given model class.
|
|
166
|
+
"""
|
|
167
|
+
concrete_model = model._meta.concrete_model
|
|
168
|
+
content_type = ContentType.objects.get_for_model(concrete_model)
|
|
169
|
+
return self.filter(content_type=content_type)
|
|
167
170
|
|
|
168
171
|
def get_list_for_object(self, obj, use_cache=False):
|
|
169
172
|
"""
|
|
170
|
-
Return a list of `DynamicGroup` assigned to the given object.
|
|
171
|
-
which will return a queryset but that is an additional query to the DB when you may just
|
|
172
|
-
want a list.
|
|
173
|
+
Return a (cached) list of `DynamicGroup` objects assigned to the given object.
|
|
173
174
|
|
|
174
175
|
Args:
|
|
175
176
|
obj: The object to seek dynamic groups membership by.
|
|
176
|
-
use_cache:
|
|
177
|
+
use_cache: Obsolete; cache is always used. If truly necessary to get up-to-the-minute accuracy, you should
|
|
178
|
+
call `[dg.update_cached_members() for dg in DynamicGroup.objects.filter(content_type=...)]` beforehand,
|
|
179
|
+
but be aware that that's potentially quite expensive computationally.
|
|
177
180
|
"""
|
|
178
|
-
|
|
179
|
-
raise TypeError(f"{obj} is not an instance of Django Model class")
|
|
180
|
-
|
|
181
|
-
# Get dynamic groups for this content_type using the discrete content_type fields to
|
|
182
|
-
# optimize the query.
|
|
183
|
-
eligible_groups = self._get_eligible_dynamic_groups(obj, use_cache=use_cache)
|
|
184
|
-
|
|
185
|
-
# Filter down to matching groups.
|
|
186
|
-
my_groups = []
|
|
187
|
-
for dynamic_group in list(eligible_groups):
|
|
188
|
-
if dynamic_group.has_member(obj, use_cache=use_cache):
|
|
189
|
-
my_groups.append(dynamic_group)
|
|
190
|
-
|
|
191
|
-
return my_groups
|
|
181
|
+
return list(self.get_for_object(obj))
|
|
192
182
|
|
|
193
183
|
def get_for_object(self, obj, use_cache=False):
|
|
194
184
|
"""
|
|
195
|
-
Return a queryset of `DynamicGroup` objects that are assigned to the given object.
|
|
185
|
+
Return a (cached) queryset of `DynamicGroup` objects that are assigned to the given object.
|
|
196
186
|
|
|
197
187
|
Args:
|
|
198
188
|
obj: The object to seek dynamic groups membership by.
|
|
199
|
-
use_cache:
|
|
189
|
+
use_cache: Obsolete; cache is always used. If truly necessary to get up-to-the-minute accuracy, you should
|
|
190
|
+
call `[dg.update_cached_members() for dg in DynamicGroup.objects.filter(content_type=...)]` beforehand,
|
|
191
|
+
but be aware that's potentially quite expensive computationally.
|
|
200
192
|
"""
|
|
201
|
-
|
|
193
|
+
if not isinstance(obj, Model):
|
|
194
|
+
raise TypeError(f"{obj} is not an instance of Django Model class")
|
|
195
|
+
|
|
196
|
+
return self.filter(
|
|
197
|
+
content_type__app_label=obj._meta.app_label,
|
|
198
|
+
content_type__model=obj._meta.model_name,
|
|
199
|
+
static_group_associations__associated_object_id=obj.id,
|
|
200
|
+
)
|
|
202
201
|
|
|
203
202
|
def get_by_natural_key(self, slug):
|
|
204
203
|
return self.get(slug=slug)
|
|
205
204
|
|
|
206
|
-
@classmethod
|
|
207
|
-
def _get_eligible_dynamic_groups_cache_key(cls, obj):
|
|
208
|
-
"""
|
|
209
|
-
Return the cache key for the queryset of `DynamicGroup` objects that are eligible to potentially contain the
|
|
210
|
-
given object.
|
|
211
|
-
"""
|
|
212
|
-
return f"nautobot.{obj._meta.label_lower}._get_eligible_dynamic_groups"
|
|
213
|
-
|
|
214
|
-
def _get_eligible_dynamic_groups(self, obj, use_cache=False):
|
|
215
|
-
"""
|
|
216
|
-
Return a queryset of `DynamicGroup` objects that are eligible to potentially contain the given object.
|
|
217
|
-
"""
|
|
218
|
-
cache_key = self.__class__._get_eligible_dynamic_groups_cache_key(obj)
|
|
219
|
-
|
|
220
|
-
def _query_eligible_dynamic_groups():
|
|
221
|
-
"""
|
|
222
|
-
A callable to be used as the default value for the cache of which dynamic groups are
|
|
223
|
-
eligible for a given object.
|
|
224
|
-
"""
|
|
225
|
-
# Save a DB query if we can by using the _content_type field on the model which is a cached instance of the ContentType
|
|
226
|
-
if use_cache and hasattr(type(obj), "_content_type"):
|
|
227
|
-
return self.filter(content_type_id=type(obj)._content_type.id)
|
|
228
|
-
return self.filter(
|
|
229
|
-
content_type__app_label=obj._meta.app_label, content_type__model=obj._meta.model_name
|
|
230
|
-
).select_related("content_type")
|
|
231
|
-
|
|
232
|
-
if not use_cache:
|
|
233
|
-
eligible_dynamic_groups = _query_eligible_dynamic_groups()
|
|
234
|
-
cache.set(cache_key, eligible_dynamic_groups, get_settings_or_config("DYNAMIC_GROUPS_MEMBER_CACHE_TIMEOUT"))
|
|
235
|
-
return eligible_dynamic_groups
|
|
236
|
-
|
|
237
|
-
return cache.get_or_set(
|
|
238
|
-
cache_key, _query_eligible_dynamic_groups, get_settings_or_config("DYNAMIC_GROUPS_MEMBER_CACHE_TIMEOUT")
|
|
239
|
-
)
|
|
240
|
-
|
|
241
205
|
|
|
242
206
|
class DynamicGroupMembershipQuerySet(RestrictedQuerySet):
|
|
243
207
|
"""Queryset for `DynamicGroupMembership` objects."""
|
nautobot/extras/signals.py
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import contextlib
|
|
2
2
|
import contextvars
|
|
3
|
-
from datetime import timedelta
|
|
4
3
|
import logging
|
|
5
4
|
import os
|
|
6
|
-
import secrets
|
|
7
5
|
import shutil
|
|
8
6
|
import traceback
|
|
9
7
|
|
|
@@ -15,7 +13,7 @@ from django.core.cache import cache
|
|
|
15
13
|
from django.core.exceptions import ValidationError
|
|
16
14
|
from django.core.files.storage import get_storage_class
|
|
17
15
|
from django.db import transaction
|
|
18
|
-
from django.db.models.signals import m2m_changed, post_delete, post_save, pre_delete, pre_save
|
|
16
|
+
from django.db.models.signals import m2m_changed, post_delete, post_migrate, post_save, pre_delete, pre_save
|
|
19
17
|
from django.dispatch import receiver
|
|
20
18
|
from django.utils import timezone
|
|
21
19
|
from django_prometheus.models import model_deletes, model_inserts, model_updates
|
|
@@ -23,7 +21,6 @@ import redis.exceptions
|
|
|
23
21
|
|
|
24
22
|
from nautobot.core.celery import app, import_jobs
|
|
25
23
|
from nautobot.core.models import BaseModel
|
|
26
|
-
from nautobot.core.utils.config import get_settings_or_config
|
|
27
24
|
from nautobot.core.utils.logging import sanitize
|
|
28
25
|
from nautobot.extras.choices import JobResultStatusChoices, ObjectChangeActionChoices
|
|
29
26
|
from nautobot.extras.constants import CHANGELOG_MAX_CHANGE_CONTEXT_DETAIL
|
|
@@ -35,6 +32,7 @@ from nautobot.extras.models import (
|
|
|
35
32
|
DynamicGroupMembership,
|
|
36
33
|
GitRepository,
|
|
37
34
|
JobResult,
|
|
35
|
+
MetadataType,
|
|
38
36
|
ObjectChange,
|
|
39
37
|
Relationship,
|
|
40
38
|
)
|
|
@@ -66,31 +64,47 @@ def get_user_if_authenticated(user, instance):
|
|
|
66
64
|
return None
|
|
67
65
|
|
|
68
66
|
|
|
69
|
-
@receiver(post_save)
|
|
70
|
-
@receiver(
|
|
71
|
-
@receiver(
|
|
67
|
+
@receiver(post_save, sender=ComputedField)
|
|
68
|
+
@receiver(post_save, sender=CustomField)
|
|
69
|
+
@receiver(post_save, sender=CustomField.content_types.through)
|
|
70
|
+
@receiver(post_save, sender=MetadataType)
|
|
71
|
+
@receiver(post_save, sender=MetadataType.content_types.through)
|
|
72
|
+
@receiver(m2m_changed, sender=ComputedField)
|
|
73
|
+
@receiver(m2m_changed, sender=CustomField)
|
|
74
|
+
@receiver(m2m_changed, sender=CustomField.content_types.through)
|
|
75
|
+
@receiver(m2m_changed, sender=MetadataType)
|
|
76
|
+
@receiver(m2m_changed, sender=MetadataType.content_types.through)
|
|
77
|
+
@receiver(post_delete, sender=ComputedField)
|
|
78
|
+
@receiver(post_delete, sender=CustomField)
|
|
79
|
+
@receiver(post_delete, sender=CustomField.content_types.through)
|
|
80
|
+
@receiver(post_delete, sender=MetadataType)
|
|
81
|
+
@receiver(post_delete, sender=MetadataType.content_types.through)
|
|
72
82
|
def invalidate_models_cache(sender, **kwargs):
|
|
73
|
-
"""Invalidate the related-models cache for ComputedFields
|
|
83
|
+
"""Invalidate the related-models cache for ComputedFields and CustomFields."""
|
|
74
84
|
if sender is CustomField.content_types.through:
|
|
75
85
|
manager = CustomField.objects
|
|
76
|
-
elif sender
|
|
77
|
-
manager =
|
|
86
|
+
elif sender is MetadataType.content_types.through:
|
|
87
|
+
manager = MetadataType.objects
|
|
78
88
|
else:
|
|
79
|
-
|
|
89
|
+
manager = sender.objects
|
|
90
|
+
|
|
91
|
+
with contextlib.suppress(redis.exceptions.ConnectionError):
|
|
92
|
+
# TODO: *maybe* target more narrowly, e.g. only clear the cache for specific related content-types?
|
|
93
|
+
cache.delete_pattern(f"{manager.get_for_model.cache_key_prefix}.*")
|
|
80
94
|
|
|
81
|
-
cached_methods = (
|
|
82
|
-
"get_for_model",
|
|
83
|
-
"get_for_model_source",
|
|
84
|
-
"get_for_model_destination",
|
|
85
|
-
)
|
|
86
95
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
96
|
+
@receiver(post_save, sender=Relationship)
|
|
97
|
+
@receiver(m2m_changed, sender=Relationship)
|
|
98
|
+
@receiver(post_delete, sender=Relationship)
|
|
99
|
+
def invalidate_relationship_models_cache(sender, **kwargs):
|
|
100
|
+
"""Invalidate the related-models caches for Relationships."""
|
|
101
|
+
for method in (
|
|
102
|
+
Relationship.objects.get_for_model_source,
|
|
103
|
+
Relationship.objects.get_for_model_destination,
|
|
104
|
+
):
|
|
105
|
+
with contextlib.suppress(redis.exceptions.ConnectionError):
|
|
106
|
+
# TODO: *maybe* target more narrowly, e.g. only clear the cache for specific related content-types?
|
|
107
|
+
cache.delete_pattern(f"{method.cache_key_prefix}.*")
|
|
94
108
|
|
|
95
109
|
|
|
96
110
|
@receiver(post_save)
|
|
@@ -131,7 +145,11 @@ def _handle_changed_object(sender, instance, raw=False, **kwargs):
|
|
|
131
145
|
|
|
132
146
|
# Generate a unique identifier for this change to stash in the change context
|
|
133
147
|
# This is used for deferred change logging and for looking up related changes without querying the database
|
|
134
|
-
unique_object_change_id =
|
|
148
|
+
unique_object_change_id = None
|
|
149
|
+
if user is not None:
|
|
150
|
+
unique_object_change_id = f"{changed_object_type.pk}__{changed_object_id}__{user.pk}"
|
|
151
|
+
else:
|
|
152
|
+
unique_object_change_id = f"{changed_object_type.pk}__{changed_object_id}"
|
|
135
153
|
|
|
136
154
|
# If a change already exists for this change_id, user, and object, update it instead of creating a new one.
|
|
137
155
|
# If the object was deleted then recreated with the same pk (don't do this), change the action to update.
|
|
@@ -146,12 +164,13 @@ def _handle_changed_object(sender, instance, raw=False, **kwargs):
|
|
|
146
164
|
# Skip the database check when deferring object changes
|
|
147
165
|
if not change_context.defer_object_changes and related_changes.exists():
|
|
148
166
|
objectchange = instance.to_objectchange(action)
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
most_recent_change.action
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
167
|
+
if objectchange is not None:
|
|
168
|
+
most_recent_change = related_changes.order_by("-time").first()
|
|
169
|
+
if most_recent_change.action == ObjectChangeActionChoices.ACTION_DELETE:
|
|
170
|
+
most_recent_change.action = ObjectChangeActionChoices.ACTION_UPDATE
|
|
171
|
+
most_recent_change.object_data = objectchange.object_data
|
|
172
|
+
most_recent_change.object_data_v2 = objectchange.object_data_v2
|
|
173
|
+
most_recent_change.save()
|
|
155
174
|
|
|
156
175
|
else:
|
|
157
176
|
change_context.deferred_object_changes[unique_object_change_id] = [
|
|
@@ -159,11 +178,14 @@ def _handle_changed_object(sender, instance, raw=False, **kwargs):
|
|
|
159
178
|
]
|
|
160
179
|
if not change_context.defer_object_changes:
|
|
161
180
|
objectchange = instance.to_objectchange(action)
|
|
162
|
-
objectchange
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
181
|
+
if objectchange is not None:
|
|
182
|
+
objectchange.user = user
|
|
183
|
+
objectchange.request_id = change_context.change_id
|
|
184
|
+
objectchange.change_context = change_context.context
|
|
185
|
+
objectchange.change_context_detail = change_context.context_detail[
|
|
186
|
+
:CHANGELOG_MAX_CHANGE_CONTEXT_DETAIL
|
|
187
|
+
]
|
|
188
|
+
objectchange.save()
|
|
167
189
|
|
|
168
190
|
# restore field cache
|
|
169
191
|
instance._state.fields_cache = original_cache
|
|
@@ -174,12 +196,6 @@ def _handle_changed_object(sender, instance, raw=False, **kwargs):
|
|
|
174
196
|
elif action == ObjectChangeActionChoices.ACTION_UPDATE:
|
|
175
197
|
model_updates.labels(instance._meta.model_name).inc()
|
|
176
198
|
|
|
177
|
-
# Housekeeping: 0.1% chance of clearing out expired ObjectChanges
|
|
178
|
-
changelog_retention = get_settings_or_config("CHANGELOG_RETENTION")
|
|
179
|
-
if changelog_retention and secrets.randbelow(1000) == 0:
|
|
180
|
-
cutoff = timezone.now() - timedelta(days=changelog_retention)
|
|
181
|
-
ObjectChange.objects.filter(time__lt=cutoff).delete()
|
|
182
|
-
|
|
183
199
|
|
|
184
200
|
@receiver(pre_delete)
|
|
185
201
|
def _handle_deleted_object(sender, instance, **kwargs):
|
|
@@ -236,13 +252,14 @@ def _handle_deleted_object(sender, instance, **kwargs):
|
|
|
236
252
|
# Skip the database check when deferring object changes
|
|
237
253
|
if not change_context.defer_object_changes and related_changes.exists():
|
|
238
254
|
objectchange = instance.to_objectchange(ObjectChangeActionChoices.ACTION_DELETE)
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
most_recent_change.action
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
255
|
+
if objectchange is not None:
|
|
256
|
+
most_recent_change = related_changes.order_by("-time").first()
|
|
257
|
+
if most_recent_change.action != ObjectChangeActionChoices.ACTION_CREATE:
|
|
258
|
+
most_recent_change.action = ObjectChangeActionChoices.ACTION_DELETE
|
|
259
|
+
most_recent_change.object_data = objectchange.object_data
|
|
260
|
+
most_recent_change.object_data_v2 = objectchange.object_data_v2
|
|
261
|
+
most_recent_change.save()
|
|
262
|
+
save_new_objectchange = False
|
|
246
263
|
|
|
247
264
|
if save_new_objectchange:
|
|
248
265
|
change_context.deferred_object_changes.setdefault(unique_object_change_id, []).append(
|
|
@@ -250,16 +267,20 @@ def _handle_deleted_object(sender, instance, **kwargs):
|
|
|
250
267
|
"action": ObjectChangeActionChoices.ACTION_DELETE,
|
|
251
268
|
"instance": instance,
|
|
252
269
|
"user": user,
|
|
253
|
-
"changed_object_id":
|
|
270
|
+
"changed_object_id": changed_object_id,
|
|
271
|
+
"changed_object_type": changed_object_type,
|
|
254
272
|
}
|
|
255
273
|
)
|
|
256
274
|
if not change_context.defer_object_changes:
|
|
257
275
|
objectchange = instance.to_objectchange(ObjectChangeActionChoices.ACTION_DELETE)
|
|
258
|
-
objectchange
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
276
|
+
if objectchange is not None:
|
|
277
|
+
objectchange.user = user
|
|
278
|
+
objectchange.request_id = change_context.change_id
|
|
279
|
+
objectchange.change_context = change_context.context
|
|
280
|
+
objectchange.change_context_detail = change_context.context_detail[
|
|
281
|
+
:CHANGELOG_MAX_CHANGE_CONTEXT_DETAIL
|
|
282
|
+
]
|
|
283
|
+
objectchange.save()
|
|
263
284
|
|
|
264
285
|
# restore field cache
|
|
265
286
|
instance._state.fields_cache = original_cache
|
|
@@ -268,6 +289,19 @@ def _handle_deleted_object(sender, instance, **kwargs):
|
|
|
268
289
|
model_deletes.labels(instance._meta.model_name).inc()
|
|
269
290
|
|
|
270
291
|
|
|
292
|
+
#
|
|
293
|
+
# Content types
|
|
294
|
+
#
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
@receiver(post_migrate)
|
|
298
|
+
def post_migrate_clear_content_type_caches(sender, app_config, signal, **kwargs):
|
|
299
|
+
"""Clear various content-type caches after a migration."""
|
|
300
|
+
with contextlib.suppress(redis.exceptions.ConnectionError):
|
|
301
|
+
cache.delete("nautobot.extras.utils.change_logged_models_queryset")
|
|
302
|
+
cache.delete_pattern("nautobot.extras.utils.FeatureQuery.*")
|
|
303
|
+
|
|
304
|
+
|
|
271
305
|
#
|
|
272
306
|
# Custom fields
|
|
273
307
|
#
|
|
@@ -387,60 +421,18 @@ m2m_changed.connect(dynamic_group_children_changed, sender=DynamicGroup.children
|
|
|
387
421
|
pre_save.connect(dynamic_group_membership_created, sender=DynamicGroupMembership)
|
|
388
422
|
|
|
389
423
|
|
|
390
|
-
def dynamic_group_eligible_groups_changed(sender, instance, **kwargs):
|
|
391
|
-
"""
|
|
392
|
-
When a DynamicGroup is created or deleted, refresh the cache of eligible groups for the associated ContentType.
|
|
393
|
-
|
|
394
|
-
Can't change content_type_id on an existing instance, so no need to check for that.
|
|
395
|
-
"""
|
|
396
|
-
|
|
397
|
-
if get_settings_or_config("DYNAMIC_GROUPS_MEMBER_CACHE_TIMEOUT") == 0:
|
|
398
|
-
# Caching is disabled, so there's nothing to do
|
|
399
|
-
return
|
|
400
|
-
|
|
401
|
-
if kwargs.get("created", None) is False:
|
|
402
|
-
# We do not care about updates
|
|
403
|
-
# "created" is not a kwarg for post_delete signals, so is unset or None
|
|
404
|
-
# "created" is a kwarg for post_save signals, but you cannot change content types of existing groups
|
|
405
|
-
# therefor we can ignore cache updates on DynamicGroups updates
|
|
406
|
-
return
|
|
407
|
-
|
|
408
|
-
content_type = instance.content_type
|
|
409
|
-
cache_key = f"nautobot.{content_type.app_label}.{content_type.model}._get_eligible_dynamic_groups"
|
|
410
|
-
cache.set(
|
|
411
|
-
cache_key,
|
|
412
|
-
DynamicGroup.objects.filter(content_type_id=instance.content_type_id),
|
|
413
|
-
get_settings_or_config("DYNAMIC_GROUPS_MEMBER_CACHE_TIMEOUT"),
|
|
414
|
-
)
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
post_save.connect(dynamic_group_eligible_groups_changed, sender=DynamicGroup)
|
|
418
|
-
post_delete.connect(dynamic_group_eligible_groups_changed, sender=DynamicGroup)
|
|
419
|
-
|
|
420
|
-
|
|
421
424
|
def dynamic_group_update_cached_members(sender, instance, **kwargs):
|
|
422
425
|
"""
|
|
423
|
-
When a DynamicGroup or DynamicGroupMembership is updated, update the cache of members.
|
|
426
|
+
When a DynamicGroup or DynamicGroupMembership is updated, update the cache of members for it and any parent groups.
|
|
424
427
|
"""
|
|
425
|
-
|
|
426
|
-
if get_settings_or_config("DYNAMIC_GROUPS_MEMBER_CACHE_TIMEOUT") == 0:
|
|
427
|
-
# Caching is disabled, so there's nothing to do
|
|
428
|
-
return
|
|
429
|
-
|
|
430
428
|
if isinstance(instance, DynamicGroupMembership):
|
|
431
|
-
group = instance.
|
|
429
|
+
group = instance.parent_group
|
|
432
430
|
else:
|
|
433
431
|
group = instance
|
|
434
432
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
# Since a change a group or group of groups does not affect it's children, we only need to go up the tree
|
|
439
|
-
# A group of groups does not use the cache of it's children due to the complexity of the set operations
|
|
440
|
-
for ancestor in list(this_instance.parents.all()):
|
|
441
|
-
_update_cache_and_parents(ancestor)
|
|
442
|
-
|
|
443
|
-
_update_cache_and_parents(group)
|
|
433
|
+
group.update_cached_members()
|
|
434
|
+
for ancestor in group.get_ancestors():
|
|
435
|
+
ancestor.update_cached_members()
|
|
444
436
|
|
|
445
437
|
|
|
446
438
|
post_save.connect(dynamic_group_update_cached_members, sender=DynamicGroup)
|
|
@@ -494,3 +486,19 @@ def refresh_job_models(sender, *, apps, **kwargs):
|
|
|
494
486
|
)
|
|
495
487
|
job_model.installed = False
|
|
496
488
|
job_model.save()
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
#
|
|
492
|
+
# Metadata
|
|
493
|
+
#
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
def handle_mdt_removed_obj_types(instance, action, pk_set, **kwargs): # pylint: disable=useless-return
|
|
497
|
+
"""Handle the cleanup of old Metadata when a MetadataType is removed from one or more ContentTypes."""
|
|
498
|
+
if action != "post_remove":
|
|
499
|
+
return
|
|
500
|
+
# Existing content types have been removed from the MetadataType, delete their data.
|
|
501
|
+
# TODO delete Metadata records with object_type in pk_set and metadata_type == instance
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
m2m_changed.connect(handle_mdt_removed_obj_types, sender=MetadataType.content_types.through)
|