nautobot 2.0.0a2__py3-none-any.whl → 2.0.0b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nautobot/__init__.py +1 -5
- nautobot/apps/api.py +6 -8
- nautobot/apps/forms.py +0 -2
- nautobot/apps/ui.py +0 -8
- nautobot/circuits/api/serializers.py +9 -119
- nautobot/circuits/api/urls.py +1 -1
- nautobot/circuits/api/views.py +0 -1
- nautobot/circuits/choices.py +0 -2
- nautobot/circuits/filters.py +7 -6
- nautobot/circuits/forms.py +3 -73
- nautobot/circuits/migrations/0001_initial_part_1.py +0 -1
- nautobot/circuits/migrations/0002_initial_part_2.py +0 -1
- nautobot/circuits/migrations/0003_auto_slug.py +0 -1
- nautobot/circuits/migrations/0004_increase_provider_account_length.py +0 -1
- nautobot/circuits/migrations/0005_providernetwork.py +0 -1
- nautobot/circuits/migrations/0006_cache_circuit_terminations.py +0 -1
- nautobot/circuits/migrations/0007_circuitterminations_primary_model.py +0 -1
- nautobot/circuits/migrations/0008_add_natural_indexing.py +0 -1
- nautobot/circuits/migrations/0009_circuittermination_location.py +0 -1
- nautobot/circuits/migrations/0010_rename_foreign_keys_and_related_names.py +0 -1
- nautobot/circuits/migrations/0011_remove_site_foreign_key_from_circuit_termination_class.py +0 -1
- nautobot/circuits/migrations/0012_created_datetime.py +0 -1
- nautobot/circuits/migrations/0013_alter_circuittermination__path.py +0 -1
- nautobot/circuits/migrations/0014_related_name_changes.py +1 -2
- nautobot/circuits/migrations/0015_remove_circuittype_provider_slug.py +20 -0
- nautobot/circuits/migrations/0016_tagsfield.py +34 -0
- nautobot/circuits/migrations/0017_fixup_null_statuses.py +22 -0
- nautobot/circuits/migrations/0018_status_nonnullable.py +22 -0
- nautobot/circuits/models.py +3 -93
- nautobot/circuits/navigation.py +14 -69
- nautobot/circuits/signals.py +0 -2
- nautobot/circuits/tables.py +42 -5
- nautobot/circuits/templates/circuits/circuit_retrieve.html +1 -1
- nautobot/circuits/templates/circuits/circuittermination_retrieve.html +1 -1
- nautobot/circuits/templates/circuits/circuittype_retrieve.html +1 -1
- nautobot/circuits/templates/circuits/provider_create.html +0 -1
- nautobot/circuits/templates/circuits/provider_retrieve.html +1 -1
- nautobot/circuits/tests/integration/test_relationships.py +13 -16
- nautobot/circuits/tests/test_api.py +13 -43
- nautobot/circuits/tests/test_filters.py +20 -15
- nautobot/circuits/tests/test_models.py +7 -3
- nautobot/circuits/tests/test_views.py +57 -67
- nautobot/circuits/views.py +18 -9
- nautobot/core/api/__init__.py +8 -2
- nautobot/core/api/authentication.py +0 -3
- nautobot/core/api/fields.py +15 -6
- nautobot/core/api/filter_backends.py +3 -2
- nautobot/core/api/metadata.py +237 -30
- nautobot/core/api/mixins.py +94 -0
- nautobot/core/api/pagination.py +3 -3
- nautobot/core/api/parsers.py +154 -0
- nautobot/core/api/renderers.py +153 -2
- nautobot/core/api/schema.py +47 -3
- nautobot/core/api/serializers.py +377 -37
- nautobot/core/api/urls.py +11 -3
- nautobot/core/api/utils.py +174 -2
- nautobot/core/api/versioning.py +32 -10
- nautobot/core/api/views.py +266 -75
- nautobot/core/apps/__init__.py +138 -221
- nautobot/core/celery/__init__.py +112 -41
- nautobot/core/celery/backends.py +19 -13
- nautobot/core/celery/control.py +46 -0
- nautobot/core/celery/encoders.py +53 -0
- nautobot/core/celery/log.py +38 -0
- nautobot/core/celery/schedulers.py +23 -4
- nautobot/core/celery/task.py +1 -16
- nautobot/core/checks.py +0 -27
- nautobot/core/choices.py +21 -113
- nautobot/core/{cli.py → cli/__init__.py} +1 -2
- nautobot/core/cli/__main__.py +3 -0
- nautobot/core/constants.py +25 -43
- nautobot/core/context_processors.py +12 -0
- nautobot/core/filters.py +2 -2
- nautobot/core/forms/__init__.py +0 -4
- nautobot/core/forms/fields.py +39 -68
- nautobot/core/forms/forms.py +27 -27
- nautobot/core/forms/utils.py +7 -59
- nautobot/core/forms/widgets.py +0 -1
- nautobot/core/graphql/__init__.py +2 -2
- nautobot/core/graphql/schema.py +4 -27
- nautobot/core/jobs/__init__.py +75 -0
- nautobot/core/management/commands/build_ui.py +255 -0
- nautobot/core/management/commands/celery.py +0 -1
- nautobot/core/management/commands/generate_test_data.py +18 -13
- nautobot/core/management/commands/post_upgrade.py +24 -24
- nautobot/core/management/commands/validate_models.py +0 -1
- nautobot/core/middleware.py +0 -1
- nautobot/core/models/__init__.py +26 -1
- nautobot/core/models/fields.py +24 -5
- nautobot/core/models/generics.py +2 -46
- nautobot/core/models/managers.py +5 -0
- nautobot/core/models/name_color_content_types.py +1 -19
- nautobot/core/models/tree_queries.py +14 -4
- nautobot/core/models/utils.py +9 -10
- nautobot/core/models/validators.py +17 -8
- nautobot/core/releases.py +8 -10
- nautobot/core/settings.py +81 -53
- nautobot/core/tables.py +5 -5
- nautobot/core/tasks.py +4 -7
- nautobot/core/templates/base.html +1 -49
- nautobot/core/templates/base_django.html +49 -0
- nautobot/core/templates/base_react.html +55 -0
- nautobot/core/templates/buttons/export.html +6 -4
- nautobot/core/templates/generic/object_bulk_create.html +10 -21
- nautobot/core/templates/generic/object_list.html +4 -1
- nautobot/core/templates/generic/object_retrieve_plugin_full_width.html +3 -0
- nautobot/core/templates/inc/footer.html +1 -0
- nautobot/core/templates/inc/javascript.html +0 -14
- nautobot/core/templates/inc/nav_menu.html +28 -33
- nautobot/core/templates/inc/object_details_advanced_panel.html +13 -0
- nautobot/core/templates/inc/relationships_table_rows.html +2 -2
- nautobot/core/templates/nautobot_config.py.j2 +8 -25
- nautobot/core/templates/plugin_template/__init__.py-tpl +1 -2
- nautobot/core/templates/rest_framework/api.html +8 -0
- nautobot/core/templatetags/buttons.py +32 -29
- nautobot/core/templatetags/helpers.py +1 -1
- nautobot/core/testing/__init__.py +47 -44
- nautobot/core/testing/api.py +365 -47
- nautobot/core/testing/filters.py +12 -7
- nautobot/core/testing/integration.py +1 -1
- nautobot/core/testing/migrations.py +2 -0
- nautobot/core/testing/mixins.py +22 -12
- nautobot/core/testing/schema.py +2 -1
- nautobot/core/testing/views.py +28 -51
- nautobot/core/tests/integration/test_filters.py +17 -8
- nautobot/core/tests/integration/test_navbar.py +11 -34
- nautobot/core/tests/integration/test_plugin_navbar.py +9 -103
- nautobot/core/tests/nautobot_config.py +2 -3
- nautobot/core/tests/runner.py +0 -1
- nautobot/core/tests/test_api.py +290 -24
- nautobot/core/tests/test_authentication.py +57 -14
- nautobot/core/tests/test_checks.py +0 -7
- nautobot/core/tests/test_choices.py +0 -1
- nautobot/core/tests/test_filters.py +117 -110
- nautobot/core/tests/test_forms.py +47 -110
- nautobot/core/tests/test_graphql.py +158 -135
- nautobot/core/tests/test_logging.py +4 -1
- nautobot/core/tests/test_managers.py +3 -5
- nautobot/core/tests/test_models.py +2 -0
- nautobot/core/tests/test_ordering.py +0 -2
- nautobot/core/tests/test_paginator.py +3 -1
- nautobot/core/tests/test_releases.py +12 -12
- nautobot/core/tests/test_templatetags_helpers.py +7 -4
- nautobot/core/tests/test_utils.py +112 -78
- nautobot/core/tests/test_views.py +12 -17
- nautobot/core/tests/test_views_utils.py +6 -9
- nautobot/core/utils/data.py +17 -0
- nautobot/core/utils/deprecation.py +13 -20
- nautobot/core/utils/filtering.py +53 -9
- nautobot/core/utils/git.py +12 -4
- nautobot/core/utils/lookup.py +3 -1
- nautobot/core/utils/requests.py +23 -116
- nautobot/core/views/__init__.py +1 -2
- nautobot/core/views/generic.py +131 -119
- nautobot/core/views/mixins.py +53 -62
- nautobot/core/views/paginator.py +0 -1
- nautobot/core/views/renderers.py +14 -12
- nautobot/core/views/utils.py +87 -4
- nautobot/dcim/api/serializers.py +160 -672
- nautobot/dcim/api/urls.py +1 -1
- nautobot/dcim/api/views.py +7 -46
- nautobot/dcim/choices.py +2 -25
- nautobot/dcim/elevations.py +0 -1
- nautobot/dcim/factory.py +15 -4
- nautobot/dcim/filters/__init__.py +42 -13
- nautobot/dcim/form_mixins.py +1 -27
- nautobot/dcim/forms.py +58 -797
- nautobot/dcim/management/commands/trace_paths.py +0 -1
- nautobot/dcim/migrations/0001_initial_part_1.py +0 -1
- nautobot/dcim/migrations/0002_initial_part_2.py +0 -1
- nautobot/dcim/migrations/0003_initial_part_3.py +0 -1
- nautobot/dcim/migrations/0004_initial_part_4.py +0 -1
- nautobot/dcim/migrations/0005_device_local_context_schema.py +0 -1
- nautobot/dcim/migrations/0006_auto_slug.py +0 -1
- nautobot/dcim/migrations/0007_device_secrets_group.py +0 -1
- nautobot/dcim/migrations/0008_increase_all_serial_lengths.py +0 -1
- nautobot/dcim/migrations/0009_add_natural_indexing.py +0 -1
- nautobot/dcim/migrations/0010_interface_status.py +0 -1
- nautobot/dcim/migrations/0011_interface_status_data_migration.py +0 -1
- nautobot/dcim/migrations/0012_interface_parent_bridge.py +0 -1
- nautobot/dcim/migrations/0013_location_location_type.py +0 -1
- nautobot/dcim/migrations/0014_location_status_data_migration.py +0 -1
- nautobot/dcim/migrations/0015_device_components__changeloggedmodel.py +0 -1
- nautobot/dcim/migrations/0016_device_components__timestamp_data_migration.py +0 -1
- nautobot/dcim/migrations/0017_locationtype_nestable.py +0 -1
- nautobot/dcim/migrations/0018_device_redundancy_group.py +0 -1
- nautobot/dcim/migrations/0019_device_redundancy_group_data_migration.py +0 -1
- nautobot/dcim/migrations/0020_move_site_fields_to_location_model.py +0 -1
- nautobot/dcim/migrations/0021_mptt_to_tree_queries.py +0 -1
- nautobot/dcim/migrations/0022_interface_mac_address_data_migration.py +0 -1
- nautobot/dcim/migrations/0023_alter_interface_mac_address.py +0 -1
- nautobot/dcim/migrations/0024_alter_device_and_rack_role_add_new_role.py +2 -2
- nautobot/dcim/migrations/0025_device_and_rack_roles_data_migrations.py +19 -14
- nautobot/dcim/migrations/0026_rename_device_and_rack_role.py +0 -1
- nautobot/dcim/migrations/0027_remove_device_role_and_rack_role.py +1 -2
- nautobot/dcim/migrations/0028_rename_foreignkey_fields.py +1 -2
- nautobot/dcim/migrations/0029_add_tree_managers_and_foreign_keys_pre_data_migration.py +0 -1
- nautobot/dcim/migrations/0030_migrate_region_and_site_data_to_locations.py +2 -2
- nautobot/dcim/migrations/0031_rename_path_end_point_related_name.py +0 -1
- nautobot/dcim/migrations/0032_remove_site_foreign_key_from_dcim_models.py +0 -1
- nautobot/dcim/migrations/0033_created_datetime.py +0 -1
- nautobot/dcim/migrations/0034_fixup_fks_and_related_names.py +0 -1
- nautobot/dcim/migrations/0035_related_name_changes.py +1 -2
- nautobot/dcim/migrations/0036_remove_region_and_site.py +1 -2
- nautobot/dcim/migrations/0037_interface_ip_addresses_m2m.py +0 -1
- nautobot/dcim/migrations/0038_alter_location_managers.py +0 -1
- nautobot/dcim/migrations/0039_remove_slug.py +24 -0
- nautobot/dcim/migrations/0040_tagsfield.py +109 -0
- nautobot/dcim/migrations/0041_ipam__namespaces.py +25 -0
- nautobot/dcim/migrations/0042_fixup_null_statuses.py +51 -0
- nautobot/dcim/migrations/0043_status_nonnullable.py +72 -0
- nautobot/dcim/models/cables.py +4 -35
- nautobot/dcim/models/device_component_templates.py +7 -2
- nautobot/dcim/models/device_components.py +26 -203
- nautobot/dcim/models/devices.py +30 -152
- nautobot/dcim/models/locations.py +3 -64
- nautobot/dcim/models/power.py +3 -51
- nautobot/dcim/models/racks.py +7 -86
- nautobot/dcim/navigation.py +141 -467
- nautobot/dcim/signals.py +0 -2
- nautobot/dcim/tables/devices.py +8 -5
- nautobot/dcim/tables/devicetypes.py +1 -1
- nautobot/dcim/tables/locations.py +2 -2
- nautobot/dcim/tables/power.py +2 -2
- nautobot/dcim/templates/dcim/console_port_connection_list.html +7 -0
- nautobot/dcim/templates/dcim/device.html +15 -4
- nautobot/dcim/templates/dcim/device_edit.html +6 -0
- nautobot/dcim/templates/dcim/deviceredundancygroup_create.html +0 -1
- nautobot/dcim/templates/dcim/devicetype.html +2 -2
- nautobot/dcim/templates/dcim/interface.html +4 -0
- nautobot/dcim/templates/dcim/interface_connection_list.html +7 -0
- nautobot/dcim/templates/dcim/interface_edit.html +1 -0
- nautobot/dcim/templates/dcim/location.html +16 -1
- nautobot/dcim/templates/dcim/locationtype.html +15 -0
- nautobot/dcim/templates/dcim/power_port_connection_list.html +7 -0
- nautobot/dcim/templates/dcim/rackgroup.html +0 -12
- nautobot/dcim/tests/integration/test_cable_connect_form.py +4 -4
- nautobot/dcim/tests/test_api.py +202 -130
- nautobot/dcim/tests/test_cablepaths.py +47 -42
- nautobot/dcim/tests/test_filters.py +156 -134
- nautobot/dcim/tests/test_forms.py +12 -213
- nautobot/dcim/tests/test_graphql.py +8 -3
- nautobot/dcim/tests/test_migrations.py +6 -11
- nautobot/dcim/tests/test_models.py +208 -158
- nautobot/dcim/tests/test_natural_ordering.py +12 -14
- nautobot/dcim/tests/test_signals.py +7 -4
- nautobot/dcim/tests/test_views.py +270 -264
- nautobot/dcim/urls.py +21 -26
- nautobot/dcim/views.py +14 -156
- nautobot/docs/additional-features/caching.md +6 -87
- nautobot/docs/additional-features/job-scheduling-and-approvals.md +3 -0
- nautobot/docs/additional-features/jobs.md +179 -197
- nautobot/docs/administration/nautobot-server.md +9 -24
- nautobot/docs/administration/nautobot-shell.md +6 -6
- nautobot/docs/administration/replicating-nautobot.md +0 -10
- nautobot/docs/configuration/index.md +9 -9
- nautobot/docs/configuration/optional-settings.md +32 -61
- nautobot/docs/configuration/required-settings.md +11 -52
- nautobot/docs/development/application-registry.md +2 -13
- nautobot/docs/development/best-practices.md +2 -1
- nautobot/docs/development/docker-compose-advanced-use-cases.md +1 -1
- nautobot/docs/development/extending-models.md +15 -17
- nautobot/docs/development/generic-views.md +0 -2
- nautobot/docs/development/getting-started.md +56 -6
- nautobot/docs/development/navigation-menu.md +22 -93
- nautobot/docs/development/react-ui.md +105 -0
- nautobot/docs/development/release-checklist.md +3 -3
- nautobot/docs/development/role-internals.md +1 -3
- nautobot/docs/development/style-guide.md +6 -4
- nautobot/docs/development/templates.md +2 -1
- nautobot/docs/docker/index.md +16 -14
- nautobot/docs/index.md +7 -3
- nautobot/docs/installation/index.md +4 -1
- nautobot/docs/installation/migrating-from-netbox.md +12 -43
- nautobot/docs/installation/migrating-from-postgresql.md +1 -1
- nautobot/docs/installation/nautobot.md +1 -1
- nautobot/docs/installation/tables/v2-api-behavior-changes.yaml +70 -0
- nautobot/docs/installation/tables/v2-api-removed-fields.yaml +142 -0
- nautobot/docs/installation/tables/v2-api-renamed-fields.yaml +124 -0
- nautobot/docs/installation/tables/v2-code-location-changes.yaml +241 -0
- nautobot/docs/installation/tables/v2-code-removals.yaml +67 -0
- nautobot/docs/installation/tables/v2-database-behavior-changes.yaml +37 -0
- nautobot/docs/installation/tables/v2-database-removed-fields.yaml +166 -0
- nautobot/docs/installation/tables/v2-database-renamed-fields.yaml +340 -0
- nautobot/docs/installation/tables/v2-filters-corrected-fields.yaml +28 -0
- nautobot/docs/installation/tables/v2-filters-enhanced-fields.yaml +241 -0
- nautobot/docs/installation/tables/v2-filters-removed-fields.yaml +553 -0
- nautobot/docs/installation/tables/v2-filters-renamed-fields.yaml +223 -0
- nautobot/docs/installation/tables/v2-logging-renamed-loggers.yaml +23 -0
- nautobot/docs/installation/upgrading-from-nautobot-v1.md +190 -636
- nautobot/docs/installation/upgrading.md +5 -2
- nautobot/docs/models/dcim/device.md +3 -0
- nautobot/docs/models/dcim/deviceredundancygroup.md +3 -3
- nautobot/docs/models/extras/computedfield.md +4 -4
- nautobot/docs/models/extras/dynamicgroup.md +9 -9
- nautobot/docs/models/extras/gitrepository.md +3 -0
- nautobot/docs/models/extras/job.md +1 -0
- nautobot/docs/models/extras/jobbutton.md +18 -13
- nautobot/docs/models/extras/jobhook.md +7 -4
- nautobot/docs/models/extras/jobresult.md +6 -2
- nautobot/docs/models/extras/relationship.md +2 -2
- nautobot/docs/models/extras/status.md +6 -19
- nautobot/docs/models/ipam/ipaddress.md +3 -0
- nautobot/docs/models/ipam/vrf.md +0 -3
- nautobot/docs/models/virtualization/virtualmachine.md +3 -0
- nautobot/docs/plugins/development.md +92 -24
- nautobot/docs/release-notes/version-1.5.md +96 -0
- nautobot/docs/release-notes/version-2.0.md +216 -0
- nautobot/docs/requirements.txt +5 -4
- nautobot/docs/rest-api/overview.md +384 -215
- nautobot/docs/rest-api/ui-related-endpoints.md +9 -0
- nautobot/extras/admin.py +3 -5
- nautobot/extras/api/customfields.py +15 -39
- nautobot/extras/api/fields.py +0 -11
- nautobot/extras/api/mixins.py +45 -0
- nautobot/extras/api/relationships.py +63 -159
- nautobot/extras/api/serializers.py +165 -706
- nautobot/extras/api/urls.py +1 -1
- nautobot/extras/api/views.py +295 -282
- nautobot/extras/apps.py +4 -7
- nautobot/extras/choices.py +11 -22
- nautobot/extras/constants.py +9 -3
- nautobot/extras/datasources/__init__.py +2 -0
- nautobot/extras/datasources/git.py +135 -186
- nautobot/extras/datasources/registry.py +25 -35
- nautobot/extras/factory.py +1 -3
- nautobot/extras/filters/__init__.py +49 -47
- nautobot/extras/filters/mixins.py +10 -8
- nautobot/extras/forms/forms.py +72 -148
- nautobot/extras/forms/mixins.py +34 -57
- nautobot/extras/health_checks.py +0 -33
- nautobot/extras/jobs.py +387 -566
- nautobot/extras/management/__init__.py +55 -48
- nautobot/extras/management/commands/renaturalize.py +0 -1
- nautobot/extras/management/commands/runjob.py +24 -62
- nautobot/extras/management/commands/webhook_receiver.py +0 -1
- nautobot/extras/managers.py +30 -7
- nautobot/extras/migrations/0001_initial_part_1.py +0 -1
- nautobot/extras/migrations/0002_initial_part_2.py +0 -1
- nautobot/extras/migrations/0003_initial_part_3.py +0 -1
- nautobot/extras/migrations/0004_populate_default_status_records.py +0 -1
- nautobot/extras/migrations/0005_configcontext_device_types.py +0 -1
- nautobot/extras/migrations/0006_graphqlquery.py +0 -1
- nautobot/extras/migrations/0007_configcontextschema.py +0 -1
- nautobot/extras/migrations/0008_jobresult__custom_field_data.py +0 -1
- nautobot/extras/migrations/0009_computedfield.py +0 -1
- nautobot/extras/migrations/0010_change_cf_validation_max_min_field_to_bigint.py +0 -1
- nautobot/extras/migrations/0011_fileattachment_fileproxy.py +0 -1
- nautobot/extras/migrations/0012_healthchecktestmodel.py +0 -1
- nautobot/extras/migrations/0013_default_fallback_value_computedfield.py +0 -1
- nautobot/extras/migrations/0014_auto_slug.py +0 -1
- nautobot/extras/migrations/0015_scheduled_job.py +0 -1
- nautobot/extras/migrations/0016_secret.py +0 -1
- nautobot/extras/migrations/0017_joblogentry.py +0 -1
- nautobot/extras/migrations/0018_joblog_data_migration.py +0 -2
- nautobot/extras/migrations/0019_joblogentry__meta_options__related_name.py +0 -1
- nautobot/extras/migrations/0020_customfield_changelog.py +0 -1
- nautobot/extras/migrations/0021_customfield_changelog_data.py +0 -1
- nautobot/extras/migrations/0022_objectchange_object_datav2.py +0 -1
- nautobot/extras/migrations/0023_job_model.py +0 -1
- nautobot/extras/migrations/0024_job_data_migration.py +0 -1
- nautobot/extras/migrations/0025_add_advanced_ui_boolean_to_customfield_conputedfield_and_relationship.py +0 -1
- nautobot/extras/migrations/0026_job_add_gitrepository_fk.py +0 -1
- nautobot/extras/migrations/0027_job_gitrepository_data_migration.py +0 -1
- nautobot/extras/migrations/0028_job_reduce_source.py +0 -1
- nautobot/extras/migrations/0029_dynamicgroup.py +0 -1
- nautobot/extras/migrations/0030_webhook_alter_unique_together.py +0 -1
- nautobot/extras/migrations/0031_tag_content_types.py +0 -1
- nautobot/extras/migrations/0032_tag_content_types_data_migration.py +0 -1
- nautobot/extras/migrations/0033_add__optimized_indexing.py +0 -1
- nautobot/extras/migrations/0034_alter_fileattachment_mimetype.py +0 -1
- nautobot/extras/migrations/0035_scheduledjob_crontab.py +0 -1
- nautobot/extras/migrations/0036_job_add_has_sensitive_variables.py +0 -1
- nautobot/extras/migrations/0037_configcontextschema__remove_name_unique__create_constraint_unique_name_owner.py +0 -1
- nautobot/extras/migrations/0038_configcontext_locations.py +0 -1
- nautobot/extras/migrations/0039_objectchange__add_change_context.py +0 -1
- nautobot/extras/migrations/0040_dynamicgroup__dynamicgroupmembership.py +0 -1
- nautobot/extras/migrations/0041_jobresult_job_kwargs.py +0 -1
- nautobot/extras/migrations/0042_job__add_is_job_hook_receiver.py +0 -1
- nautobot/extras/migrations/0043_note.py +0 -1
- nautobot/extras/migrations/0044_add_job_hook.py +0 -1
- nautobot/extras/migrations/0045_add_custom_field_slug.py +0 -1
- nautobot/extras/migrations/0046_populate_custom_field_slug_label.py +0 -1
- nautobot/extras/migrations/0047_enforce_custom_field_slug.py +0 -1
- nautobot/extras/migrations/0048_alter_objectchange_change_context_detail.py +0 -1
- nautobot/extras/migrations/0049_alter_tag_slug.py +0 -1
- nautobot/extras/migrations/0050_customfield_grouping.py +0 -1
- nautobot/extras/migrations/0051_add_job_task_queues.py +0 -1
- nautobot/extras/migrations/0052_configcontext_device_redundancy_groups.py +0 -1
- nautobot/extras/migrations/0053_relationship_required_on.py +0 -1
- nautobot/extras/migrations/0054_scheduledjob_kwargs_request_user_change.py +0 -1
- nautobot/extras/migrations/0055_configcontext_dynamic_groups.py +0 -1
- nautobot/extras/migrations/0056_objectchange_add_reverse_time_idx.py +0 -1
- nautobot/extras/migrations/0057_jobbutton.py +0 -1
- nautobot/extras/migrations/0058_jobresult_add_time_status_idxs.py +38 -0
- nautobot/extras/migrations/{0058_joblogentry_scheduledjob_webhook_data_migration.py → 0059_joblogentry_scheduledjob_webhook_data_migration.py} +1 -2
- nautobot/extras/migrations/{0059_alter_joblogentry_scheduledjob_webhook_fields.py → 0060_alter_joblogentry_scheduledjob_webhook_fields.py} +1 -2
- nautobot/extras/migrations/{0060_role_and_alter_status.py → 0061_role_and_alter_status.py} +1 -8
- nautobot/extras/migrations/{0061_collect_roles_from_related_apps_roles.py → 0062_collect_roles_from_related_apps_roles.py} +33 -33
- nautobot/extras/migrations/{0062_alter_role_options.py → 0063_alter_role_options.py} +1 -2
- nautobot/extras/migrations/{0063_alter_configcontext_and_add_new_role.py → 0064_alter_configcontext_and_add_new_role.py} +1 -2
- nautobot/extras/migrations/0065_configcontext_data_migrations.py +44 -0
- nautobot/extras/migrations/{0065_rename_configcontext_role.py → 0066_rename_configcontext_role.py} +1 -2
- nautobot/extras/migrations/{0066_jobresult__add_celery_fields.py → 0067_jobresult__add_celery_fields.py} +36 -3
- nautobot/extras/migrations/{0067_created_datetime.py → 0068_created_datetime.py} +1 -2
- nautobot/extras/migrations/{0068_remove_site_and_region_attributes_from_config_context.py → 0069_remove_site_and_region_attributes_from_config_context.py} +1 -2
- nautobot/extras/migrations/{0069_replace_related_names.py → 0070_replace_related_names.py} +1 -1
- nautobot/extras/migrations/{0070_rename_model_fields.py → 0071_rename_model_fields.py} +1 -2
- nautobot/extras/migrations/0072_job__unique_name_data_migration.py +86 -0
- nautobot/extras/migrations/{0072_job__unique_name.py → 0073_job__unique_name.py} +13 -10
- nautobot/extras/migrations/{0073_remove_gitrepository_fields.py → 0074_remove_gitrepository_fields.py} +1 -2
- nautobot/extras/migrations/{0074_rename_slug_to_key_for_custom_field.py → 0075_rename_slug_to_key_for_custom_field.py} +1 -1
- nautobot/extras/migrations/{0075_migrate_custom_field_data.py → 0076_migrate_custom_field_data.py} +1 -1
- nautobot/extras/migrations/{0076_remove_name_field_and_make_label_field_non_nullable.py → 0077_remove_name_field_and_make_label_field_non_nullable.py} +1 -1
- nautobot/extras/migrations/0078_remove_slug.py +45 -0
- nautobot/extras/migrations/0079_tagsfield.py +28 -0
- nautobot/extras/migrations/0080_rename_relationship_slug_to_key.py +17 -0
- nautobot/extras/migrations/0081_rename_relationship_name_to_label.py +29 -0
- nautobot/extras/migrations/0082_ensure_relationship_keys_are_unique.py +43 -0
- nautobot/extras/migrations/0083_rename_computed_field_slug_to_key.py +21 -0
- nautobot/extras/migrations/0084_taggeditem_cleanup.py +43 -0
- nautobot/extras/migrations/0085_taggeditem_uniqueness.py +22 -0
- nautobot/extras/migrations/0086_job__celery_task_fields__dryrun_support.py +81 -0
- nautobot/extras/migrations/0087_job__commit_default_data_migration.py +26 -0
- nautobot/extras/migrations/0088_joblogentry__log_level_default.py +17 -0
- nautobot/extras/migrations/0089_joblogentry__log_level_data_migration.py +34 -0
- nautobot/extras/migrations/0090_scheduledjob__data_migration.py +57 -0
- nautobot/extras/models/__init__.py +2 -3
- nautobot/extras/models/change_logging.py +0 -36
- nautobot/extras/models/customfields.py +39 -33
- nautobot/extras/models/datasources.py +48 -50
- nautobot/extras/models/groups.py +5 -12
- nautobot/extras/models/jobs.py +190 -323
- nautobot/extras/models/mixins.py +0 -71
- nautobot/extras/models/models.py +1 -22
- nautobot/extras/models/relationships.py +20 -21
- nautobot/extras/models/roles.py +0 -23
- nautobot/extras/models/secrets.py +2 -31
- nautobot/extras/models/statuses.py +6 -5
- nautobot/extras/models/tags.py +2 -17
- nautobot/extras/navigation.py +89 -307
- nautobot/extras/plugins/__init__.py +3 -121
- nautobot/extras/plugins/utils.py +0 -3
- nautobot/extras/plugins/validators.py +5 -4
- nautobot/extras/plugins/views.py +16 -4
- nautobot/extras/querysets.py +1 -7
- nautobot/extras/registry.py +3 -0
- nautobot/extras/signals.py +26 -60
- nautobot/extras/tables.py +42 -49
- nautobot/extras/tasks.py +0 -12
- nautobot/extras/templates/extras/configcontext.html +1 -1
- nautobot/extras/templates/extras/configcontextschema.html +16 -1
- nautobot/extras/templates/extras/customfield.html +0 -13
- nautobot/extras/templates/extras/dynamicgroup_edit.html +0 -1
- nautobot/extras/templates/extras/gitrepository.html +3 -3
- nautobot/extras/templates/extras/inc/jobresult.html +10 -0
- nautobot/extras/templates/extras/inc/panel_jobhistory.html +1 -1
- nautobot/extras/templates/extras/job.html +35 -25
- nautobot/extras/templates/extras/job_approval_request.html +15 -30
- nautobot/extras/templates/extras/job_detail.html +13 -31
- nautobot/extras/templates/extras/job_edit.html +14 -17
- nautobot/extras/templates/extras/jobresult.html +24 -6
- nautobot/extras/templates/extras/objectchange_list.html +1 -1
- nautobot/extras/templates/extras/scheduledjob.html +2 -2
- nautobot/extras/templates/extras/secret.html +28 -0
- nautobot/extras/templates/extras/secret_edit.html +0 -1
- nautobot/extras/templates/extras/secretsgroup_edit.html +0 -1
- nautobot/extras/templatetags/custom_links.py +0 -2
- nautobot/extras/templatetags/job_buttons.py +1 -0
- nautobot/extras/templatetags/plugins.py +0 -1
- nautobot/extras/{tests/example_jobs → test_jobs}/api_test_job.py +13 -6
- nautobot/extras/test_jobs/atomic_transaction.py +53 -0
- nautobot/extras/test_jobs/dry_run.py +29 -0
- nautobot/extras/{tests/example_jobs/test_duplicate_name.py → test_jobs/duplicate_name.py} +4 -0
- nautobot/extras/test_jobs/duplicate_name2.py +9 -0
- nautobot/extras/test_jobs/fail.py +23 -0
- nautobot/extras/{tests/example_jobs/test_field_default.py → test_jobs/field_default.py} +4 -0
- nautobot/extras/{tests/example_jobs/test_field_order.py → test_jobs/field_order.py} +4 -0
- nautobot/extras/{tests/example_jobs/test_file_upload_fail.py → test_jobs/file_upload_fail.py} +11 -6
- nautobot/extras/test_jobs/file_upload_pass.py +25 -0
- nautobot/extras/test_jobs/has_sensitive_variables.py +25 -0
- nautobot/extras/test_jobs/ipaddress_vars.py +66 -0
- nautobot/extras/test_jobs/job_button_receiver.py +28 -0
- nautobot/extras/test_jobs/job_hook_receiver.py +29 -0
- nautobot/extras/test_jobs/job_variables.py +88 -0
- nautobot/extras/test_jobs/location_with_custom_field.py +45 -0
- nautobot/extras/test_jobs/log_redaction.py +20 -0
- nautobot/extras/test_jobs/log_skip_db_logging.py +17 -0
- nautobot/extras/test_jobs/modify_db.py +25 -0
- nautobot/extras/{tests/example_jobs/test_no_field_order.py → test_jobs/no_field_order.py} +4 -0
- nautobot/extras/test_jobs/object_var_optional.py +21 -0
- nautobot/extras/test_jobs/object_var_required.py +21 -0
- nautobot/extras/test_jobs/object_vars.py +26 -0
- nautobot/extras/test_jobs/pass.py +25 -0
- nautobot/extras/test_jobs/profiling.py +32 -0
- nautobot/extras/test_jobs/read_only_job.py +15 -0
- nautobot/extras/{tests/example_jobs/test_required_args.py → test_jobs/required_args.py} +4 -0
- nautobot/extras/{tests/example_jobs/test_soft_time_limit_greater_than_time_limit.py → test_jobs/soft_time_limit_greater_than_time_limit.py} +5 -1
- nautobot/extras/{tests/example_jobs/test_task_queues.py → test_jobs/task_queues.py} +5 -1
- nautobot/extras/tests/integration/__init__.py +3 -3
- nautobot/extras/tests/integration/test_computedfields.py +1 -1
- nautobot/extras/tests/integration/test_configcontextschema.py +7 -5
- nautobot/extras/tests/integration/test_customfields.py +4 -2
- nautobot/extras/tests/integration/test_dynamicgroups.py +2 -2
- nautobot/extras/tests/integration/test_jobs.py +25 -27
- nautobot/extras/tests/integration/test_notes.py +8 -4
- nautobot/extras/tests/integration/test_plugins.py +4 -4
- nautobot/extras/tests/integration/test_relationships.py +2 -2
- nautobot/extras/tests/test_api.py +371 -381
- nautobot/extras/tests/test_changelog.py +17 -16
- nautobot/extras/tests/test_context_managers.py +5 -6
- nautobot/extras/tests/test_customfields.py +112 -73
- nautobot/extras/tests/test_datasources.py +191 -117
- nautobot/extras/tests/test_dynamicgroups.py +45 -68
- nautobot/extras/tests/test_filters.py +170 -130
- nautobot/extras/tests/test_forms.py +107 -109
- nautobot/extras/tests/{test_scripts.py → test_job_variables.py} +43 -49
- nautobot/extras/tests/test_jobs.py +271 -273
- nautobot/extras/tests/test_management.py +3 -6
- nautobot/extras/tests/test_migrations.py +5 -3
- nautobot/extras/tests/test_models.py +121 -173
- nautobot/extras/tests/test_notes.py +0 -1
- nautobot/extras/tests/test_plugins.py +55 -89
- nautobot/extras/tests/test_relationships.py +174 -130
- nautobot/extras/tests/test_tags.py +6 -12
- nautobot/extras/tests/test_utils.py +31 -1
- nautobot/extras/tests/test_views.py +223 -184
- nautobot/extras/tests/test_webhooks.py +16 -15
- nautobot/extras/urls.py +69 -69
- nautobot/extras/utils.py +137 -163
- nautobot/extras/views.py +81 -153
- nautobot/ipam/api/fields.py +17 -0
- nautobot/ipam/api/serializers.py +77 -164
- nautobot/ipam/api/urls.py +4 -1
- nautobot/ipam/api/views.py +28 -19
- nautobot/ipam/apps.py +1 -0
- nautobot/ipam/choices.py +5 -12
- nautobot/ipam/constants.py +1 -0
- nautobot/ipam/factory.py +41 -30
- nautobot/ipam/filters.py +58 -25
- nautobot/ipam/forms.py +82 -211
- nautobot/ipam/graphql/types.py +0 -9
- nautobot/ipam/lookups.py +13 -8
- nautobot/ipam/management/commands/__init__.py +0 -0
- nautobot/ipam/management/commands/fix_prefix_broadcast.py +17 -0
- nautobot/ipam/migrations/0001_initial_part_1.py +0 -1
- nautobot/ipam/migrations/0002_initial_part_2.py +0 -1
- nautobot/ipam/migrations/0003_remove_max_length.py +0 -1
- nautobot/ipam/migrations/0004_fixup_p2p_broadcast.py +0 -1
- nautobot/ipam/migrations/0005_auto_slug.py +0 -1
- nautobot/ipam/migrations/0006_ipaddress_nat_outside_list.py +0 -1
- nautobot/ipam/migrations/0007_add_natural_indexing.py +0 -1
- nautobot/ipam/migrations/0008_prefix_vlan_vlangroup_location.py +0 -1
- nautobot/ipam/migrations/0009_alter_vlan_name.py +0 -1
- nautobot/ipam/migrations/0010_alter_ipam_role_add_new_role.py +1 -2
- nautobot/ipam/migrations/0011_migrate_ipam_role_data.py +32 -39
- nautobot/ipam/migrations/0012_rename_ipam_roles.py +0 -1
- nautobot/ipam/migrations/0013_delete_role.py +0 -1
- nautobot/ipam/migrations/0014_rename_foreign_keys_and_related_names.py +0 -1
- nautobot/ipam/migrations/0015_prefix_add_type.py +0 -1
- nautobot/ipam/migrations/0016_prefix_type_data_migration.py +0 -3
- nautobot/ipam/migrations/0017_prefix_remove_is_pool.py +0 -1
- nautobot/ipam/migrations/0018_remove_site_foreign_key_from_ipam_models.py +0 -1
- nautobot/ipam/migrations/0019_created_datetime.py +0 -1
- nautobot/ipam/migrations/0020_related_name_changes.py +1 -2
- nautobot/ipam/migrations/0021_prefix_add_rir_and_date_allocated.py +0 -1
- nautobot/ipam/migrations/0022_aggregate_to_prefix_data_migration.py +3 -5
- nautobot/ipam/migrations/0023_delete_aggregate.py +0 -1
- nautobot/ipam/migrations/0024_interface_to_ipaddress_m2m.py +0 -1
- nautobot/ipam/migrations/0025_interface_ipaddress_m2m_data_migration.py +0 -1
- nautobot/ipam/migrations/0026_ipaddress_remove_assigned_object.py +0 -1
- nautobot/ipam/migrations/0027_remove_rir_slug.py +16 -0
- nautobot/ipam/migrations/0028_tagsfield.py +44 -0
- nautobot/ipam/migrations/0029_ip_address_to_interface_uniqueness_constraints.py +18 -0
- nautobot/ipam/migrations/0030_ipam__namespaces.py +231 -0
- nautobot/ipam/migrations/0031_ipam__prefix__add_parent.py +58 -0
- nautobot/ipam/migrations/0032_ipam__namespaces_finish.py +63 -0
- nautobot/ipam/migrations/0033_fixup_null_statuses.py +26 -0
- nautobot/ipam/migrations/0034_status_nonnullable.py +36 -0
- nautobot/ipam/models.py +579 -368
- nautobot/ipam/navigation.py +36 -159
- nautobot/ipam/querysets.py +117 -90
- nautobot/ipam/signals.py +89 -0
- nautobot/ipam/tables.py +86 -28
- nautobot/ipam/templates/ipam/ipaddress.html +14 -30
- nautobot/ipam/templates/ipam/ipaddress_edit.html +1 -0
- nautobot/ipam/templates/ipam/namespace_ipaddresses.html +11 -0
- nautobot/ipam/templates/ipam/namespace_prefixes.html +11 -0
- nautobot/ipam/templates/ipam/namespace_retrieve.html +42 -0
- nautobot/ipam/templates/ipam/namespace_vrfs.html +11 -0
- nautobot/ipam/templates/ipam/prefix.html +27 -33
- nautobot/ipam/templates/ipam/prefix_edit.html +7 -1
- nautobot/ipam/templates/ipam/vlangroup.html +0 -13
- nautobot/ipam/templates/ipam/vrf.html +6 -4
- nautobot/ipam/templates/ipam/vrf_edit.html +20 -2
- nautobot/ipam/tests/integration/test_prefixes.py +4 -27
- nautobot/ipam/tests/test_api.py +60 -61
- nautobot/ipam/tests/test_filters.py +187 -126
- nautobot/ipam/tests/test_forms.py +12 -6
- nautobot/ipam/tests/test_graphql.py +8 -6
- nautobot/ipam/tests/test_migrations.py +8 -13
- nautobot/ipam/tests/test_models.py +426 -274
- nautobot/ipam/tests/test_ordering.py +6 -3
- nautobot/ipam/tests/test_querysets.py +340 -96
- nautobot/ipam/tests/test_views.py +100 -55
- nautobot/ipam/urls.py +28 -5
- nautobot/ipam/{utils.py → utils/__init__.py} +2 -2
- nautobot/ipam/utils/migrations.py +713 -0
- nautobot/ipam/views.py +237 -122
- nautobot/project-static/docs/404.html +1399 -166
- nautobot/project-static/docs/additional-features/caching.html +1416 -320
- nautobot/project-static/docs/additional-features/change-logging.html +1389 -190
- nautobot/project-static/docs/additional-features/config-contexts.html +1389 -190
- nautobot/project-static/docs/additional-features/graphql.html +1389 -190
- nautobot/project-static/docs/additional-features/healthcheck.html +1389 -190
- nautobot/project-static/docs/additional-features/job-scheduling-and-approvals.html +1393 -190
- nautobot/project-static/docs/additional-features/jobs.html +1677 -460
- nautobot/project-static/docs/additional-features/napalm.html +1389 -190
- nautobot/project-static/docs/additional-features/prometheus-metrics.html +1389 -190
- nautobot/project-static/docs/additional-features/template-filters.html +1389 -190
- nautobot/project-static/docs/administration/celery-queues.html +1389 -190
- nautobot/project-static/docs/administration/nautobot-server.html +1553 -375
- nautobot/project-static/docs/administration/nautobot-shell.html +1395 -196
- nautobot/project-static/docs/administration/permissions.html +1389 -190
- nautobot/project-static/docs/administration/replicating-nautobot.html +1387 -207
- nautobot/project-static/docs/apps/index.html +1389 -190
- nautobot/project-static/docs/apps/nautobot-apps.html +1387 -175
- nautobot/project-static/docs/assets/javascripts/bundle.51198bba.min.js +29 -0
- nautobot/project-static/docs/assets/javascripts/bundle.51198bba.min.js.map +8 -0
- nautobot/project-static/docs/assets/javascripts/workers/{search.16e2a7d4.min.js → search.208ed371.min.js} +9 -15
- nautobot/project-static/docs/assets/javascripts/workers/{search.16e2a7d4.min.js.map → search.208ed371.min.js.map} +4 -4
- nautobot/project-static/docs/assets/stylesheets/main.ded33207.min.css +1 -0
- nautobot/project-static/docs/assets/stylesheets/main.ded33207.min.css.map +1 -0
- nautobot/project-static/docs/assets/stylesheets/palette.a0c5b2b5.min.css +1 -0
- nautobot/project-static/docs/assets/stylesheets/palette.a0c5b2b5.min.css.map +1 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +1775 -590
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +1389 -190
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +3588 -1922
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +1461 -262
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +1401 -170
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +1396 -191
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +2095 -894
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +2357 -1194
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +2258 -940
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +1389 -190
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +1400 -201
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +11068 -7861
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +2867 -2224
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +1389 -190
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +2641 -1573
- nautobot/project-static/docs/configuration/authentication/ldap.html +1389 -190
- nautobot/project-static/docs/configuration/authentication/remote.html +1389 -190
- nautobot/project-static/docs/configuration/authentication/sso.html +1389 -190
- nautobot/project-static/docs/configuration/index.html +1398 -199
- nautobot/project-static/docs/configuration/optional-settings.html +1418 -274
- nautobot/project-static/docs/configuration/required-settings.html +1419 -287
- nautobot/project-static/docs/core-functionality/circuits.html +1446 -247
- nautobot/project-static/docs/core-functionality/device-types.html +1448 -249
- nautobot/project-static/docs/core-functionality/devices.html +1452 -249
- nautobot/project-static/docs/core-functionality/ipam.html +1452 -253
- nautobot/project-static/docs/core-functionality/power.html +1448 -249
- nautobot/project-static/docs/core-functionality/secrets.html +1448 -249
- nautobot/project-static/docs/core-functionality/services.html +1448 -249
- nautobot/project-static/docs/core-functionality/sites-and-racks.html +1448 -249
- nautobot/project-static/docs/core-functionality/tenancy.html +1448 -249
- nautobot/project-static/docs/core-functionality/virtualization.html +1452 -249
- nautobot/project-static/docs/core-functionality/vlans.html +1448 -249
- nautobot/project-static/docs/development/application-registry.html +1393 -214
- nautobot/project-static/docs/development/best-practices.html +1392 -192
- nautobot/project-static/docs/development/docker-compose-advanced-use-cases.html +1390 -191
- nautobot/project-static/docs/development/extending-models.html +1443 -257
- nautobot/project-static/docs/development/generic-views.html +1403 -174
- nautobot/project-static/docs/development/getting-started.html +1568 -262
- nautobot/project-static/docs/development/homepage.html +1389 -190
- nautobot/project-static/docs/development/index.html +1389 -190
- nautobot/project-static/docs/development/model-features.html +1389 -190
- nautobot/project-static/docs/development/natural-keys.html +1389 -190
- nautobot/project-static/docs/development/navigation-menu.html +1451 -330
- nautobot/project-static/docs/development/react-ui.html +4199 -0
- nautobot/project-static/docs/development/release-checklist.html +1392 -193
- nautobot/project-static/docs/development/role-internals.html +1402 -172
- nautobot/project-static/docs/development/style-guide.html +1399 -199
- nautobot/project-static/docs/development/templates.html +1391 -191
- nautobot/project-static/docs/development/testing.html +1389 -190
- nautobot/project-static/docs/development/user-preferences.html +1389 -190
- nautobot/project-static/docs/docker/index.html +1408 -206
- nautobot/project-static/docs/index.html +1397 -180
- nautobot/project-static/docs/installation/centos.html +1401 -170
- nautobot/project-static/docs/installation/external-authentication.html +1389 -190
- nautobot/project-static/docs/installation/http-server.html +1389 -190
- nautobot/project-static/docs/installation/index.html +1394 -191
- nautobot/project-static/docs/installation/migrating-from-netbox.html +1452 -305
- nautobot/project-static/docs/installation/migrating-from-postgresql.html +1390 -191
- nautobot/project-static/docs/installation/nautobot.html +1390 -191
- nautobot/project-static/docs/installation/region-and-site-data-migration-guide.html +1389 -190
- nautobot/project-static/docs/installation/selinux-troubleshooting.html +1401 -170
- nautobot/project-static/docs/installation/services.html +1389 -190
- nautobot/project-static/docs/installation/tables/v2-api-behavior-changes.yaml +70 -0
- nautobot/project-static/docs/installation/tables/v2-api-removed-fields.yaml +142 -0
- nautobot/project-static/docs/installation/tables/v2-api-renamed-fields.yaml +124 -0
- nautobot/project-static/docs/installation/tables/v2-code-location-changes.yaml +241 -0
- nautobot/project-static/docs/installation/tables/v2-code-removals.yaml +67 -0
- nautobot/project-static/docs/installation/tables/v2-database-behavior-changes.yaml +37 -0
- nautobot/project-static/docs/installation/tables/v2-database-removed-fields.yaml +166 -0
- nautobot/project-static/docs/installation/tables/v2-database-renamed-fields.yaml +340 -0
- nautobot/project-static/docs/installation/tables/v2-filters-corrected-fields.yaml +28 -0
- nautobot/project-static/docs/installation/tables/v2-filters-enhanced-fields.yaml +241 -0
- nautobot/project-static/docs/installation/tables/v2-filters-removed-fields.yaml +553 -0
- nautobot/project-static/docs/installation/tables/v2-filters-renamed-fields.yaml +223 -0
- nautobot/project-static/docs/installation/tables/v2-logging-renamed-loggers.yaml +23 -0
- nautobot/project-static/docs/installation/ubuntu.html +1401 -170
- nautobot/project-static/docs/installation/upgrading-from-nautobot-v1.html +4254 -1923
- nautobot/project-static/docs/installation/upgrading.html +1395 -192
- nautobot/project-static/docs/models/circuits/circuit.html +1427 -174
- nautobot/project-static/docs/models/circuits/circuittermination.html +1427 -174
- nautobot/project-static/docs/models/circuits/circuittype.html +1427 -174
- nautobot/project-static/docs/models/circuits/provider.html +1427 -174
- nautobot/project-static/docs/models/circuits/providernetwork.html +1427 -174
- nautobot/project-static/docs/models/dcim/cable.html +1458 -174
- nautobot/project-static/docs/models/dcim/consoleport.html +1427 -174
- nautobot/project-static/docs/models/dcim/consoleporttemplate.html +1427 -174
- nautobot/project-static/docs/models/dcim/consoleserverport.html +1427 -174
- nautobot/project-static/docs/models/dcim/consoleserverporttemplate.html +1427 -174
- nautobot/project-static/docs/models/dcim/device.html +1431 -174
- nautobot/project-static/docs/models/dcim/devicebay.html +1427 -174
- nautobot/project-static/docs/models/dcim/devicebaytemplate.html +1427 -174
- nautobot/project-static/docs/models/dcim/deviceredundancygroup.html +1522 -177
- nautobot/project-static/docs/models/dcim/devicetype.html +1427 -174
- nautobot/project-static/docs/models/dcim/frontport.html +1427 -174
- nautobot/project-static/docs/models/dcim/frontporttemplate.html +1427 -174
- nautobot/project-static/docs/models/dcim/interface.html +1427 -174
- nautobot/project-static/docs/models/dcim/interfacetemplate.html +1427 -174
- nautobot/project-static/docs/models/dcim/inventoryitem.html +1427 -174
- nautobot/project-static/docs/models/dcim/location.html +1427 -174
- nautobot/project-static/docs/models/dcim/locationtype.html +1427 -174
- nautobot/project-static/docs/models/dcim/manufacturer.html +1427 -174
- nautobot/project-static/docs/models/dcim/platform.html +1427 -174
- nautobot/project-static/docs/models/dcim/powerfeed.html +1425 -172
- nautobot/project-static/docs/models/dcim/poweroutlet.html +1427 -174
- nautobot/project-static/docs/models/dcim/poweroutlettemplate.html +1427 -174
- nautobot/project-static/docs/models/dcim/powerpanel.html +1425 -172
- nautobot/project-static/docs/models/dcim/powerport.html +1427 -174
- nautobot/project-static/docs/models/dcim/powerporttemplate.html +1427 -174
- nautobot/project-static/docs/models/dcim/rack.html +1427 -174
- nautobot/project-static/docs/models/dcim/rackgroup.html +1427 -174
- nautobot/project-static/docs/models/dcim/rackreservation.html +1427 -174
- nautobot/project-static/docs/models/dcim/rearport.html +1427 -174
- nautobot/project-static/docs/models/dcim/rearporttemplate.html +1427 -174
- nautobot/project-static/docs/models/dcim/region.html +1401 -170
- nautobot/project-static/docs/models/dcim/site.html +1401 -170
- nautobot/project-static/docs/models/dcim/virtualchassis.html +1425 -172
- nautobot/project-static/docs/models/extras/computedfield.html +1393 -194
- nautobot/project-static/docs/models/extras/configcontext.html +1465 -174
- nautobot/project-static/docs/models/extras/configcontextschema.html +1421 -168
- nautobot/project-static/docs/models/extras/customfield.html +1389 -190
- nautobot/project-static/docs/models/extras/customlink.html +1389 -190
- nautobot/project-static/docs/models/extras/dynamicgroup.html +1398 -199
- nautobot/project-static/docs/models/extras/exporttemplate.html +1389 -190
- nautobot/project-static/docs/models/extras/gitrepository.html +1393 -190
- nautobot/project-static/docs/models/extras/graphqlquery.html +1469 -171
- nautobot/project-static/docs/models/extras/imageattachment.html +1434 -181
- nautobot/project-static/docs/models/extras/job.html +1411 -157
- nautobot/project-static/docs/models/extras/jobbutton.html +1410 -207
- nautobot/project-static/docs/models/extras/jobhook.html +1397 -194
- nautobot/project-static/docs/models/extras/joblogentry.html +1408 -155
- nautobot/project-static/docs/models/extras/jobresult.html +1417 -159
- nautobot/project-static/docs/models/extras/note.html +1389 -190
- nautobot/project-static/docs/models/extras/relationship.html +1391 -192
- nautobot/project-static/docs/models/extras/role.html +1495 -198
- nautobot/project-static/docs/models/extras/secret.html +1492 -201
- nautobot/project-static/docs/models/extras/secretsgroup.html +1410 -157
- nautobot/project-static/docs/models/extras/status.html +1381 -221
- nautobot/project-static/docs/models/extras/tag.html +1389 -190
- nautobot/project-static/docs/models/extras/webhook.html +1389 -190
- nautobot/project-static/docs/models/ipam/ipaddress.html +1488 -200
- nautobot/project-static/docs/models/ipam/prefix.html +1410 -157
- nautobot/project-static/docs/models/ipam/rir.html +1410 -157
- nautobot/project-static/docs/models/ipam/routetarget.html +1410 -157
- nautobot/project-static/docs/models/ipam/service.html +1410 -157
- nautobot/project-static/docs/models/ipam/vlan.html +1410 -157
- nautobot/project-static/docs/models/ipam/vlangroup.html +1410 -157
- nautobot/project-static/docs/models/ipam/vrf.html +1410 -161
- nautobot/project-static/docs/models/tenancy/tenant.html +1412 -159
- nautobot/project-static/docs/models/tenancy/tenantgroup.html +1412 -159
- nautobot/project-static/docs/models/users/objectpermission.html +1462 -171
- nautobot/project-static/docs/models/users/token.html +1410 -157
- nautobot/project-static/docs/models/virtualization/cluster.html +1410 -157
- nautobot/project-static/docs/models/virtualization/clustergroup.html +1410 -157
- nautobot/project-static/docs/models/virtualization/clustertype.html +1410 -157
- nautobot/project-static/docs/models/virtualization/virtualmachine.html +1414 -157
- nautobot/project-static/docs/models/virtualization/vminterface.html +1410 -157
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/plugins/development.html +1916 -646
- nautobot/project-static/docs/plugins/index.html +1389 -190
- nautobot/project-static/docs/plugins/porting-from-netbox.html +1389 -190
- nautobot/project-static/docs/release-notes/index.html +1389 -190
- nautobot/project-static/docs/release-notes/version-1.0.html +1389 -190
- nautobot/project-static/docs/release-notes/version-1.1.html +1389 -190
- nautobot/project-static/docs/release-notes/version-1.2.html +1389 -190
- nautobot/project-static/docs/release-notes/version-1.3.html +1389 -190
- nautobot/project-static/docs/release-notes/version-1.4.html +1389 -190
- nautobot/project-static/docs/release-notes/version-1.5.html +2016 -397
- nautobot/project-static/docs/release-notes/version-2.0.html +1935 -287
- nautobot/project-static/docs/requirements.txt +5 -4
- nautobot/project-static/docs/rest-api/authentication.html +1389 -190
- nautobot/project-static/docs/rest-api/filtering.html +1389 -190
- nautobot/project-static/docs/rest-api/overview.html +2002 -576
- nautobot/project-static/docs/rest-api/ui-related-endpoints.html +4057 -0
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +197 -187
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guides/custom-fields.html +1390 -191
- nautobot/project-static/docs/user-guides/getting-started/creating-devices.html +1392 -193
- nautobot/project-static/docs/user-guides/getting-started/index.html +1388 -189
- nautobot/project-static/docs/user-guides/getting-started/interfaces.html +1388 -189
- nautobot/project-static/docs/user-guides/getting-started/ipam.html +1386 -187
- nautobot/project-static/docs/user-guides/getting-started/platforms.html +1448 -249
- nautobot/project-static/docs/user-guides/getting-started/regions.html +1411 -212
- nautobot/project-static/docs/user-guides/getting-started/search-bar.html +1395 -196
- nautobot/project-static/docs/user-guides/getting-started/tenants.html +1448 -249
- nautobot/project-static/docs/user-guides/getting-started/vlans-and-vlan-groups.html +1448 -249
- nautobot/project-static/docs/user-guides/git-data-source.html +1405 -206
- nautobot/project-static/docs/user-guides/graphql.html +1402 -203
- nautobot/project-static/docs/user-guides/relationships.html +1448 -249
- nautobot/project-static/docs/user-guides/s3-django-storage.html +1448 -249
- nautobot/project-static/js/forms.js +16 -9
- nautobot/project-static/js/theme.js +5 -0
- nautobot/tenancy/api/serializers.py +4 -34
- nautobot/tenancy/api/urls.py +1 -1
- nautobot/tenancy/filters/__init__.py +9 -7
- nautobot/tenancy/filters/mixins.py +3 -2
- nautobot/tenancy/forms.py +3 -36
- nautobot/tenancy/migrations/0001_initial.py +0 -1
- nautobot/tenancy/migrations/0002_auto_slug.py +0 -1
- nautobot/tenancy/migrations/0003_mptt_to_tree_queries.py +0 -1
- nautobot/tenancy/migrations/0004_change_tree_manager_on_tree_models.py +0 -1
- nautobot/tenancy/migrations/0005_rename_foreign_keys_and_related_names.py +0 -1
- nautobot/tenancy/migrations/0006_created_datetime.py +0 -1
- nautobot/tenancy/migrations/0007_remove_tenant_tenantgroup_slug.py +20 -0
- nautobot/tenancy/migrations/0008_tagsfield.py +19 -0
- nautobot/tenancy/models.py +0 -30
- nautobot/tenancy/navigation.py +6 -39
- nautobot/tenancy/tables.py +4 -4
- nautobot/tenancy/templates/tenancy/tenant.html +12 -12
- nautobot/tenancy/templates/tenancy/tenant_edit.html +0 -1
- nautobot/tenancy/templates/tenancy/tenantgroup.html +1 -1
- nautobot/tenancy/tests/test_api.py +1 -12
- nautobot/tenancy/tests/test_filters.py +20 -12
- nautobot/tenancy/tests/test_views.py +11 -29
- nautobot/tenancy/urls.py +10 -10
- nautobot/tenancy/views.py +0 -3
- nautobot/ui/.eslintignore +6 -0
- nautobot/ui/.gitignore +10 -0
- nautobot/ui/.prettierignore +9 -0
- nautobot/ui/.prettierrc +4 -0
- nautobot/ui/README.md +33 -0
- nautobot/ui/app_imports.js.j2 +7 -0
- nautobot/ui/craco.config.js +46 -0
- nautobot/ui/jsconfig-base.json +11 -0
- nautobot/ui/jsconfig.json +5 -0
- nautobot/ui/lib/nautobot-craco-alias-plugin.js +40 -0
- nautobot/ui/package-lock.json +21451 -0
- nautobot/ui/package.json +70 -0
- nautobot/ui/public/index.html +47 -0
- nautobot/ui/public/logo192.png +0 -0
- nautobot/ui/public/logo512.png +0 -0
- nautobot/ui/public/manifest.json +25 -0
- nautobot/ui/public/nautobot_logo.svg +131 -0
- nautobot/ui/public/robots.txt +3 -0
- nautobot/ui/src/App.js +71 -0
- nautobot/ui/src/components/AppFullWidthComponents.js +8 -0
- nautobot/ui/src/components/AppTab.js +40 -0
- nautobot/ui/src/components/Apps.js +60 -0
- nautobot/ui/src/components/HomeChangelogPanel.js +98 -0
- nautobot/ui/src/components/HomePanel.js +58 -0
- nautobot/ui/src/components/JobHistoryTable.js +78 -0
- nautobot/ui/src/components/Layout.js +53 -0
- nautobot/ui/src/components/LoadingWidget.js +25 -0
- nautobot/ui/src/components/Navbar.js +116 -0
- nautobot/ui/src/components/NotificationPopover.js +27 -0
- nautobot/ui/src/components/ObjectListTable.js +209 -0
- nautobot/ui/src/components/ReferenceDataTag.js +35 -0
- nautobot/ui/src/components/RouterButton.js +10 -0
- nautobot/ui/src/components/RouterLink.js +10 -0
- nautobot/ui/src/components/SidebarNav.js +147 -0
- nautobot/ui/src/components/Table.js +48 -0
- nautobot/ui/src/components/TableItem.js +71 -0
- nautobot/ui/src/components/__tests__/AppFullWidthComponents.test.js +16 -0
- nautobot/ui/src/components/__tests__/AppTab.test.js +21 -0
- nautobot/ui/src/components/__tests__/Apps.test.js +14 -0
- nautobot/ui/src/components/__tests__/Layout.test.js +33 -0
- nautobot/ui/src/components/__tests__/Table.test.js +36 -0
- nautobot/ui/src/components/__tests__/TableItem.test.js +37 -0
- nautobot/ui/src/components/__tests__/paginator.test.js +43 -0
- nautobot/ui/src/components/__tests__/paginator_form.test.js +13 -0
- nautobot/ui/src/components/pagination.js +93 -0
- nautobot/ui/src/components/paginator.js +79 -0
- nautobot/ui/src/components/paginator_form.js +43 -0
- nautobot/ui/src/components/usePagination.js +57 -0
- nautobot/ui/src/constants/apiPath.js +10 -0
- nautobot/ui/src/constants/icons.js +15 -0
- nautobot/ui/src/constants/size.js +15 -0
- nautobot/ui/src/index.js +65 -0
- nautobot/ui/src/reportWebVitals.js +15 -0
- nautobot/ui/src/router.js +77 -0
- nautobot/ui/src/utils/api.js +131 -0
- nautobot/ui/src/utils/app-import.js +15 -0
- nautobot/ui/src/utils/color.js +15 -0
- nautobot/ui/src/utils/date.js +14 -0
- nautobot/ui/src/utils/index.js +15 -0
- nautobot/ui/src/utils/navigation.js +32 -0
- nautobot/ui/src/utils/session.js +64 -0
- nautobot/ui/src/utils/store.js +242 -0
- nautobot/ui/src/utils/string.js +6 -0
- nautobot/ui/src/utils/url.js +4 -0
- nautobot/ui/src/views/Home.js +138 -0
- nautobot/ui/src/views/InstalledApps.js +80 -0
- nautobot/ui/src/views/Login.js +48 -0
- nautobot/ui/src/views/Logout.js +20 -0
- nautobot/ui/src/views/__tests__/BSCreateViewTemplate.test.js +11 -0
- nautobot/ui/src/views/__tests__/BSListViewTemplate.test.js +107 -0
- nautobot/ui/src/views/__tests__/Login.test.js +15 -0
- nautobot/ui/src/views/generic/GenericView.js +142 -0
- nautobot/ui/src/views/generic/ObjectCreate.js +96 -0
- nautobot/ui/src/views/generic/ObjectList.js +127 -0
- nautobot/ui/src/views/generic/ObjectRetrieve.js +551 -0
- nautobot/users/admin.py +1 -1
- nautobot/users/api/serializers.py +51 -61
- nautobot/users/api/urls.py +1 -1
- nautobot/users/api/views.py +53 -2
- nautobot/users/migrations/0001_initial.py +0 -1
- nautobot/users/migrations/0002_token_ordering_by_created.py +0 -1
- nautobot/users/migrations/0003_alter_user_options.py +0 -1
- nautobot/users/migrations/0004_alter_user_managers.py +0 -1
- nautobot/users/tests/test_api.py +109 -28
- nautobot/users/tests/test_filters.py +0 -4
- nautobot/users/tests/test_models.py +0 -1
- nautobot/users/views.py +0 -7
- nautobot/virtualization/api/serializers.py +18 -132
- nautobot/virtualization/api/urls.py +1 -1
- nautobot/virtualization/api/views.py +1 -22
- nautobot/virtualization/choices.py +0 -2
- nautobot/virtualization/filters.py +12 -7
- nautobot/virtualization/forms.py +21 -117
- nautobot/virtualization/migrations/0001_initial.py +0 -1
- nautobot/virtualization/migrations/0002_virtualmachine_local_context_schema.py +0 -1
- nautobot/virtualization/migrations/0003_vminterface_verbose_name.py +0 -1
- nautobot/virtualization/migrations/0004_auto_slug.py +0 -1
- nautobot/virtualization/migrations/0005_add_natural_indexing.py +0 -1
- nautobot/virtualization/migrations/0006_vminterface_status.py +0 -1
- nautobot/virtualization/migrations/0007_vminterface_status_data_migration.py +0 -1
- nautobot/virtualization/migrations/0008_vminterface_parent.py +0 -1
- nautobot/virtualization/migrations/0009_cluster_location.py +0 -1
- nautobot/virtualization/migrations/0010_vminterface_mac_address_data_migration.py +0 -1
- nautobot/virtualization/migrations/0011_alter_vminterface_mac_address.py +0 -1
- nautobot/virtualization/migrations/0012_alter_virtualmachine_role_add_new_role.py +1 -2
- nautobot/virtualization/migrations/0013_migrate_virtualmachine_role_data.py +18 -12
- nautobot/virtualization/migrations/0014_rename_virtualmachine_roles.py +0 -1
- nautobot/virtualization/migrations/0015_rename_foreignkey_fields.py +1 -2
- nautobot/virtualization/migrations/0016_remove_site_foreign_key_from_cluster_class.py +0 -1
- nautobot/virtualization/migrations/0017_created_datetime.py +0 -1
- nautobot/virtualization/migrations/0018_related_name_changes.py +1 -2
- nautobot/virtualization/migrations/0019_vminterface_ip_addresses_m2m.py +0 -1
- nautobot/virtualization/migrations/0020_remove_clustergroup_clustertype_slug.py +20 -0
- nautobot/virtualization/migrations/0021_tagsfield_and_vminterface_to_primarymodel.py +39 -0
- nautobot/virtualization/migrations/0022_vminterface_timestamps_data_migration.py +17 -0
- nautobot/virtualization/migrations/0023_ipam__namespaces.py +25 -0
- nautobot/virtualization/migrations/0024_fixup_null_statuses.py +25 -0
- nautobot/virtualization/migrations/0025_status_nonnullable.py +29 -0
- nautobot/virtualization/models.py +39 -131
- nautobot/virtualization/navigation.py +18 -99
- nautobot/virtualization/tables.py +4 -4
- nautobot/virtualization/templates/virtualization/virtualmachine.html +13 -2
- nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +6 -0
- nautobot/virtualization/tests/test_api.py +42 -52
- nautobot/virtualization/tests/test_filters.py +98 -75
- nautobot/virtualization/tests/test_models.py +36 -13
- nautobot/virtualization/tests/test_views.py +68 -73
- nautobot/virtualization/urls.py +10 -10
- nautobot/virtualization/views.py +8 -14
- {nautobot-2.0.0a2.dist-info → nautobot-2.0.0b1.dist-info}/METADATA +15 -22
- {nautobot-2.0.0a2.dist-info → nautobot-2.0.0b1.dist-info}/RECORD +987 -834
- {nautobot-2.0.0a2.dist-info → nautobot-2.0.0b1.dist-info}/WHEEL +1 -1
- nautobot/circuits/api/nested_serializers.py +0 -69
- nautobot/core/templates/plugin_template/navigation.py-tpl +0 -22
- nautobot/dcim/api/nested_serializers.py +0 -356
- nautobot/dcim/templates/dcim/device_import.html +0 -5
- nautobot/dcim/templates/dcim/device_import_child.html +0 -5
- nautobot/dcim/templates/dcim/inc/device_import_header.html +0 -4
- nautobot/extras/api/nested_serializers.py +0 -353
- nautobot/extras/migrations/0064_configcontext_data_migrations.py +0 -42
- nautobot/extras/migrations/0071_job__unique_name_data_migration.py +0 -47
- nautobot/extras/reports.py +0 -60
- nautobot/extras/scripts.py +0 -72
- nautobot/extras/tests/example_jobs/script_variables.py +0 -67
- nautobot/extras/tests/example_jobs/test_duplicate_name2.py +0 -5
- nautobot/extras/tests/example_jobs/test_fail.py +0 -16
- nautobot/extras/tests/example_jobs/test_file_upload_pass.py +0 -20
- nautobot/extras/tests/example_jobs/test_ipaddress_vars.py +0 -52
- nautobot/extras/tests/example_jobs/test_job_button_receiver.py +0 -21
- nautobot/extras/tests/example_jobs/test_job_hook_receiver.py +0 -20
- nautobot/extras/tests/example_jobs/test_location_with_custom_field.py +0 -35
- nautobot/extras/tests/example_jobs/test_log_redaction.py +0 -14
- nautobot/extras/tests/example_jobs/test_modify_db.py +0 -19
- nautobot/extras/tests/example_jobs/test_object_var_optional.py +0 -14
- nautobot/extras/tests/example_jobs/test_object_var_required.py +0 -14
- nautobot/extras/tests/example_jobs/test_object_vars.py +0 -29
- nautobot/extras/tests/example_jobs/test_pass.py +0 -19
- nautobot/extras/tests/example_jobs/test_read_only_fail.py +0 -24
- nautobot/extras/tests/example_jobs/test_read_only_no_commit_field.py +0 -10
- nautobot/extras/tests/example_jobs/test_read_only_pass.py +0 -22
- nautobot/ipam/api/nested_serializers.py +0 -143
- nautobot/project-static/docs/assets/javascripts/bundle.5a2dcb6a.min.js +0 -29
- nautobot/project-static/docs/assets/javascripts/bundle.5a2dcb6a.min.js.map +0 -8
- nautobot/project-static/docs/assets/javascripts/extra/bundle.5f09fbc3.min.js +0 -18
- nautobot/project-static/docs/assets/javascripts/extra/bundle.5f09fbc3.min.js.map +0 -8
- nautobot/project-static/docs/assets/stylesheets/extra.0d2c79a8.min.css +0 -1
- nautobot/project-static/docs/assets/stylesheets/extra.0d2c79a8.min.css.map +0 -1
- nautobot/project-static/docs/assets/stylesheets/main.975780f9.min.css +0 -1
- nautobot/project-static/docs/assets/stylesheets/main.975780f9.min.css.map +0 -1
- nautobot/project-static/docs/assets/stylesheets/palette.2505c338.min.css +0 -1
- nautobot/project-static/docs/assets/stylesheets/palette.2505c338.min.css.map +0 -1
- nautobot/tenancy/api/nested_serializers.py +0 -31
- nautobot/users/api/nested_serializers.py +0 -67
- nautobot/virtualization/api/nested_serializers.py +0 -65
- /nautobot/extras/{tests/example_jobs → test_jobs}/__init__.py +0 -0
- /nautobot/{dcim/models/sites.py → ipam/management/__init__.py} +0 -0
- {nautobot-2.0.0a2.dist-info → nautobot-2.0.0b1.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.0.0a2.dist-info → nautobot-2.0.0b1.dist-info}/entry_points.txt +0 -0
|
@@ -3,32 +3,33 @@ import logging
|
|
|
3
3
|
from django.conf import settings
|
|
4
4
|
from django.contrib.contenttypes.models import ContentType
|
|
5
5
|
from django.core.exceptions import ObjectDoesNotExist
|
|
6
|
-
from django.urls import NoReverseMatch
|
|
7
6
|
from drf_spectacular.utils import extend_schema_field
|
|
8
7
|
from rest_framework import serializers
|
|
9
|
-
from rest_framework.reverse import reverse
|
|
10
8
|
|
|
11
9
|
from nautobot.core.api import (
|
|
10
|
+
BaseModelSerializer,
|
|
12
11
|
ChoiceField,
|
|
13
12
|
ContentTypeField,
|
|
14
|
-
|
|
13
|
+
CustomFieldModelSerializerMixin,
|
|
14
|
+
NautobotModelSerializer,
|
|
15
|
+
NotesSerializerMixin,
|
|
16
|
+
RelationshipModelSerializerMixin,
|
|
15
17
|
ValidatedModelSerializer,
|
|
16
18
|
)
|
|
17
19
|
from nautobot.core.api.exceptions import SerializerNotFound
|
|
18
|
-
from nautobot.core.api.
|
|
19
|
-
from nautobot.core.api.
|
|
20
|
-
|
|
20
|
+
from nautobot.core.api.serializers import PolymorphicProxySerializer
|
|
21
|
+
from nautobot.core.api.utils import (
|
|
22
|
+
get_nested_serializer_depth,
|
|
23
|
+
get_serializers_for_models,
|
|
24
|
+
return_nested_serializer_data_based_on_depth,
|
|
25
|
+
)
|
|
21
26
|
from nautobot.core.models.utils import get_all_concrete_models
|
|
22
|
-
from nautobot.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
NestedDeviceTypeSerializer,
|
|
27
|
-
NestedLocationSerializer,
|
|
28
|
-
NestedPlatformSerializer,
|
|
29
|
-
NestedRackSerializer,
|
|
27
|
+
from nautobot.dcim.api.serializers import (
|
|
28
|
+
DeviceSerializer,
|
|
29
|
+
LocationSerializer,
|
|
30
|
+
RackSerializer,
|
|
30
31
|
)
|
|
31
|
-
from nautobot.
|
|
32
|
+
from nautobot.extras import choices, models
|
|
32
33
|
from nautobot.extras.choices import (
|
|
33
34
|
CustomFieldFilterLogicChoices,
|
|
34
35
|
CustomFieldTypeChoices,
|
|
@@ -36,6 +37,9 @@ from nautobot.extras.choices import (
|
|
|
36
37
|
JobResultStatusChoices,
|
|
37
38
|
ObjectChangeActionChoices,
|
|
38
39
|
)
|
|
40
|
+
from nautobot.extras.api.mixins import (
|
|
41
|
+
TaggedModelSerializerMixin,
|
|
42
|
+
)
|
|
39
43
|
from nautobot.extras.datasources import get_datasource_content_choices
|
|
40
44
|
from nautobot.extras.models import (
|
|
41
45
|
ComputedField,
|
|
@@ -70,54 +74,8 @@ from nautobot.extras.models import (
|
|
|
70
74
|
)
|
|
71
75
|
from nautobot.extras.models.mixins import NotesMixin
|
|
72
76
|
from nautobot.extras.utils import ChangeLoggedModelsQuery, FeatureQuery, RoleModelsQuery, TaggableClassesQuery
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
NestedTenantGroupSerializer,
|
|
76
|
-
)
|
|
77
|
-
from nautobot.tenancy.models import Tenant, TenantGroup
|
|
78
|
-
from nautobot.users.api.nested_serializers import NestedUserSerializer
|
|
79
|
-
from nautobot.virtualization.api.nested_serializers import (
|
|
80
|
-
NestedClusterGroupSerializer,
|
|
81
|
-
NestedClusterSerializer,
|
|
82
|
-
)
|
|
83
|
-
from nautobot.virtualization.models import Cluster, ClusterGroup
|
|
84
|
-
|
|
85
|
-
from .customfields import CustomFieldModelSerializerMixin
|
|
86
|
-
from .fields import MultipleChoiceJSONField, RoleSerializerField, StatusSerializerField
|
|
87
|
-
from .relationships import RelationshipModelSerializerMixin
|
|
88
|
-
|
|
89
|
-
# Not all of these variable(s) are not actually used anywhere in this file, but required for the
|
|
90
|
-
# automagically replacing a Serializer with its corresponding NestedSerializer.
|
|
91
|
-
from .nested_serializers import ( # noqa: F401
|
|
92
|
-
NestedComputedFieldSerializer,
|
|
93
|
-
NestedConfigContextSchemaSerializer,
|
|
94
|
-
NestedConfigContextSerializer,
|
|
95
|
-
NestedCustomFieldChoiceSerializer,
|
|
96
|
-
NestedCustomFieldSerializer,
|
|
97
|
-
NestedCustomLinkSerializer,
|
|
98
|
-
NestedDynamicGroupSerializer,
|
|
99
|
-
NestedDynamicGroupMembershipSerializer,
|
|
100
|
-
NestedExportTemplateSerializer,
|
|
101
|
-
NestedGitRepositorySerializer,
|
|
102
|
-
NestedGraphQLQuerySerializer,
|
|
103
|
-
NestedImageAttachmentSerializer,
|
|
104
|
-
NestedJobButtonSerializer,
|
|
105
|
-
NestedJobHookSerializer,
|
|
106
|
-
NestedJobSerializer,
|
|
107
|
-
NestedJobResultSerializer,
|
|
108
|
-
NestedNoteSerializer,
|
|
109
|
-
NestedRelationshipAssociationSerializer,
|
|
110
|
-
NestedRelationshipSerializer,
|
|
111
|
-
NestedRoleSerializer,
|
|
112
|
-
NestedScheduledJobSerializer,
|
|
113
|
-
NestedScheduledJobCreationSerializer,
|
|
114
|
-
NestedSecretSerializer,
|
|
115
|
-
NestedSecretsGroupSerializer,
|
|
116
|
-
NestedSecretsGroupAssociationSerializer,
|
|
117
|
-
NestedStatusSerializer,
|
|
118
|
-
NestedTagSerializer,
|
|
119
|
-
NestedWebhookSerializer,
|
|
120
|
-
)
|
|
77
|
+
|
|
78
|
+
from .fields import MultipleChoiceJSONField
|
|
121
79
|
|
|
122
80
|
#
|
|
123
81
|
# Mixins and Base Classes
|
|
@@ -126,130 +84,19 @@ from .nested_serializers import ( # noqa: F401
|
|
|
126
84
|
logger = logging.getLogger(__name__)
|
|
127
85
|
|
|
128
86
|
|
|
129
|
-
class NotesSerializerMixin(BaseModelSerializer):
|
|
130
|
-
"""Extend Serializer with a `notes` field."""
|
|
131
|
-
|
|
132
|
-
notes_url = serializers.SerializerMethodField()
|
|
133
|
-
|
|
134
|
-
def get_field_names(self, declared_fields, info):
|
|
135
|
-
"""Ensure that fields includes "notes_url" field if applicable."""
|
|
136
|
-
fields = list(super().get_field_names(declared_fields, info))
|
|
137
|
-
if hasattr(self.Meta.model, "notes"):
|
|
138
|
-
self.extend_field_names(fields, "notes_url")
|
|
139
|
-
return fields
|
|
140
|
-
|
|
141
|
-
@extend_schema_field(serializers.URLField())
|
|
142
|
-
def get_notes_url(self, instance):
|
|
143
|
-
try:
|
|
144
|
-
notes_url = get_route_for_model(instance, "notes", api=True)
|
|
145
|
-
return reverse(notes_url, args=[instance.id], request=self.context["request"])
|
|
146
|
-
except NoReverseMatch:
|
|
147
|
-
model_name = type(instance).__name__
|
|
148
|
-
logger.warning(
|
|
149
|
-
(
|
|
150
|
-
f"Notes feature is not available for model {model_name}. "
|
|
151
|
-
"Please make sure to: "
|
|
152
|
-
f"1. Include NotesMixin from nautobot.extras.model.mixins in the {model_name} class definition "
|
|
153
|
-
f"2. Include NotesViewSetMixin from nautobot.extras.api.mixins in the {model_name}ViewSet "
|
|
154
|
-
"before including NotesSerializerMixin in the model serializer"
|
|
155
|
-
)
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
return None
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
class NautobotModelSerializer(
|
|
162
|
-
RelationshipModelSerializerMixin, CustomFieldModelSerializerMixin, NotesSerializerMixin, ValidatedModelSerializer
|
|
163
|
-
):
|
|
164
|
-
"""Base class to use for serializers based on OrganizationalModel or PrimaryModel.
|
|
165
|
-
|
|
166
|
-
Can also be used for models derived from BaseModel, so long as they support custom fields and relationships.
|
|
167
|
-
"""
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
class StatusModelSerializerMixin(BaseModelSerializer):
|
|
171
|
-
"""Mixin to add `status` choice field to model serializers."""
|
|
172
|
-
|
|
173
|
-
status = StatusSerializerField(required=True)
|
|
174
|
-
|
|
175
|
-
def get_field_names(self, declared_fields, info):
|
|
176
|
-
"""Ensure that "status" field is always present."""
|
|
177
|
-
fields = list(super().get_field_names(declared_fields, info))
|
|
178
|
-
self.extend_field_names(fields, "status")
|
|
179
|
-
return fields
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
class TagSerializerField(LimitQuerysetChoicesSerializerMixin, NestedTagSerializer):
|
|
183
|
-
"""NestedSerializer field for `Tag` object fields."""
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
class TaggedModelSerializerMixin(BaseModelSerializer):
|
|
187
|
-
tags = TagSerializerField(many=True, required=False)
|
|
188
|
-
|
|
189
|
-
def get_field_names(self, declared_fields, info):
|
|
190
|
-
"""Ensure that 'tags' field is always present."""
|
|
191
|
-
fields = list(super().get_field_names(declared_fields, info))
|
|
192
|
-
self.extend_field_names(fields, "tags")
|
|
193
|
-
return fields
|
|
194
|
-
|
|
195
|
-
def create(self, validated_data):
|
|
196
|
-
tags = validated_data.pop("tags", None)
|
|
197
|
-
instance = super().create(validated_data)
|
|
198
|
-
|
|
199
|
-
if tags is not None:
|
|
200
|
-
return self._save_tags(instance, tags)
|
|
201
|
-
return instance
|
|
202
|
-
|
|
203
|
-
def update(self, instance, validated_data):
|
|
204
|
-
tags = validated_data.pop("tags", None)
|
|
205
|
-
|
|
206
|
-
# Cache tags on instance for change logging
|
|
207
|
-
instance._tags = tags or []
|
|
208
|
-
|
|
209
|
-
instance = super().update(instance, validated_data)
|
|
210
|
-
|
|
211
|
-
if tags is not None:
|
|
212
|
-
return self._save_tags(instance, tags)
|
|
213
|
-
return instance
|
|
214
|
-
|
|
215
|
-
def _save_tags(self, instance, tags):
|
|
216
|
-
if tags:
|
|
217
|
-
instance.tags.set([t.name for t in tags])
|
|
218
|
-
else:
|
|
219
|
-
instance.tags.clear()
|
|
220
|
-
|
|
221
|
-
return instance
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
# TODO: remove in 2.2
|
|
225
|
-
@class_deprecated_in_favor_of(TaggedModelSerializerMixin)
|
|
226
|
-
class TaggedObjectSerializer(TaggedModelSerializerMixin):
|
|
227
|
-
pass
|
|
228
|
-
|
|
229
|
-
|
|
230
87
|
#
|
|
231
88
|
# Computed Fields
|
|
232
89
|
#
|
|
233
90
|
|
|
234
91
|
|
|
235
92
|
class ComputedFieldSerializer(ValidatedModelSerializer, NotesSerializerMixin):
|
|
236
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:computedfield-detail")
|
|
237
93
|
content_type = ContentTypeField(
|
|
238
94
|
queryset=ContentType.objects.filter(FeatureQuery("custom_fields").get_query()).order_by("app_label", "model"),
|
|
239
95
|
)
|
|
240
96
|
|
|
241
97
|
class Meta:
|
|
242
98
|
model = ComputedField
|
|
243
|
-
fields =
|
|
244
|
-
"url",
|
|
245
|
-
"slug",
|
|
246
|
-
"label",
|
|
247
|
-
"description",
|
|
248
|
-
"content_type",
|
|
249
|
-
"template",
|
|
250
|
-
"fallback_value",
|
|
251
|
-
"weight",
|
|
252
|
-
)
|
|
99
|
+
fields = "__all__"
|
|
253
100
|
|
|
254
101
|
|
|
255
102
|
#
|
|
@@ -257,8 +104,7 @@ class ComputedFieldSerializer(ValidatedModelSerializer, NotesSerializerMixin):
|
|
|
257
104
|
#
|
|
258
105
|
|
|
259
106
|
|
|
260
|
-
class ConfigContextSerializer(ValidatedModelSerializer, NotesSerializerMixin):
|
|
261
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:configcontext-detail")
|
|
107
|
+
class ConfigContextSerializer(ValidatedModelSerializer, TaggedModelSerializerMixin, NotesSerializerMixin):
|
|
262
108
|
owner_content_type = ContentTypeField(
|
|
263
109
|
queryset=ContentType.objects.filter(FeatureQuery("config_context_owners").get_query()),
|
|
264
110
|
required=False,
|
|
@@ -266,63 +112,6 @@ class ConfigContextSerializer(ValidatedModelSerializer, NotesSerializerMixin):
|
|
|
266
112
|
default=None,
|
|
267
113
|
)
|
|
268
114
|
owner = serializers.SerializerMethodField(read_only=True)
|
|
269
|
-
config_context_schema = NestedConfigContextSchemaSerializer(required=False, allow_null=True)
|
|
270
|
-
locations = SerializedPKRelatedField(
|
|
271
|
-
queryset=Location.objects.all(),
|
|
272
|
-
serializer=NestedLocationSerializer,
|
|
273
|
-
required=False,
|
|
274
|
-
many=True,
|
|
275
|
-
)
|
|
276
|
-
roles = SerializedPKRelatedField(
|
|
277
|
-
queryset=Role.objects.all(),
|
|
278
|
-
serializer=NestedRoleSerializer,
|
|
279
|
-
required=False,
|
|
280
|
-
many=True,
|
|
281
|
-
)
|
|
282
|
-
device_types = SerializedPKRelatedField(
|
|
283
|
-
queryset=DeviceType.objects.all(),
|
|
284
|
-
serializer=NestedDeviceTypeSerializer,
|
|
285
|
-
required=False,
|
|
286
|
-
many=True,
|
|
287
|
-
)
|
|
288
|
-
platforms = SerializedPKRelatedField(
|
|
289
|
-
queryset=Platform.objects.all(),
|
|
290
|
-
serializer=NestedPlatformSerializer,
|
|
291
|
-
required=False,
|
|
292
|
-
many=True,
|
|
293
|
-
)
|
|
294
|
-
cluster_groups = SerializedPKRelatedField(
|
|
295
|
-
queryset=ClusterGroup.objects.all(),
|
|
296
|
-
serializer=NestedClusterGroupSerializer,
|
|
297
|
-
required=False,
|
|
298
|
-
many=True,
|
|
299
|
-
)
|
|
300
|
-
clusters = SerializedPKRelatedField(
|
|
301
|
-
queryset=Cluster.objects.all(),
|
|
302
|
-
serializer=NestedClusterSerializer,
|
|
303
|
-
required=False,
|
|
304
|
-
many=True,
|
|
305
|
-
)
|
|
306
|
-
tenant_groups = SerializedPKRelatedField(
|
|
307
|
-
queryset=TenantGroup.objects.all(),
|
|
308
|
-
serializer=NestedTenantGroupSerializer,
|
|
309
|
-
required=False,
|
|
310
|
-
many=True,
|
|
311
|
-
)
|
|
312
|
-
tenants = SerializedPKRelatedField(
|
|
313
|
-
queryset=Tenant.objects.all(),
|
|
314
|
-
serializer=NestedTenantSerializer,
|
|
315
|
-
required=False,
|
|
316
|
-
many=True,
|
|
317
|
-
)
|
|
318
|
-
tags = serializers.SlugRelatedField(queryset=Tag.objects.all(), slug_field="slug", required=False, many=True)
|
|
319
|
-
|
|
320
|
-
dynamic_groups = SerializedPKRelatedField(
|
|
321
|
-
queryset=DynamicGroup.objects.all(),
|
|
322
|
-
serializer=NestedDynamicGroupSerializer,
|
|
323
|
-
required=False,
|
|
324
|
-
many=True,
|
|
325
|
-
)
|
|
326
115
|
|
|
327
116
|
# Conditional enablement of dynamic groups filtering
|
|
328
117
|
def __init__(self, *args, **kwargs):
|
|
@@ -333,45 +122,21 @@ class ConfigContextSerializer(ValidatedModelSerializer, NotesSerializerMixin):
|
|
|
333
122
|
|
|
334
123
|
class Meta:
|
|
335
124
|
model = ConfigContext
|
|
336
|
-
fields =
|
|
337
|
-
"url",
|
|
338
|
-
"name",
|
|
339
|
-
"owner_content_type",
|
|
340
|
-
"owner_object_id",
|
|
341
|
-
"owner",
|
|
342
|
-
"weight",
|
|
343
|
-
"description",
|
|
344
|
-
"config_context_schema",
|
|
345
|
-
"is_active",
|
|
346
|
-
"locations",
|
|
347
|
-
"roles",
|
|
348
|
-
"device_types",
|
|
349
|
-
"platforms",
|
|
350
|
-
"cluster_groups",
|
|
351
|
-
"clusters",
|
|
352
|
-
"tenant_groups",
|
|
353
|
-
"tenants",
|
|
354
|
-
"tags",
|
|
355
|
-
"dynamic_groups",
|
|
356
|
-
"data",
|
|
357
|
-
]
|
|
125
|
+
fields = "__all__"
|
|
358
126
|
|
|
359
127
|
@extend_schema_field(
|
|
360
128
|
PolymorphicProxySerializer(
|
|
361
129
|
component_name="ConfigContextOwner",
|
|
362
130
|
resource_type_field_name="object_type",
|
|
363
|
-
serializers=lambda: get_serializers_for_models(
|
|
364
|
-
FeatureQuery("config_context_owners").list_subclasses(), prefix="Nested"
|
|
365
|
-
),
|
|
131
|
+
serializers=lambda: get_serializers_for_models(FeatureQuery("config_context_owners").list_subclasses()),
|
|
366
132
|
allow_null=True,
|
|
367
133
|
)
|
|
368
134
|
)
|
|
369
135
|
def get_owner(self, obj):
|
|
370
136
|
if obj.owner is None:
|
|
371
137
|
return None
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
return serializer(obj.owner, context=context).data
|
|
138
|
+
depth = get_nested_serializer_depth(self)
|
|
139
|
+
return return_nested_serializer_data_based_on_depth(self, depth, obj, obj.owner, "owner")
|
|
375
140
|
|
|
376
141
|
|
|
377
142
|
#
|
|
@@ -380,7 +145,6 @@ class ConfigContextSerializer(ValidatedModelSerializer, NotesSerializerMixin):
|
|
|
380
145
|
|
|
381
146
|
|
|
382
147
|
class ConfigContextSchemaSerializer(NautobotModelSerializer):
|
|
383
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:configcontextschema-detail")
|
|
384
148
|
owner_content_type = ContentTypeField(
|
|
385
149
|
queryset=ContentType.objects.filter(FeatureQuery("config_context_owners").get_query()),
|
|
386
150
|
required=False,
|
|
@@ -391,33 +155,21 @@ class ConfigContextSchemaSerializer(NautobotModelSerializer):
|
|
|
391
155
|
|
|
392
156
|
class Meta:
|
|
393
157
|
model = ConfigContextSchema
|
|
394
|
-
fields =
|
|
395
|
-
"url",
|
|
396
|
-
"name",
|
|
397
|
-
"slug",
|
|
398
|
-
"owner_content_type",
|
|
399
|
-
"owner_object_id",
|
|
400
|
-
"owner",
|
|
401
|
-
"description",
|
|
402
|
-
"data_schema",
|
|
403
|
-
]
|
|
158
|
+
fields = "__all__"
|
|
404
159
|
|
|
405
160
|
@extend_schema_field(
|
|
406
161
|
PolymorphicProxySerializer(
|
|
407
162
|
component_name="ConfigContextSchemaOwner",
|
|
408
163
|
resource_type_field_name="object_type",
|
|
409
|
-
serializers=lambda: get_serializers_for_models(
|
|
410
|
-
FeatureQuery("config_context_owners").list_subclasses(), prefix="Nested"
|
|
411
|
-
),
|
|
164
|
+
serializers=lambda: get_serializers_for_models(FeatureQuery("config_context_owners").list_subclasses()),
|
|
412
165
|
allow_null=True,
|
|
413
166
|
)
|
|
414
167
|
)
|
|
415
168
|
def get_owner(self, obj):
|
|
416
169
|
if obj.owner is None:
|
|
417
170
|
return None
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
return serializer(obj.owner, context=context).data
|
|
171
|
+
depth = get_nested_serializer_depth(self)
|
|
172
|
+
return return_nested_serializer_data_based_on_depth(self, depth, obj, obj.owner, "owner")
|
|
421
173
|
|
|
422
174
|
|
|
423
175
|
#
|
|
@@ -431,7 +183,7 @@ class ContentTypeSerializer(BaseModelSerializer):
|
|
|
431
183
|
|
|
432
184
|
class Meta:
|
|
433
185
|
model = ContentType
|
|
434
|
-
fields =
|
|
186
|
+
fields = "__all__"
|
|
435
187
|
|
|
436
188
|
@extend_schema_field(serializers.CharField)
|
|
437
189
|
def get_display(self, obj):
|
|
@@ -444,7 +196,6 @@ class ContentTypeSerializer(BaseModelSerializer):
|
|
|
444
196
|
|
|
445
197
|
|
|
446
198
|
class CustomFieldSerializer(ValidatedModelSerializer, NotesSerializerMixin):
|
|
447
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:customfield-detail")
|
|
448
199
|
content_types = ContentTypeField(
|
|
449
200
|
queryset=ContentType.objects.filter(FeatureQuery("custom_fields").get_query()),
|
|
450
201
|
many=True,
|
|
@@ -455,30 +206,13 @@ class CustomFieldSerializer(ValidatedModelSerializer, NotesSerializerMixin):
|
|
|
455
206
|
|
|
456
207
|
class Meta:
|
|
457
208
|
model = CustomField
|
|
458
|
-
fields =
|
|
459
|
-
"url",
|
|
460
|
-
"content_types",
|
|
461
|
-
"type",
|
|
462
|
-
"label",
|
|
463
|
-
"key",
|
|
464
|
-
"description",
|
|
465
|
-
"required",
|
|
466
|
-
"filter_logic",
|
|
467
|
-
"default",
|
|
468
|
-
"weight",
|
|
469
|
-
"validation_minimum",
|
|
470
|
-
"validation_maximum",
|
|
471
|
-
"validation_regex",
|
|
472
|
-
]
|
|
209
|
+
fields = "__all__"
|
|
473
210
|
|
|
474
211
|
|
|
475
212
|
class CustomFieldChoiceSerializer(ValidatedModelSerializer):
|
|
476
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:customfieldchoice-detail")
|
|
477
|
-
custom_field = NestedCustomFieldSerializer()
|
|
478
|
-
|
|
479
213
|
class Meta:
|
|
480
214
|
model = CustomFieldChoice
|
|
481
|
-
fields =
|
|
215
|
+
fields = "__all__"
|
|
482
216
|
|
|
483
217
|
|
|
484
218
|
#
|
|
@@ -487,24 +221,13 @@ class CustomFieldChoiceSerializer(ValidatedModelSerializer):
|
|
|
487
221
|
|
|
488
222
|
|
|
489
223
|
class CustomLinkSerializer(ValidatedModelSerializer, NotesSerializerMixin):
|
|
490
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:customlink-detail")
|
|
491
224
|
content_type = ContentTypeField(
|
|
492
225
|
queryset=ContentType.objects.filter(FeatureQuery("custom_links").get_query()).order_by("app_label", "model"),
|
|
493
226
|
)
|
|
494
227
|
|
|
495
228
|
class Meta:
|
|
496
229
|
model = CustomLink
|
|
497
|
-
fields =
|
|
498
|
-
"url",
|
|
499
|
-
"target_url",
|
|
500
|
-
"name",
|
|
501
|
-
"content_type",
|
|
502
|
-
"text",
|
|
503
|
-
"weight",
|
|
504
|
-
"group_name",
|
|
505
|
-
"button_class",
|
|
506
|
-
"new_window",
|
|
507
|
-
)
|
|
230
|
+
fields = "__all__"
|
|
508
231
|
|
|
509
232
|
|
|
510
233
|
#
|
|
@@ -512,37 +235,24 @@ class CustomLinkSerializer(ValidatedModelSerializer, NotesSerializerMixin):
|
|
|
512
235
|
#
|
|
513
236
|
|
|
514
237
|
|
|
238
|
+
class DynamicGroupMembershipSerializer(ValidatedModelSerializer):
|
|
239
|
+
class Meta:
|
|
240
|
+
model = DynamicGroupMembership
|
|
241
|
+
fields = "__all__"
|
|
242
|
+
|
|
243
|
+
|
|
515
244
|
class DynamicGroupSerializer(NautobotModelSerializer):
|
|
516
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:dynamicgroup-detail")
|
|
517
245
|
content_type = ContentTypeField(
|
|
518
246
|
queryset=ContentType.objects.filter(FeatureQuery("dynamic_groups").get_query()).order_by("app_label", "model"),
|
|
519
247
|
)
|
|
520
|
-
# Read-only because m2m is hard. Easier to just create # `DynamicGroupMemberships` explicitly
|
|
521
|
-
# using their own endpoint at /api/extras/dynamic-group-memberships/.
|
|
522
|
-
children = NestedDynamicGroupMembershipSerializer(source="dynamic_group_memberships", read_only=True, many=True)
|
|
523
248
|
|
|
524
249
|
class Meta:
|
|
525
250
|
model = DynamicGroup
|
|
526
|
-
fields =
|
|
527
|
-
|
|
528
|
-
"
|
|
529
|
-
"
|
|
530
|
-
|
|
531
|
-
"content_type",
|
|
532
|
-
"filter",
|
|
533
|
-
"children",
|
|
534
|
-
]
|
|
535
|
-
extra_kwargs = {"filter": {"read_only": False}}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
class DynamicGroupMembershipSerializer(ValidatedModelSerializer):
|
|
539
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:dynamicgroupmembership-detail")
|
|
540
|
-
group = NestedDynamicGroupSerializer()
|
|
541
|
-
parent_group = NestedDynamicGroupSerializer()
|
|
542
|
-
|
|
543
|
-
class Meta:
|
|
544
|
-
model = DynamicGroupMembership
|
|
545
|
-
fields = ["url", "group", "parent_group", "operator", "weight"]
|
|
251
|
+
fields = "__all__"
|
|
252
|
+
extra_kwargs = {
|
|
253
|
+
"children": {"source": "dynamic_group_memberships", "read_only": True},
|
|
254
|
+
"filter": {"read_only": False},
|
|
255
|
+
}
|
|
546
256
|
|
|
547
257
|
|
|
548
258
|
#
|
|
@@ -552,7 +262,6 @@ class DynamicGroupMembershipSerializer(ValidatedModelSerializer):
|
|
|
552
262
|
|
|
553
263
|
# TODO: export-templates don't support custom-fields, is this omission intentional?
|
|
554
264
|
class ExportTemplateSerializer(RelationshipModelSerializerMixin, ValidatedModelSerializer, NotesSerializerMixin):
|
|
555
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:exporttemplate-detail")
|
|
556
265
|
content_type = ContentTypeField(
|
|
557
266
|
queryset=ContentType.objects.filter(FeatureQuery("export_templates").get_query()),
|
|
558
267
|
)
|
|
@@ -566,35 +275,21 @@ class ExportTemplateSerializer(RelationshipModelSerializerMixin, ValidatedModelS
|
|
|
566
275
|
|
|
567
276
|
class Meta:
|
|
568
277
|
model = ExportTemplate
|
|
569
|
-
fields =
|
|
570
|
-
"url",
|
|
571
|
-
"content_type",
|
|
572
|
-
"owner_content_type",
|
|
573
|
-
"owner_object_id",
|
|
574
|
-
"owner",
|
|
575
|
-
"name",
|
|
576
|
-
"description",
|
|
577
|
-
"template_code",
|
|
578
|
-
"mime_type",
|
|
579
|
-
"file_extension",
|
|
580
|
-
]
|
|
278
|
+
fields = "__all__"
|
|
581
279
|
|
|
582
280
|
@extend_schema_field(
|
|
583
281
|
PolymorphicProxySerializer(
|
|
584
282
|
component_name="ExportTemplateOwner",
|
|
585
283
|
resource_type_field_name="object_type",
|
|
586
|
-
serializers=lambda: get_serializers_for_models(
|
|
587
|
-
FeatureQuery("export_template_owners").list_subclasses(), prefix="Nested"
|
|
588
|
-
),
|
|
284
|
+
serializers=lambda: get_serializers_for_models(FeatureQuery("export_template_owners").list_subclasses()),
|
|
589
285
|
allow_null=True,
|
|
590
286
|
)
|
|
591
287
|
)
|
|
592
288
|
def get_owner(self, obj):
|
|
593
289
|
if obj.owner is None:
|
|
594
290
|
return None
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
return serializer(obj.owner, context=context).data
|
|
291
|
+
depth = get_nested_serializer_depth(self)
|
|
292
|
+
return return_nested_serializer_data_based_on_depth(self, depth, obj, obj.owner, "owner")
|
|
598
293
|
|
|
599
294
|
|
|
600
295
|
#
|
|
@@ -605,10 +300,6 @@ class ExportTemplateSerializer(RelationshipModelSerializerMixin, ValidatedModelS
|
|
|
605
300
|
class GitRepositorySerializer(NautobotModelSerializer):
|
|
606
301
|
"""Git repositories defined as a data source."""
|
|
607
302
|
|
|
608
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:gitrepository-detail")
|
|
609
|
-
|
|
610
|
-
secrets_group = NestedSecretsGroupSerializer(required=False, allow_null=True)
|
|
611
|
-
|
|
612
303
|
provided_contents = MultipleChoiceJSONField(
|
|
613
304
|
choices=lambda: get_datasource_content_choices("extras.gitrepository"),
|
|
614
305
|
allow_blank=True,
|
|
@@ -617,23 +308,7 @@ class GitRepositorySerializer(NautobotModelSerializer):
|
|
|
617
308
|
|
|
618
309
|
class Meta:
|
|
619
310
|
model = GitRepository
|
|
620
|
-
fields =
|
|
621
|
-
"url",
|
|
622
|
-
"name",
|
|
623
|
-
"slug",
|
|
624
|
-
"remote_url",
|
|
625
|
-
"branch",
|
|
626
|
-
"secrets_group",
|
|
627
|
-
"current_head",
|
|
628
|
-
"provided_contents",
|
|
629
|
-
]
|
|
630
|
-
|
|
631
|
-
def validate(self, data):
|
|
632
|
-
"""
|
|
633
|
-
Add the originating Request as a parameter to be passed when creating/updating a GitRepository.
|
|
634
|
-
"""
|
|
635
|
-
data["request"] = self.context["request"]
|
|
636
|
-
return super().validate(data)
|
|
311
|
+
fields = "__all__"
|
|
637
312
|
|
|
638
313
|
|
|
639
314
|
#
|
|
@@ -642,18 +317,11 @@ class GitRepositorySerializer(NautobotModelSerializer):
|
|
|
642
317
|
|
|
643
318
|
|
|
644
319
|
class GraphQLQuerySerializer(ValidatedModelSerializer, NotesSerializerMixin):
|
|
645
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:graphqlquery-detail")
|
|
646
320
|
variables = serializers.DictField(required=False, allow_null=True, default={})
|
|
647
321
|
|
|
648
322
|
class Meta:
|
|
649
323
|
model = GraphQLQuery
|
|
650
|
-
fields =
|
|
651
|
-
"url",
|
|
652
|
-
"name",
|
|
653
|
-
"slug",
|
|
654
|
-
"query",
|
|
655
|
-
"variables",
|
|
656
|
-
)
|
|
324
|
+
fields = "__all__"
|
|
657
325
|
|
|
658
326
|
|
|
659
327
|
class GraphQLQueryInputSerializer(serializers.Serializer):
|
|
@@ -670,23 +338,11 @@ class GraphQLQueryOutputSerializer(serializers.Serializer):
|
|
|
670
338
|
|
|
671
339
|
|
|
672
340
|
class ImageAttachmentSerializer(ValidatedModelSerializer):
|
|
673
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:imageattachment-detail")
|
|
674
341
|
content_type = ContentTypeField(queryset=ContentType.objects.all())
|
|
675
|
-
parent = serializers.SerializerMethodField(read_only=True)
|
|
676
342
|
|
|
677
343
|
class Meta:
|
|
678
344
|
model = ImageAttachment
|
|
679
|
-
fields =
|
|
680
|
-
"url",
|
|
681
|
-
"content_type",
|
|
682
|
-
"object_id",
|
|
683
|
-
"parent",
|
|
684
|
-
"name",
|
|
685
|
-
"image",
|
|
686
|
-
"image_height",
|
|
687
|
-
"image_width",
|
|
688
|
-
"created",
|
|
689
|
-
]
|
|
345
|
+
fields = "__all__"
|
|
690
346
|
|
|
691
347
|
def validate(self, data):
|
|
692
348
|
# Validate that the parent object exists
|
|
@@ -705,15 +361,15 @@ class ImageAttachmentSerializer(ValidatedModelSerializer):
|
|
|
705
361
|
component_name="ImageAttachmentParent",
|
|
706
362
|
resource_type_field_name="object_type",
|
|
707
363
|
serializers=[
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
364
|
+
DeviceSerializer,
|
|
365
|
+
LocationSerializer,
|
|
366
|
+
RackSerializer,
|
|
711
367
|
],
|
|
712
368
|
)
|
|
713
369
|
)
|
|
714
370
|
def get_parent(self, obj):
|
|
715
|
-
|
|
716
|
-
return
|
|
371
|
+
depth = get_nested_serializer_depth(self)
|
|
372
|
+
return return_nested_serializer_data_based_on_depth(self, depth, obj, obj.parent, "parent")
|
|
717
373
|
|
|
718
374
|
|
|
719
375
|
#
|
|
@@ -722,44 +378,9 @@ class ImageAttachmentSerializer(ValidatedModelSerializer):
|
|
|
722
378
|
|
|
723
379
|
|
|
724
380
|
class JobSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
|
|
725
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:job-detail")
|
|
726
|
-
|
|
727
381
|
class Meta:
|
|
728
382
|
model = Job
|
|
729
|
-
fields =
|
|
730
|
-
"url",
|
|
731
|
-
"source",
|
|
732
|
-
"module_name",
|
|
733
|
-
"job_class_name",
|
|
734
|
-
"grouping",
|
|
735
|
-
"grouping_override",
|
|
736
|
-
"name",
|
|
737
|
-
"name_override",
|
|
738
|
-
"slug",
|
|
739
|
-
"description",
|
|
740
|
-
"description_override",
|
|
741
|
-
"installed",
|
|
742
|
-
"enabled",
|
|
743
|
-
"is_job_hook_receiver",
|
|
744
|
-
"is_job_button_receiver",
|
|
745
|
-
"has_sensitive_variables",
|
|
746
|
-
"has_sensitive_variables_override",
|
|
747
|
-
"approval_required",
|
|
748
|
-
"approval_required_override",
|
|
749
|
-
"commit_default",
|
|
750
|
-
"commit_default_override",
|
|
751
|
-
"hidden",
|
|
752
|
-
"hidden_override",
|
|
753
|
-
"read_only",
|
|
754
|
-
"read_only_override",
|
|
755
|
-
"soft_time_limit",
|
|
756
|
-
"soft_time_limit_override",
|
|
757
|
-
"time_limit",
|
|
758
|
-
"time_limit_override",
|
|
759
|
-
"task_queues",
|
|
760
|
-
"task_queues_override",
|
|
761
|
-
"tags",
|
|
762
|
-
]
|
|
383
|
+
fields = "__all__"
|
|
763
384
|
|
|
764
385
|
def validate(self, data):
|
|
765
386
|
# note no validation for on creation of jobs because we do not support user creation of Job records via API
|
|
@@ -790,7 +411,6 @@ class JobVariableSerializer(serializers.Serializer):
|
|
|
790
411
|
help_text = serializers.CharField(read_only=True, required=False)
|
|
791
412
|
default = serializers.JSONField(read_only=True, required=False)
|
|
792
413
|
required = serializers.BooleanField(read_only=True, required=False)
|
|
793
|
-
|
|
794
414
|
min_length = serializers.IntegerField(read_only=True, required=False)
|
|
795
415
|
max_length = serializers.IntegerField(read_only=True, required=False)
|
|
796
416
|
min_value = serializers.IntegerField(read_only=True, required=False)
|
|
@@ -799,11 +419,17 @@ class JobVariableSerializer(serializers.Serializer):
|
|
|
799
419
|
model = serializers.CharField(read_only=True, required=False)
|
|
800
420
|
|
|
801
421
|
|
|
802
|
-
|
|
803
|
-
|
|
422
|
+
#
|
|
423
|
+
# Scheduled Jobs
|
|
424
|
+
#
|
|
425
|
+
|
|
804
426
|
|
|
805
|
-
|
|
806
|
-
|
|
427
|
+
class ScheduledJobSerializer(BaseModelSerializer):
|
|
428
|
+
# start_time = serializers.DateTimeField(format=None, required=False)
|
|
429
|
+
|
|
430
|
+
class Meta:
|
|
431
|
+
model = ScheduledJob
|
|
432
|
+
fields = "__all__"
|
|
807
433
|
|
|
808
434
|
|
|
809
435
|
#
|
|
@@ -812,63 +438,18 @@ class JobRunResponseSerializer(serializers.Serializer):
|
|
|
812
438
|
|
|
813
439
|
|
|
814
440
|
class JobResultSerializer(CustomFieldModelSerializerMixin, BaseModelSerializer):
|
|
815
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:jobresult-detail")
|
|
816
|
-
user = NestedUserSerializer(read_only=True)
|
|
817
441
|
status = ChoiceField(choices=JobResultStatusChoices, read_only=True)
|
|
818
|
-
job_model = NestedJobSerializer(read_only=True)
|
|
819
|
-
obj_type = ContentTypeField(read_only=True)
|
|
820
|
-
scheduled_job = NestedScheduledJobSerializer(read_only=True)
|
|
821
442
|
|
|
822
443
|
class Meta:
|
|
823
444
|
model = JobResult
|
|
824
|
-
fields =
|
|
825
|
-
"url",
|
|
826
|
-
"date_created",
|
|
827
|
-
"date_done",
|
|
828
|
-
"name",
|
|
829
|
-
"job_model",
|
|
830
|
-
"obj_type",
|
|
831
|
-
"status",
|
|
832
|
-
"user",
|
|
833
|
-
"data",
|
|
834
|
-
"task_id",
|
|
835
|
-
"task_kwargs",
|
|
836
|
-
"scheduled_job",
|
|
837
|
-
]
|
|
445
|
+
fields = "__all__"
|
|
838
446
|
|
|
839
447
|
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
#
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
class ScheduledJobSerializer(BaseModelSerializer):
|
|
846
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:scheduledjob-detail")
|
|
847
|
-
user = NestedUserSerializer(read_only=True)
|
|
848
|
-
job_model = NestedJobSerializer(read_only=True)
|
|
849
|
-
approved_by_user = NestedUserSerializer(read_only=True)
|
|
448
|
+
class JobRunResponseSerializer(serializers.Serializer):
|
|
449
|
+
"""Serializer representing responses from the JobModelViewSet.run() POST endpoint."""
|
|
850
450
|
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
fields = [
|
|
854
|
-
"url",
|
|
855
|
-
"name",
|
|
856
|
-
"user",
|
|
857
|
-
"job_model",
|
|
858
|
-
"task",
|
|
859
|
-
"interval",
|
|
860
|
-
"queue",
|
|
861
|
-
"job_class",
|
|
862
|
-
"last_run_at",
|
|
863
|
-
"total_run_count",
|
|
864
|
-
"date_changed",
|
|
865
|
-
"description",
|
|
866
|
-
"user",
|
|
867
|
-
"approved_by_user",
|
|
868
|
-
"approval_required",
|
|
869
|
-
"approved_at",
|
|
870
|
-
"crontab",
|
|
871
|
-
]
|
|
451
|
+
schedule = ScheduledJobSerializer(read_only=True, required=False)
|
|
452
|
+
job_result = JobResultSerializer(read_only=True, required=False)
|
|
872
453
|
|
|
873
454
|
|
|
874
455
|
#
|
|
@@ -889,7 +470,6 @@ class JobClassSerializer(serializers.Serializer):
|
|
|
889
470
|
description = serializers.CharField(max_length=255, required=False, read_only=True)
|
|
890
471
|
test_methods = serializers.ListField(child=serializers.CharField(max_length=255))
|
|
891
472
|
vars = serializers.SerializerMethodField(read_only=True)
|
|
892
|
-
result = NestedJobResultSerializer(required=False)
|
|
893
473
|
|
|
894
474
|
@extend_schema_field(serializers.DictField)
|
|
895
475
|
def get_vars(self, instance):
|
|
@@ -912,7 +492,6 @@ class JobClassDetailSerializer(JobClassSerializer):
|
|
|
912
492
|
|
|
913
493
|
|
|
914
494
|
class JobHookSerializer(NautobotModelSerializer):
|
|
915
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:jobhook-detail")
|
|
916
495
|
content_types = ContentTypeField(
|
|
917
496
|
queryset=ChangeLoggedModelsQuery().as_queryset(),
|
|
918
497
|
many=True,
|
|
@@ -920,17 +499,7 @@ class JobHookSerializer(NautobotModelSerializer):
|
|
|
920
499
|
|
|
921
500
|
class Meta:
|
|
922
501
|
model = JobHook
|
|
923
|
-
fields =
|
|
924
|
-
"id",
|
|
925
|
-
"url",
|
|
926
|
-
"name",
|
|
927
|
-
"content_types",
|
|
928
|
-
"job",
|
|
929
|
-
"enabled",
|
|
930
|
-
"type_create",
|
|
931
|
-
"type_update",
|
|
932
|
-
"type_delete",
|
|
933
|
-
]
|
|
502
|
+
fields = "__all__"
|
|
934
503
|
|
|
935
504
|
def validate(self, data):
|
|
936
505
|
validated_data = super().validate(data)
|
|
@@ -950,17 +519,58 @@ class JobHookSerializer(NautobotModelSerializer):
|
|
|
950
519
|
return validated_data
|
|
951
520
|
|
|
952
521
|
|
|
522
|
+
class JobCreationSerializer(BaseModelSerializer):
|
|
523
|
+
"""
|
|
524
|
+
Nested serializer specifically for use with `JobInputSerializer.schedule`.
|
|
525
|
+
|
|
526
|
+
We don't use `WritableNestedSerializer` here because this is not used to look up
|
|
527
|
+
an existing `ScheduledJob`, but instead used to specify parameters for creating one.
|
|
528
|
+
"""
|
|
529
|
+
|
|
530
|
+
url = serializers.HyperlinkedIdentityField(view_name="extras-api:scheduledjob-detail")
|
|
531
|
+
name = serializers.CharField(max_length=255, required=False)
|
|
532
|
+
start_time = serializers.DateTimeField(format=None, required=False)
|
|
533
|
+
|
|
534
|
+
class Meta:
|
|
535
|
+
model = ScheduledJob
|
|
536
|
+
fields = ["url", "name", "start_time", "interval", "crontab"]
|
|
537
|
+
|
|
538
|
+
def validate(self, data):
|
|
539
|
+
data = super().validate(data)
|
|
540
|
+
|
|
541
|
+
if data["interval"] in choices.JobExecutionType.SCHEDULE_CHOICES:
|
|
542
|
+
if "name" not in data:
|
|
543
|
+
raise serializers.ValidationError({"name": "Please provide a name for the job schedule."})
|
|
544
|
+
|
|
545
|
+
if ("start_time" not in data and data["interval"] != choices.JobExecutionType.TYPE_CUSTOM) or (
|
|
546
|
+
"start_time" in data and data["start_time"] < models.ScheduledJob.earliest_possible_time()
|
|
547
|
+
):
|
|
548
|
+
raise serializers.ValidationError(
|
|
549
|
+
{
|
|
550
|
+
"start_time": "Please enter a valid date and time greater than or equal to the current date and time."
|
|
551
|
+
}
|
|
552
|
+
)
|
|
553
|
+
|
|
554
|
+
if data["interval"] == choices.JobExecutionType.TYPE_CUSTOM:
|
|
555
|
+
if data.get("crontab") is None:
|
|
556
|
+
raise serializers.ValidationError({"crontab": "Please enter a valid crontab."})
|
|
557
|
+
try:
|
|
558
|
+
models.ScheduledJob.get_crontab(data["crontab"])
|
|
559
|
+
except Exception as e:
|
|
560
|
+
raise serializers.ValidationError({"crontab": e})
|
|
561
|
+
|
|
562
|
+
return data
|
|
563
|
+
|
|
564
|
+
|
|
953
565
|
class JobInputSerializer(serializers.Serializer):
|
|
954
566
|
data = serializers.JSONField(required=False, default=dict)
|
|
955
|
-
|
|
956
|
-
schedule = NestedScheduledJobCreationSerializer(required=False)
|
|
567
|
+
schedule = JobCreationSerializer(required=False)
|
|
957
568
|
task_queue = serializers.CharField(required=False, allow_blank=True)
|
|
958
569
|
|
|
959
570
|
|
|
960
571
|
class JobMultiPartInputSerializer(serializers.Serializer):
|
|
961
572
|
"""JobMultiPartInputSerializer is a "flattened" version of JobInputSerializer for use with multipart/form-data submissions which only accept key-value pairs"""
|
|
962
573
|
|
|
963
|
-
_commit = serializers.BooleanField(required=False, default=None)
|
|
964
574
|
_schedule_name = serializers.CharField(max_length=255, required=False)
|
|
965
575
|
_schedule_start_time = serializers.DateTimeField(format=None, required=False)
|
|
966
576
|
_schedule_interval = ChoiceField(choices=JobExecutionType, required=False)
|
|
@@ -995,25 +605,9 @@ class JobMultiPartInputSerializer(serializers.Serializer):
|
|
|
995
605
|
|
|
996
606
|
|
|
997
607
|
class JobLogEntrySerializer(BaseModelSerializer):
|
|
998
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:joblogentry-detail")
|
|
999
|
-
display = serializers.SerializerMethodField()
|
|
1000
|
-
|
|
1001
608
|
class Meta:
|
|
1002
609
|
model = JobLogEntry
|
|
1003
|
-
fields =
|
|
1004
|
-
"url",
|
|
1005
|
-
"absolute_url",
|
|
1006
|
-
"created",
|
|
1007
|
-
"grouping",
|
|
1008
|
-
"job_result",
|
|
1009
|
-
"log_level",
|
|
1010
|
-
"log_object",
|
|
1011
|
-
"message",
|
|
1012
|
-
]
|
|
1013
|
-
|
|
1014
|
-
@extend_schema_field(serializers.CharField)
|
|
1015
|
-
def get_display(self, obj):
|
|
1016
|
-
return obj.created.isoformat()
|
|
610
|
+
fields = "__all__"
|
|
1017
611
|
|
|
1018
612
|
|
|
1019
613
|
#
|
|
@@ -1022,22 +616,11 @@ class JobLogEntrySerializer(BaseModelSerializer):
|
|
|
1022
616
|
|
|
1023
617
|
|
|
1024
618
|
class JobButtonSerializer(ValidatedModelSerializer, NotesSerializerMixin):
|
|
1025
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:jobbutton-detail")
|
|
1026
619
|
content_types = ContentTypeField(queryset=ContentType.objects.all(), many=True)
|
|
1027
620
|
|
|
1028
621
|
class Meta:
|
|
1029
622
|
model = JobButton
|
|
1030
|
-
fields =
|
|
1031
|
-
"url",
|
|
1032
|
-
"job",
|
|
1033
|
-
"name",
|
|
1034
|
-
"content_types",
|
|
1035
|
-
"text",
|
|
1036
|
-
"weight",
|
|
1037
|
-
"group_name",
|
|
1038
|
-
"button_class",
|
|
1039
|
-
"confirmation",
|
|
1040
|
-
)
|
|
623
|
+
fields = "__all__"
|
|
1041
624
|
|
|
1042
625
|
|
|
1043
626
|
#
|
|
@@ -1046,29 +629,19 @@ class JobButtonSerializer(ValidatedModelSerializer, NotesSerializerMixin):
|
|
|
1046
629
|
|
|
1047
630
|
|
|
1048
631
|
class NoteSerializer(BaseModelSerializer):
|
|
1049
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:note-detail")
|
|
1050
|
-
user = NestedUserSerializer(read_only=True)
|
|
1051
632
|
assigned_object_type = ContentTypeField(queryset=ContentType.objects.all())
|
|
1052
633
|
assigned_object = serializers.SerializerMethodField()
|
|
1053
634
|
|
|
1054
635
|
class Meta:
|
|
1055
636
|
model = Note
|
|
1056
|
-
fields =
|
|
1057
|
-
|
|
1058
|
-
"user",
|
|
1059
|
-
"user_name",
|
|
1060
|
-
"assigned_object_type",
|
|
1061
|
-
"assigned_object_id",
|
|
1062
|
-
"assigned_object",
|
|
1063
|
-
"note",
|
|
1064
|
-
"slug",
|
|
1065
|
-
]
|
|
637
|
+
fields = "__all__"
|
|
638
|
+
list_display_fields = ["note", "assigned_object_type", "assigned_object_id", "user"]
|
|
1066
639
|
|
|
1067
640
|
@extend_schema_field(
|
|
1068
641
|
PolymorphicProxySerializer(
|
|
1069
642
|
component_name="NoteAssignedObject",
|
|
1070
643
|
resource_type_field_name="object_type",
|
|
1071
|
-
serializers=lambda: get_serializers_for_models(get_all_concrete_models(NotesMixin)
|
|
644
|
+
serializers=lambda: get_serializers_for_models(get_all_concrete_models(NotesMixin)),
|
|
1072
645
|
allow_null=True,
|
|
1073
646
|
)
|
|
1074
647
|
)
|
|
@@ -1076,9 +649,10 @@ class NoteSerializer(BaseModelSerializer):
|
|
|
1076
649
|
if obj.assigned_object is None:
|
|
1077
650
|
return None
|
|
1078
651
|
try:
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
652
|
+
depth = get_nested_serializer_depth(self)
|
|
653
|
+
return return_nested_serializer_data_based_on_depth(
|
|
654
|
+
self, depth, obj, obj.assigned_object, "assigned_object"
|
|
655
|
+
)
|
|
1082
656
|
except SerializerNotFound:
|
|
1083
657
|
return None
|
|
1084
658
|
|
|
@@ -1093,34 +667,20 @@ class NoteInputSerializer(serializers.Serializer):
|
|
|
1093
667
|
|
|
1094
668
|
|
|
1095
669
|
class ObjectChangeSerializer(BaseModelSerializer):
|
|
1096
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:objectchange-detail")
|
|
1097
|
-
user = NestedUserSerializer(read_only=True)
|
|
1098
670
|
action = ChoiceField(choices=ObjectChangeActionChoices, read_only=True)
|
|
1099
671
|
changed_object_type = ContentTypeField(read_only=True)
|
|
1100
672
|
changed_object = serializers.SerializerMethodField(read_only=True)
|
|
1101
673
|
|
|
1102
674
|
class Meta:
|
|
1103
675
|
model = ObjectChange
|
|
1104
|
-
fields =
|
|
1105
|
-
|
|
1106
|
-
"time",
|
|
1107
|
-
"user",
|
|
1108
|
-
"user_name",
|
|
1109
|
-
"request_id",
|
|
1110
|
-
"action",
|
|
1111
|
-
"changed_object_type",
|
|
1112
|
-
"changed_object_id",
|
|
1113
|
-
"changed_object",
|
|
1114
|
-
"object_data",
|
|
1115
|
-
]
|
|
676
|
+
fields = "__all__"
|
|
677
|
+
list_display_fields = ["changed_object_id", "related_object_id", "related_object_type", "user"]
|
|
1116
678
|
|
|
1117
679
|
@extend_schema_field(
|
|
1118
680
|
PolymorphicProxySerializer(
|
|
1119
681
|
component_name="ObjectChangeChangedObject",
|
|
1120
682
|
resource_type_field_name="object_type",
|
|
1121
|
-
serializers=lambda: get_serializers_for_models(
|
|
1122
|
-
ChangeLoggedModelsQuery().list_subclasses(), prefix="Nested"
|
|
1123
|
-
),
|
|
683
|
+
serializers=lambda: get_serializers_for_models(ChangeLoggedModelsQuery().list_subclasses()),
|
|
1124
684
|
allow_null=True,
|
|
1125
685
|
)
|
|
1126
686
|
)
|
|
@@ -1130,15 +690,11 @@ class ObjectChangeSerializer(BaseModelSerializer):
|
|
|
1130
690
|
"""
|
|
1131
691
|
if obj.changed_object is None:
|
|
1132
692
|
return None
|
|
1133
|
-
|
|
1134
693
|
try:
|
|
1135
|
-
|
|
694
|
+
depth = get_nested_serializer_depth(self)
|
|
695
|
+
return return_nested_serializer_data_based_on_depth(self, depth, obj, obj.changed_object, "changed_object")
|
|
1136
696
|
except SerializerNotFound:
|
|
1137
697
|
return obj.object_repr
|
|
1138
|
-
context = {"request": self.context["request"]}
|
|
1139
|
-
data = serializer(obj.changed_object, context=context).data
|
|
1140
|
-
|
|
1141
|
-
return data
|
|
1142
698
|
|
|
1143
699
|
|
|
1144
700
|
#
|
|
@@ -1147,8 +703,6 @@ class ObjectChangeSerializer(BaseModelSerializer):
|
|
|
1147
703
|
|
|
1148
704
|
|
|
1149
705
|
class RelationshipSerializer(ValidatedModelSerializer, NotesSerializerMixin):
|
|
1150
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:relationship-detail")
|
|
1151
|
-
|
|
1152
706
|
source_type = ContentTypeField(
|
|
1153
707
|
queryset=ContentType.objects.filter(FeatureQuery("relationships").get_query()),
|
|
1154
708
|
)
|
|
@@ -1159,27 +713,10 @@ class RelationshipSerializer(ValidatedModelSerializer, NotesSerializerMixin):
|
|
|
1159
713
|
|
|
1160
714
|
class Meta:
|
|
1161
715
|
model = Relationship
|
|
1162
|
-
fields =
|
|
1163
|
-
"url",
|
|
1164
|
-
"name",
|
|
1165
|
-
"slug",
|
|
1166
|
-
"description",
|
|
1167
|
-
"type",
|
|
1168
|
-
"required_on",
|
|
1169
|
-
"source_type",
|
|
1170
|
-
"source_label",
|
|
1171
|
-
"source_hidden",
|
|
1172
|
-
"source_filter",
|
|
1173
|
-
"destination_type",
|
|
1174
|
-
"destination_label",
|
|
1175
|
-
"destination_hidden",
|
|
1176
|
-
"destination_filter",
|
|
1177
|
-
]
|
|
716
|
+
fields = "__all__"
|
|
1178
717
|
|
|
1179
718
|
|
|
1180
719
|
class RelationshipAssociationSerializer(ValidatedModelSerializer):
|
|
1181
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:relationshipassociation-detail")
|
|
1182
|
-
|
|
1183
720
|
source_type = ContentTypeField(
|
|
1184
721
|
queryset=ContentType.objects.filter(FeatureQuery("relationships").get_query()),
|
|
1185
722
|
)
|
|
@@ -1188,18 +725,9 @@ class RelationshipAssociationSerializer(ValidatedModelSerializer):
|
|
|
1188
725
|
queryset=ContentType.objects.filter(FeatureQuery("relationships").get_query()),
|
|
1189
726
|
)
|
|
1190
727
|
|
|
1191
|
-
relationship = NestedRelationshipSerializer()
|
|
1192
|
-
|
|
1193
728
|
class Meta:
|
|
1194
729
|
model = RelationshipAssociation
|
|
1195
|
-
fields =
|
|
1196
|
-
"url",
|
|
1197
|
-
"relationship",
|
|
1198
|
-
"source_type",
|
|
1199
|
-
"source_id",
|
|
1200
|
-
"destination_type",
|
|
1201
|
-
"destination_id",
|
|
1202
|
-
]
|
|
730
|
+
fields = "__all__"
|
|
1203
731
|
|
|
1204
732
|
|
|
1205
733
|
#
|
|
@@ -1207,22 +735,9 @@ class RelationshipAssociationSerializer(ValidatedModelSerializer):
|
|
|
1207
735
|
#
|
|
1208
736
|
|
|
1209
737
|
|
|
1210
|
-
class RoleModelSerializerMixin(BaseModelSerializer):
|
|
1211
|
-
"""Mixin to add `role` choice field to model serializers."""
|
|
1212
|
-
|
|
1213
|
-
role = RoleSerializerField(required=False)
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
class RoleRequiredRoleModelSerializerMixin(BaseModelSerializer):
|
|
1217
|
-
"""Mixin to add `role` choice field to model serializers."""
|
|
1218
|
-
|
|
1219
|
-
role = RoleSerializerField()
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
738
|
class RoleSerializer(NautobotModelSerializer):
|
|
1223
739
|
"""Serializer for `Role` objects."""
|
|
1224
740
|
|
|
1225
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:role-detail")
|
|
1226
741
|
content_types = ContentTypeField(
|
|
1227
742
|
queryset=RoleModelsQuery().as_queryset(),
|
|
1228
743
|
many=True,
|
|
@@ -1230,14 +745,10 @@ class RoleSerializer(NautobotModelSerializer):
|
|
|
1230
745
|
|
|
1231
746
|
class Meta:
|
|
1232
747
|
model = Role
|
|
1233
|
-
fields =
|
|
1234
|
-
|
|
1235
|
-
"
|
|
1236
|
-
|
|
1237
|
-
"slug",
|
|
1238
|
-
"color",
|
|
1239
|
-
"weight",
|
|
1240
|
-
]
|
|
748
|
+
fields = "__all__"
|
|
749
|
+
extra_kwargs = {
|
|
750
|
+
"color": {"help_text": "RGB color in hexadecimal (e.g. 00ff00)"},
|
|
751
|
+
}
|
|
1241
752
|
|
|
1242
753
|
|
|
1243
754
|
#
|
|
@@ -1248,59 +759,33 @@ class RoleSerializer(NautobotModelSerializer):
|
|
|
1248
759
|
class SecretSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
|
|
1249
760
|
"""Serializer for `Secret` objects."""
|
|
1250
761
|
|
|
1251
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:secret-detail")
|
|
1252
|
-
|
|
1253
762
|
class Meta:
|
|
1254
763
|
model = Secret
|
|
1255
|
-
fields =
|
|
1256
|
-
"url",
|
|
1257
|
-
"name",
|
|
1258
|
-
"slug",
|
|
1259
|
-
"description",
|
|
1260
|
-
"provider",
|
|
1261
|
-
"parameters",
|
|
1262
|
-
]
|
|
764
|
+
fields = "__all__"
|
|
1263
765
|
|
|
1264
766
|
|
|
1265
|
-
class
|
|
1266
|
-
"""Serializer for `
|
|
1267
|
-
|
|
1268
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:secretsgroup-detail")
|
|
1269
|
-
|
|
1270
|
-
# TODO: it would be **awesome** if we could create/update SecretsGroupAssociations
|
|
1271
|
-
# alongside creating/updating the base SecretsGroup, but since this is a ManyToManyField with
|
|
1272
|
-
# a `through` table, that appears very non-trivial to implement. For now we have this as a
|
|
1273
|
-
# read-only field; to create/update SecretsGroupAssociations you must make separate calls to the
|
|
1274
|
-
# api/extras/secrets-group-associations/ REST endpoint as appropriate.
|
|
1275
|
-
secrets = NestedSecretsGroupAssociationSerializer(source="secrets_group_associations", many=True, read_only=True)
|
|
767
|
+
class SecretsGroupAssociationSerializer(ValidatedModelSerializer):
|
|
768
|
+
"""Serializer for `SecretsGroupAssociation` objects."""
|
|
1276
769
|
|
|
1277
770
|
class Meta:
|
|
1278
|
-
model =
|
|
1279
|
-
fields =
|
|
1280
|
-
"url",
|
|
1281
|
-
"name",
|
|
1282
|
-
"slug",
|
|
1283
|
-
"description",
|
|
1284
|
-
"secrets",
|
|
1285
|
-
]
|
|
1286
|
-
|
|
771
|
+
model = SecretsGroupAssociation
|
|
772
|
+
fields = "__all__"
|
|
1287
773
|
|
|
1288
|
-
class SecretsGroupAssociationSerializer(ValidatedModelSerializer):
|
|
1289
|
-
"""Serializer for `SecretsGroupAssociation` objects."""
|
|
1290
774
|
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
secret = NestedSecretSerializer()
|
|
775
|
+
class SecretsGroupSerializer(NautobotModelSerializer):
|
|
776
|
+
"""Serializer for `SecretsGroup` objects."""
|
|
1294
777
|
|
|
1295
778
|
class Meta:
|
|
1296
|
-
model =
|
|
1297
|
-
fields =
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
779
|
+
model = SecretsGroup
|
|
780
|
+
fields = "__all__"
|
|
781
|
+
# TODO: it would be **awesome** if we could create/update SecretsGroupAssociations
|
|
782
|
+
# alongside creating/updating the base SecretsGroup, but since this is a ManyToManyField with
|
|
783
|
+
# a `through` table, that appears very non-trivial to implement. For now we have this as a
|
|
784
|
+
# read-only field; to create/update SecretsGroupAssociations you must make separate calls to the
|
|
785
|
+
# api/extras/secrets-group-associations/ REST endpoint as appropriate.
|
|
786
|
+
extra_kwargs = {
|
|
787
|
+
"secrets": {"source": "secrets_group_associations", "read_only": True},
|
|
788
|
+
}
|
|
1304
789
|
|
|
1305
790
|
|
|
1306
791
|
#
|
|
@@ -1311,7 +796,6 @@ class SecretsGroupAssociationSerializer(ValidatedModelSerializer):
|
|
|
1311
796
|
class StatusSerializer(NautobotModelSerializer):
|
|
1312
797
|
"""Serializer for `Status` objects."""
|
|
1313
798
|
|
|
1314
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:status-detail")
|
|
1315
799
|
content_types = ContentTypeField(
|
|
1316
800
|
queryset=ContentType.objects.filter(FeatureQuery("statuses").get_query()),
|
|
1317
801
|
many=True,
|
|
@@ -1319,13 +803,10 @@ class StatusSerializer(NautobotModelSerializer):
|
|
|
1319
803
|
|
|
1320
804
|
class Meta:
|
|
1321
805
|
model = Status
|
|
1322
|
-
fields =
|
|
1323
|
-
|
|
1324
|
-
"
|
|
1325
|
-
|
|
1326
|
-
"slug",
|
|
1327
|
-
"color",
|
|
1328
|
-
]
|
|
806
|
+
fields = "__all__"
|
|
807
|
+
extra_kwargs = {
|
|
808
|
+
"color": {"help_text": "RGB color in hexadecimal (e.g. 00ff00)"},
|
|
809
|
+
}
|
|
1329
810
|
|
|
1330
811
|
|
|
1331
812
|
#
|
|
@@ -1334,7 +815,6 @@ class StatusSerializer(NautobotModelSerializer):
|
|
|
1334
815
|
|
|
1335
816
|
|
|
1336
817
|
class TagSerializer(NautobotModelSerializer):
|
|
1337
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:tag-detail")
|
|
1338
818
|
tagged_items = serializers.IntegerField(read_only=True)
|
|
1339
819
|
content_types = ContentTypeField(
|
|
1340
820
|
queryset=TaggableClassesQuery().as_queryset(),
|
|
@@ -1344,15 +824,10 @@ class TagSerializer(NautobotModelSerializer):
|
|
|
1344
824
|
|
|
1345
825
|
class Meta:
|
|
1346
826
|
model = Tag
|
|
1347
|
-
fields =
|
|
1348
|
-
|
|
1349
|
-
"
|
|
1350
|
-
|
|
1351
|
-
"color",
|
|
1352
|
-
"description",
|
|
1353
|
-
"tagged_items",
|
|
1354
|
-
"content_types",
|
|
1355
|
-
]
|
|
827
|
+
fields = "__all__"
|
|
828
|
+
extra_kwargs = {
|
|
829
|
+
"color": {"help_text": "RGB color in hexadecimal (e.g. 00ff00)"},
|
|
830
|
+
}
|
|
1356
831
|
|
|
1357
832
|
def validate(self, data):
|
|
1358
833
|
data = super().validate(data)
|
|
@@ -1374,7 +849,6 @@ class TagSerializer(NautobotModelSerializer):
|
|
|
1374
849
|
|
|
1375
850
|
|
|
1376
851
|
class WebhookSerializer(ValidatedModelSerializer, NotesSerializerMixin):
|
|
1377
|
-
url = serializers.HyperlinkedIdentityField(view_name="extras-api:webhook-detail")
|
|
1378
852
|
content_types = ContentTypeField(
|
|
1379
853
|
queryset=ContentType.objects.filter(FeatureQuery("webhooks").get_query()).order_by("app_label", "model"),
|
|
1380
854
|
many=True,
|
|
@@ -1382,22 +856,7 @@ class WebhookSerializer(ValidatedModelSerializer, NotesSerializerMixin):
|
|
|
1382
856
|
|
|
1383
857
|
class Meta:
|
|
1384
858
|
model = Webhook
|
|
1385
|
-
fields =
|
|
1386
|
-
"url",
|
|
1387
|
-
"content_types",
|
|
1388
|
-
"name",
|
|
1389
|
-
"type_create",
|
|
1390
|
-
"type_update",
|
|
1391
|
-
"type_delete",
|
|
1392
|
-
"payload_url",
|
|
1393
|
-
"http_method",
|
|
1394
|
-
"http_content_type",
|
|
1395
|
-
"additional_headers",
|
|
1396
|
-
"body_template",
|
|
1397
|
-
"secret",
|
|
1398
|
-
"ssl_verification",
|
|
1399
|
-
"ca_file_path",
|
|
1400
|
-
]
|
|
859
|
+
fields = "__all__"
|
|
1401
860
|
|
|
1402
861
|
def validate(self, data):
|
|
1403
862
|
validated_data = super().validate(data)
|