nautobot 2.0.0a3__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/apps/api.py +6 -8
- nautobot/apps/forms.py +0 -2
- nautobot/apps/ui.py +0 -8
- nautobot/circuits/api/serializers.py +9 -117
- nautobot/circuits/api/urls.py +1 -1
- nautobot/circuits/api/views.py +0 -1
- nautobot/circuits/forms.py +0 -65
- nautobot/circuits/migrations/0014_related_name_changes.py +1 -1
- 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 -87
- nautobot/circuits/navigation.py +14 -69
- nautobot/circuits/signals.py +0 -2
- nautobot/circuits/tables.py +39 -1
- nautobot/circuits/tests/integration/test_relationships.py +9 -9
- nautobot/circuits/tests/test_api.py +4 -8
- nautobot/circuits/tests/test_filters.py +10 -4
- nautobot/circuits/tests/test_models.py +5 -1
- nautobot/circuits/tests/test_views.py +27 -5
- nautobot/circuits/views.py +18 -10
- nautobot/core/api/__init__.py +8 -2
- 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 +4 -0
- nautobot/core/api/parsers.py +154 -0
- nautobot/core/api/renderers.py +153 -2
- nautobot/core/api/schema.py +46 -2
- nautobot/core/api/serializers.py +377 -35
- 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 -72
- nautobot/core/apps/__init__.py +138 -220
- nautobot/core/celery/__init__.py +112 -41
- nautobot/core/celery/backends.py +19 -12
- 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 +0 -113
- nautobot/core/{cli.py → cli/__init__.py} +1 -1
- nautobot/core/cli/__main__.py +3 -0
- nautobot/core/constants.py +0 -24
- 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 +38 -65
- nautobot/core/forms/forms.py +4 -1
- nautobot/core/forms/utils.py +0 -52
- 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/generate_test_data.py +3 -2
- nautobot/core/management/commands/post_upgrade.py +24 -24
- nautobot/core/models/__init__.py +26 -1
- nautobot/core/models/fields.py +24 -5
- nautobot/core/models/generics.py +2 -42
- nautobot/core/models/managers.py +5 -0
- nautobot/core/models/name_color_content_types.py +0 -14
- nautobot/core/models/tree_queries.py +14 -4
- nautobot/core/models/utils.py +5 -6
- nautobot/core/models/validators.py +17 -8
- nautobot/core/releases.py +8 -10
- nautobot/core/settings.py +80 -42
- 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 +3 -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 -20
- 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 -28
- nautobot/core/testing/__init__.py +47 -44
- nautobot/core/testing/api.py +362 -47
- nautobot/core/testing/filters.py +1 -1
- nautobot/core/testing/migrations.py +2 -0
- nautobot/core/testing/mixins.py +22 -9
- nautobot/core/testing/schema.py +2 -1
- nautobot/core/testing/views.py +21 -46
- 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/test_api.py +290 -21
- nautobot/core/tests/test_checks.py +0 -7
- nautobot/core/tests/test_filters.py +107 -59
- nautobot/core/tests/test_forms.py +26 -92
- nautobot/core/tests/test_graphql.py +110 -77
- nautobot/core/tests/test_logging.py +4 -0
- nautobot/core/tests/test_managers.py +3 -1
- nautobot/core/tests/test_models.py +2 -0
- nautobot/core/tests/test_paginator.py +3 -1
- nautobot/core/tests/test_releases.py +12 -12
- nautobot/core/tests/test_templatetags_helpers.py +4 -4
- nautobot/core/tests/test_utils.py +32 -68
- nautobot/core/tests/test_views.py +12 -15
- nautobot/core/utils/data.py +17 -0
- nautobot/core/utils/deprecation.py +9 -6
- nautobot/core/utils/filtering.py +8 -3
- nautobot/core/utils/git.py +12 -4
- nautobot/core/utils/lookup.py +3 -1
- nautobot/core/utils/requests.py +1 -104
- nautobot/core/views/__init__.py +1 -0
- nautobot/core/views/generic.py +75 -110
- nautobot/core/views/mixins.py +52 -61
- nautobot/core/views/renderers.py +6 -7
- nautobot/core/views/utils.py +80 -0
- nautobot/dcim/api/serializers.py +160 -667
- nautobot/dcim/api/urls.py +1 -1
- nautobot/dcim/api/views.py +7 -44
- nautobot/dcim/choices.py +2 -0
- nautobot/dcim/filters/__init__.py +21 -0
- nautobot/dcim/form_mixins.py +1 -27
- nautobot/dcim/forms.py +19 -765
- nautobot/dcim/migrations/0024_alter_device_and_rack_role_add_new_role.py +2 -1
- nautobot/dcim/migrations/0025_device_and_rack_roles_data_migrations.py +19 -13
- nautobot/dcim/migrations/0027_remove_device_role_and_rack_role.py +1 -1
- nautobot/dcim/migrations/0028_rename_foreignkey_fields.py +1 -1
- nautobot/dcim/migrations/0030_migrate_region_and_site_data_to_locations.py +2 -2
- nautobot/dcim/migrations/0035_related_name_changes.py +1 -1
- nautobot/dcim/migrations/0036_remove_region_and_site.py +1 -1
- nautobot/dcim/migrations/0040_tagsfield.py +109 -0
- nautobot/dcim/migrations/{0040_ipam__namespaces.py → 0041_ipam__namespaces.py} +1 -1
- nautobot/dcim/migrations/0042_fixup_null_statuses.py +51 -0
- nautobot/dcim/migrations/0043_status_nonnullable.py +72 -0
- nautobot/dcim/models/cables.py +3 -33
- nautobot/dcim/models/device_component_templates.py +6 -0
- nautobot/dcim/models/device_components.py +12 -198
- nautobot/dcim/models/devices.py +30 -143
- nautobot/dcim/models/locations.py +3 -64
- nautobot/dcim/models/power.py +3 -50
- nautobot/dcim/models/racks.py +7 -84
- nautobot/dcim/navigation.py +141 -467
- nautobot/dcim/signals.py +0 -2
- nautobot/dcim/tables/locations.py +2 -2
- nautobot/dcim/tables/power.py +1 -2
- nautobot/dcim/templates/dcim/console_port_connection_list.html +7 -0
- nautobot/dcim/templates/dcim/devicetype.html +2 -2
- nautobot/dcim/templates/dcim/interface_connection_list.html +7 -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/test_api.py +166 -81
- nautobot/dcim/tests/test_cablepaths.py +41 -35
- nautobot/dcim/tests/test_filters.py +67 -23
- nautobot/dcim/tests/test_forms.py +5 -205
- nautobot/dcim/tests/test_graphql.py +7 -2
- nautobot/dcim/tests/test_migrations.py +6 -11
- nautobot/dcim/tests/test_models.py +182 -110
- nautobot/dcim/tests/test_natural_ordering.py +11 -8
- nautobot/dcim/tests/test_signals.py +6 -3
- nautobot/dcim/tests/test_views.py +197 -175
- nautobot/dcim/urls.py +11 -16
- nautobot/dcim/views.py +7 -134
- 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 +177 -195
- nautobot/docs/administration/nautobot-server.md +6 -21
- nautobot/docs/administration/replicating-nautobot.md +0 -10
- nautobot/docs/configuration/optional-settings.md +32 -41
- nautobot/docs/configuration/required-settings.md +11 -52
- nautobot/docs/development/application-registry.md +2 -13
- nautobot/docs/development/extending-models.md +15 -17
- nautobot/docs/development/generic-views.md +0 -2
- nautobot/docs/development/getting-started.md +55 -5
- nautobot/docs/development/navigation-menu.md +22 -93
- nautobot/docs/development/react-ui.md +105 -0
- nautobot/docs/development/role-internals.md +1 -3
- nautobot/docs/development/style-guide.md +6 -4
- nautobot/docs/index.md +3 -2
- nautobot/docs/installation/migrating-from-netbox.md +11 -42
- 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 +170 -747
- 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/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/virtualization/virtualmachine.md +3 -0
- nautobot/docs/plugins/development.md +83 -21
- nautobot/docs/release-notes/version-1.5.md +53 -0
- nautobot/docs/release-notes/version-2.0.md +180 -0
- nautobot/docs/requirements.txt +1 -0
- 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 -158
- nautobot/extras/api/serializers.py +165 -700
- nautobot/extras/api/urls.py +1 -1
- nautobot/extras/api/views.py +294 -280
- nautobot/extras/apps.py +4 -7
- nautobot/extras/choices.py +11 -9
- 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/filters/__init__.py +20 -19
- nautobot/extras/filters/mixins.py +4 -4
- nautobot/extras/forms/forms.py +63 -127
- nautobot/extras/forms/mixins.py +23 -51
- nautobot/extras/health_checks.py +0 -33
- nautobot/extras/jobs.py +387 -565
- nautobot/extras/management/commands/runjob.py +24 -62
- nautobot/extras/managers.py +30 -7
- 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 -1
- nautobot/extras/migrations/{0059_alter_joblogentry_scheduledjob_webhook_fields.py → 0060_alter_joblogentry_scheduledjob_webhook_fields.py} +1 -1
- nautobot/extras/migrations/{0060_role_and_alter_status.py → 0061_role_and_alter_status.py} +1 -7
- nautobot/extras/migrations/{0061_collect_roles_from_related_apps_roles.py → 0062_collect_roles_from_related_apps_roles.py} +33 -32
- nautobot/extras/migrations/{0062_alter_role_options.py → 0063_alter_role_options.py} +1 -1
- nautobot/extras/migrations/{0063_alter_configcontext_and_add_new_role.py → 0064_alter_configcontext_and_add_new_role.py} +1 -1
- nautobot/extras/migrations/0065_configcontext_data_migrations.py +44 -0
- nautobot/extras/migrations/{0065_rename_configcontext_role.py → 0066_rename_configcontext_role.py} +1 -1
- nautobot/extras/migrations/{0066_jobresult__add_celery_fields.py → 0067_jobresult__add_celery_fields.py} +36 -2
- nautobot/extras/migrations/{0067_created_datetime.py → 0068_created_datetime.py} +1 -1
- nautobot/extras/migrations/{0068_remove_site_and_region_attributes_from_config_context.py → 0069_remove_site_and_region_attributes_from_config_context.py} +1 -1
- 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 -1
- 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 -9
- nautobot/extras/migrations/{0073_remove_gitrepository_fields.py → 0074_remove_gitrepository_fields.py} +1 -1
- 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/{0077_remove_slug.py → 0078_remove_slug.py} +1 -5
- 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 -6
- nautobot/extras/models/jobs.py +189 -321
- nautobot/extras/models/mixins.py +0 -71
- nautobot/extras/models/models.py +0 -19
- nautobot/extras/models/relationships.py +19 -13
- nautobot/extras/models/roles.py +0 -34
- nautobot/extras/models/secrets.py +2 -26
- 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 -120
- nautobot/extras/plugins/utils.py +0 -3
- nautobot/extras/plugins/validators.py +5 -4
- nautobot/extras/plugins/views.py +16 -3
- nautobot/extras/querysets.py +1 -7
- nautobot/extras/registry.py +3 -0
- nautobot/extras/signals.py +26 -60
- nautobot/extras/tables.py +34 -40
- 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/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 +15 -17
- nautobot/extras/templates/extras/jobresult.html +24 -6
- nautobot/extras/templates/extras/scheduledjob.html +2 -2
- nautobot/extras/templates/extras/secret.html +28 -0
- nautobot/extras/templatetags/job_buttons.py +1 -0
- 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/test_computedfields.py +1 -1
- nautobot/extras/tests/integration/test_configcontextschema.py +5 -3
- nautobot/extras/tests/integration/test_customfields.py +4 -2
- nautobot/extras/tests/integration/test_dynamicgroups.py +1 -1
- nautobot/extras/tests/integration/test_jobs.py +25 -27
- nautobot/extras/tests/integration/test_notes.py +8 -4
- nautobot/extras/tests/integration/test_relationships.py +2 -2
- nautobot/extras/tests/test_api.py +649 -642
- nautobot/extras/tests/test_changelog.py +3 -3
- nautobot/extras/tests/test_context_managers.py +5 -3
- nautobot/extras/tests/test_customfields.py +92 -50
- nautobot/extras/tests/test_datasources.py +189 -112
- nautobot/extras/tests/test_dynamicgroups.py +7 -8
- nautobot/extras/tests/test_filters.py +137 -89
- nautobot/extras/tests/test_forms.py +73 -75
- nautobot/extras/tests/{test_scripts.py → test_job_variables.py} +43 -49
- nautobot/extras/tests/test_jobs.py +262 -263
- nautobot/extras/tests/test_migrations.py +4 -3
- nautobot/extras/tests/test_models.py +116 -161
- nautobot/extras/tests/test_plugins.py +38 -60
- nautobot/extras/tests/test_relationships.py +167 -120
- nautobot/extras/tests/test_tags.py +6 -11
- nautobot/extras/tests/test_utils.py +31 -1
- nautobot/extras/tests/test_views.py +201 -145
- nautobot/extras/tests/test_webhooks.py +6 -2
- nautobot/extras/urls.py +42 -42
- nautobot/extras/utils.py +137 -163
- nautobot/extras/views.py +78 -152
- nautobot/ipam/api/fields.py +17 -0
- nautobot/ipam/api/serializers.py +58 -164
- nautobot/ipam/api/urls.py +1 -1
- nautobot/ipam/api/views.py +3 -2
- nautobot/ipam/apps.py +1 -2
- nautobot/ipam/filters.py +1 -10
- nautobot/ipam/forms.py +4 -177
- nautobot/ipam/lookups.py +1 -0
- nautobot/ipam/management/commands/__init__.py +0 -0
- nautobot/ipam/management/commands/fix_prefix_broadcast.py +17 -0
- nautobot/ipam/migrations/0010_alter_ipam_role_add_new_role.py +1 -1
- nautobot/ipam/migrations/0011_migrate_ipam_role_data.py +32 -38
- nautobot/ipam/migrations/0020_related_name_changes.py +1 -1
- nautobot/ipam/migrations/0022_aggregate_to_prefix_data_migration.py +2 -2
- nautobot/ipam/migrations/0028_tagsfield.py +44 -0
- nautobot/ipam/migrations/0029_ip_address_to_interface_uniqueness_constraints.py +18 -0
- nautobot/ipam/migrations/{0028_ipam__namespaces.py → 0030_ipam__namespaces.py} +77 -28
- 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 +100 -236
- nautobot/ipam/navigation.py +36 -181
- nautobot/ipam/querysets.py +20 -25
- nautobot/ipam/signals.py +49 -6
- nautobot/ipam/tables.py +10 -3
- 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 +17 -4
- nautobot/ipam/templates/ipam/namespace_vrfs.html +11 -0
- nautobot/ipam/templates/ipam/prefix.html +1 -1
- nautobot/ipam/templates/ipam/vlangroup.html +0 -13
- nautobot/ipam/templates/ipam/vrf_edit.html +6 -0
- nautobot/ipam/tests/integration/test_prefixes.py +3 -26
- nautobot/ipam/tests/test_api.py +22 -19
- nautobot/ipam/tests/test_filters.py +59 -23
- nautobot/ipam/tests/test_migrations.py +6 -10
- nautobot/ipam/tests/test_models.py +323 -198
- nautobot/ipam/tests/test_ordering.py +2 -2
- nautobot/ipam/tests/test_querysets.py +44 -24
- nautobot/ipam/tests/test_views.py +73 -26
- nautobot/ipam/urls.py +16 -0
- nautobot/ipam/{utils.py → utils/__init__.py} +2 -2
- nautobot/ipam/utils/migrations.py +713 -0
- nautobot/ipam/views.py +137 -20
- nautobot/project-static/docs/404.html +1178 -10
- nautobot/project-static/docs/additional-features/caching.html +1224 -159
- nautobot/project-static/docs/additional-features/change-logging.html +1180 -12
- nautobot/project-static/docs/additional-features/config-contexts.html +1180 -12
- nautobot/project-static/docs/additional-features/graphql.html +1179 -11
- nautobot/project-static/docs/additional-features/healthcheck.html +1180 -12
- nautobot/project-static/docs/additional-features/job-scheduling-and-approvals.html +1184 -12
- nautobot/project-static/docs/additional-features/jobs.html +1514 -328
- nautobot/project-static/docs/additional-features/napalm.html +1180 -12
- nautobot/project-static/docs/additional-features/prometheus-metrics.html +1180 -12
- nautobot/project-static/docs/additional-features/template-filters.html +1180 -12
- nautobot/project-static/docs/administration/celery-queues.html +1178 -10
- nautobot/project-static/docs/administration/nautobot-server.html +1451 -304
- nautobot/project-static/docs/administration/nautobot-shell.html +1178 -10
- nautobot/project-static/docs/administration/permissions.html +1178 -10
- nautobot/project-static/docs/administration/replicating-nautobot.html +1262 -113
- nautobot/project-static/docs/apps/index.html +1178 -10
- nautobot/project-static/docs/apps/nautobot-apps.html +1178 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +1580 -426
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +1178 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +3481 -1838
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +1178 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +1178 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +1185 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +1719 -551
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +2062 -930
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +1946 -659
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +1180 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +1189 -21
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +9283 -6218
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +2734 -2122
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +1178 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +2337 -1300
- nautobot/project-static/docs/configuration/authentication/ldap.html +1178 -10
- nautobot/project-static/docs/configuration/authentication/remote.html +1178 -10
- nautobot/project-static/docs/configuration/authentication/sso.html +1178 -10
- nautobot/project-static/docs/configuration/index.html +1178 -10
- nautobot/project-static/docs/configuration/optional-settings.html +1311 -160
- nautobot/project-static/docs/configuration/required-settings.html +1312 -211
- nautobot/project-static/docs/core-functionality/circuits.html +1178 -10
- nautobot/project-static/docs/core-functionality/device-types.html +1178 -10
- nautobot/project-static/docs/core-functionality/devices.html +1182 -10
- nautobot/project-static/docs/core-functionality/ipam.html +1182 -10
- nautobot/project-static/docs/core-functionality/power.html +1178 -10
- nautobot/project-static/docs/core-functionality/secrets.html +1178 -10
- nautobot/project-static/docs/core-functionality/services.html +1178 -10
- nautobot/project-static/docs/core-functionality/sites-and-racks.html +1178 -10
- nautobot/project-static/docs/core-functionality/tenancy.html +1178 -10
- nautobot/project-static/docs/core-functionality/virtualization.html +1182 -10
- nautobot/project-static/docs/core-functionality/vlans.html +1179 -11
- nautobot/project-static/docs/development/application-registry.html +1190 -42
- nautobot/project-static/docs/development/best-practices.html +1178 -10
- nautobot/project-static/docs/development/docker-compose-advanced-use-cases.html +1178 -10
- nautobot/project-static/docs/development/extending-models.html +1238 -83
- nautobot/project-static/docs/development/generic-views.html +1180 -14
- nautobot/project-static/docs/development/getting-started.html +1365 -90
- nautobot/project-static/docs/development/homepage.html +1178 -10
- nautobot/project-static/docs/development/index.html +1178 -10
- nautobot/project-static/docs/development/model-features.html +1178 -10
- nautobot/project-static/docs/development/natural-keys.html +1178 -10
- nautobot/project-static/docs/development/navigation-menu.html +1215 -125
- nautobot/project-static/docs/development/react-ui.html +4199 -0
- nautobot/project-static/docs/development/release-checklist.html +1178 -10
- nautobot/project-static/docs/development/role-internals.html +1179 -12
- nautobot/project-static/docs/development/style-guide.html +1188 -19
- nautobot/project-static/docs/development/templates.html +1178 -10
- nautobot/project-static/docs/development/testing.html +1178 -10
- nautobot/project-static/docs/development/user-preferences.html +1178 -10
- nautobot/project-static/docs/docker/index.html +1178 -10
- nautobot/project-static/docs/index.html +1183 -12
- nautobot/project-static/docs/installation/centos.html +1178 -10
- nautobot/project-static/docs/installation/external-authentication.html +1178 -10
- nautobot/project-static/docs/installation/http-server.html +1178 -10
- nautobot/project-static/docs/installation/index.html +1178 -10
- nautobot/project-static/docs/installation/migrating-from-netbox.html +1305 -189
- nautobot/project-static/docs/installation/migrating-from-postgresql.html +1178 -10
- nautobot/project-static/docs/installation/nautobot.html +1179 -11
- nautobot/project-static/docs/installation/region-and-site-data-migration-guide.html +1178 -10
- nautobot/project-static/docs/installation/selinux-troubleshooting.html +1178 -10
- nautobot/project-static/docs/installation/services.html +1178 -10
- 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 +1178 -10
- nautobot/project-static/docs/installation/upgrading-from-nautobot-v1.html +3823 -2152
- nautobot/project-static/docs/installation/upgrading.html +1178 -10
- nautobot/project-static/docs/models/circuits/circuit.html +1293 -103
- nautobot/project-static/docs/models/circuits/circuittermination.html +1293 -103
- nautobot/project-static/docs/models/circuits/circuittype.html +1293 -103
- nautobot/project-static/docs/models/circuits/provider.html +1293 -103
- nautobot/project-static/docs/models/circuits/providernetwork.html +1293 -103
- nautobot/project-static/docs/models/dcim/cable.html +1324 -103
- nautobot/project-static/docs/models/dcim/consoleport.html +1293 -103
- nautobot/project-static/docs/models/dcim/consoleporttemplate.html +1293 -103
- nautobot/project-static/docs/models/dcim/consoleserverport.html +1293 -103
- nautobot/project-static/docs/models/dcim/consoleserverporttemplate.html +1293 -103
- nautobot/project-static/docs/models/dcim/device.html +1326 -132
- nautobot/project-static/docs/models/dcim/devicebay.html +1293 -103
- nautobot/project-static/docs/models/dcim/devicebaytemplate.html +1293 -103
- nautobot/project-static/docs/models/dcim/deviceredundancygroup.html +1379 -97
- nautobot/project-static/docs/models/dcim/devicetype.html +1293 -103
- nautobot/project-static/docs/models/dcim/frontport.html +1293 -103
- nautobot/project-static/docs/models/dcim/frontporttemplate.html +1293 -103
- nautobot/project-static/docs/models/dcim/interface.html +1293 -103
- nautobot/project-static/docs/models/dcim/interfacetemplate.html +1293 -103
- nautobot/project-static/docs/models/dcim/inventoryitem.html +1293 -103
- nautobot/project-static/docs/models/dcim/location.html +1293 -103
- nautobot/project-static/docs/models/dcim/locationtype.html +1293 -103
- nautobot/project-static/docs/models/dcim/manufacturer.html +1292 -102
- nautobot/project-static/docs/models/dcim/platform.html +1272 -82
- nautobot/project-static/docs/models/dcim/powerfeed.html +1270 -80
- nautobot/project-static/docs/models/dcim/poweroutlet.html +1272 -82
- nautobot/project-static/docs/models/dcim/poweroutlettemplate.html +1272 -82
- nautobot/project-static/docs/models/dcim/powerpanel.html +1270 -80
- nautobot/project-static/docs/models/dcim/powerport.html +1272 -82
- nautobot/project-static/docs/models/dcim/powerporttemplate.html +1272 -82
- nautobot/project-static/docs/models/dcim/rack.html +1272 -82
- nautobot/project-static/docs/models/dcim/rackgroup.html +1272 -82
- nautobot/project-static/docs/models/dcim/rackreservation.html +1272 -82
- nautobot/project-static/docs/models/dcim/rearport.html +1286 -96
- nautobot/project-static/docs/models/dcim/rearporttemplate.html +1286 -96
- nautobot/project-static/docs/models/dcim/region.html +1178 -10
- nautobot/project-static/docs/models/dcim/site.html +1178 -10
- nautobot/project-static/docs/models/dcim/virtualchassis.html +1284 -94
- nautobot/project-static/docs/models/extras/computedfield.html +1184 -16
- nautobot/project-static/docs/models/extras/configcontext.html +1314 -86
- nautobot/project-static/docs/models/extras/configcontextschema.html +1276 -86
- nautobot/project-static/docs/models/extras/customfield.html +1180 -12
- nautobot/project-static/docs/models/extras/customlink.html +1180 -12
- nautobot/project-static/docs/models/extras/dynamicgroup.html +1180 -12
- nautobot/project-static/docs/models/extras/exporttemplate.html +1180 -12
- nautobot/project-static/docs/models/extras/gitrepository.html +1184 -12
- nautobot/project-static/docs/models/extras/graphqlquery.html +1321 -86
- nautobot/project-static/docs/models/extras/imageattachment.html +1276 -86
- nautobot/project-static/docs/models/extras/job.html +1277 -86
- nautobot/project-static/docs/models/extras/jobbutton.html +1201 -29
- nautobot/project-static/docs/models/extras/jobhook.html +1188 -16
- nautobot/project-static/docs/models/extras/joblogentry.html +1274 -84
- nautobot/project-static/docs/models/extras/jobresult.html +1364 -169
- nautobot/project-static/docs/models/extras/note.html +1180 -12
- nautobot/project-static/docs/models/extras/relationship.html +1182 -14
- nautobot/project-static/docs/models/extras/role.html +1320 -86
- nautobot/project-static/docs/models/extras/secret.html +1314 -86
- nautobot/project-static/docs/models/extras/secretsgroup.html +1276 -86
- nautobot/project-static/docs/models/extras/status.html +1188 -59
- nautobot/project-static/docs/models/extras/tag.html +1180 -12
- nautobot/project-static/docs/models/extras/webhook.html +1180 -12
- nautobot/project-static/docs/models/ipam/ipaddress.html +1327 -102
- nautobot/project-static/docs/models/ipam/prefix.html +1276 -86
- nautobot/project-static/docs/models/ipam/rir.html +1276 -86
- nautobot/project-static/docs/models/ipam/routetarget.html +1276 -86
- nautobot/project-static/docs/models/ipam/service.html +1276 -86
- nautobot/project-static/docs/models/ipam/vlan.html +1276 -86
- nautobot/project-static/docs/models/ipam/vlangroup.html +1276 -86
- nautobot/project-static/docs/models/ipam/vrf.html +1276 -86
- nautobot/project-static/docs/models/tenancy/tenant.html +1276 -86
- nautobot/project-static/docs/models/tenancy/tenantgroup.html +1276 -86
- nautobot/project-static/docs/models/users/objectpermission.html +1314 -86
- nautobot/project-static/docs/models/users/token.html +1276 -86
- nautobot/project-static/docs/models/virtualization/cluster.html +1276 -86
- nautobot/project-static/docs/models/virtualization/clustergroup.html +1276 -86
- nautobot/project-static/docs/models/virtualization/clustertype.html +1276 -86
- nautobot/project-static/docs/models/virtualization/virtualmachine.html +1321 -127
- nautobot/project-static/docs/models/virtualization/vminterface.html +1276 -86
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/plugins/development.html +1726 -495
- nautobot/project-static/docs/plugins/index.html +1178 -10
- nautobot/project-static/docs/plugins/porting-from-netbox.html +1178 -10
- nautobot/project-static/docs/release-notes/index.html +1178 -10
- nautobot/project-static/docs/release-notes/version-1.0.html +1178 -10
- nautobot/project-static/docs/release-notes/version-1.1.html +1178 -10
- nautobot/project-static/docs/release-notes/version-1.2.html +1178 -10
- nautobot/project-static/docs/release-notes/version-1.3.html +1178 -10
- nautobot/project-static/docs/release-notes/version-1.4.html +1178 -10
- nautobot/project-static/docs/release-notes/version-1.5.html +1608 -225
- nautobot/project-static/docs/release-notes/version-2.0.html +1547 -47
- nautobot/project-static/docs/requirements.txt +1 -0
- nautobot/project-static/docs/rest-api/authentication.html +1179 -11
- nautobot/project-static/docs/rest-api/filtering.html +1178 -10
- nautobot/project-static/docs/rest-api/overview.html +1841 -446
- 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 +1178 -10
- nautobot/project-static/docs/user-guides/getting-started/creating-devices.html +1178 -10
- nautobot/project-static/docs/user-guides/getting-started/index.html +1178 -10
- nautobot/project-static/docs/user-guides/getting-started/interfaces.html +1178 -10
- nautobot/project-static/docs/user-guides/getting-started/ipam.html +1178 -10
- nautobot/project-static/docs/user-guides/getting-started/platforms.html +1178 -10
- nautobot/project-static/docs/user-guides/getting-started/regions.html +1178 -10
- nautobot/project-static/docs/user-guides/getting-started/search-bar.html +1178 -10
- nautobot/project-static/docs/user-guides/getting-started/tenants.html +1178 -10
- nautobot/project-static/docs/user-guides/getting-started/vlans-and-vlan-groups.html +1178 -10
- nautobot/project-static/docs/user-guides/git-data-source.html +1178 -10
- nautobot/project-static/docs/user-guides/graphql.html +1178 -10
- nautobot/project-static/docs/user-guides/relationships.html +1178 -10
- nautobot/project-static/docs/user-guides/s3-django-storage.html +1178 -10
- nautobot/project-static/js/forms.js +16 -9
- nautobot/project-static/js/theme.js +5 -0
- nautobot/tenancy/api/serializers.py +4 -32
- nautobot/tenancy/api/urls.py +1 -1
- nautobot/tenancy/forms.py +0 -28
- nautobot/tenancy/migrations/0008_tagsfield.py +19 -0
- nautobot/tenancy/models.py +0 -25
- nautobot/tenancy/navigation.py +6 -39
- nautobot/tenancy/templates/tenancy/tenant.html +12 -12
- nautobot/tenancy/templates/tenancy/tenantgroup.html +1 -1
- nautobot/tenancy/tests/test_api.py +1 -3
- nautobot/tenancy/tests/test_filters.py +10 -5
- nautobot/tenancy/views.py +0 -2
- 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/tests/test_api.py +110 -25
- nautobot/virtualization/api/serializers.py +18 -130
- nautobot/virtualization/api/urls.py +1 -1
- nautobot/virtualization/api/views.py +1 -22
- nautobot/virtualization/forms.py +13 -99
- nautobot/virtualization/migrations/0012_alter_virtualmachine_role_add_new_role.py +1 -1
- nautobot/virtualization/migrations/0013_migrate_virtualmachine_role_data.py +18 -11
- nautobot/virtualization/migrations/0015_rename_foreignkey_fields.py +1 -1
- nautobot/virtualization/migrations/0018_related_name_changes.py +1 -1
- 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/{0021_ipam__namespaces.py → 0023_ipam__namespaces.py} +2 -2
- nautobot/virtualization/migrations/0024_fixup_null_statuses.py +25 -0
- nautobot/virtualization/migrations/0025_status_nonnullable.py +29 -0
- nautobot/virtualization/models.py +31 -123
- nautobot/virtualization/navigation.py +18 -99
- nautobot/virtualization/templates/virtualization/virtualmachine.html +2 -1
- nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +6 -0
- nautobot/virtualization/tests/test_api.py +25 -26
- nautobot/virtualization/tests/test_filters.py +41 -15
- nautobot/virtualization/tests/test_models.py +31 -7
- nautobot/virtualization/tests/test_views.py +42 -25
- nautobot/virtualization/views.py +7 -6
- {nautobot-2.0.0a3.dist-info → nautobot-2.0.0b1.dist-info}/METADATA +3 -7
- {nautobot-2.0.0a3.dist-info → nautobot-2.0.0b1.dist-info}/RECORD +744 -602
- {nautobot-2.0.0a3.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 -41
- nautobot/extras/migrations/0071_job__unique_name_data_migration.py +0 -46
- 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 -18
- 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 -159
- nautobot/ipam/migrations/0029_ipam__prefix__add_parent.py +0 -31
- nautobot/ipam/migrations/0030_ipam__prefix__data_migration.py +0 -13
- nautobot/ipam/migrations/0031_ipam__ipaddress__add_parent.py +0 -41
- nautobot/ipam/migrations/0032_ipam__ipaddress__data_migration.py +0 -11
- 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.0a3.dist-info → nautobot-2.0.0b1.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.0.0a3.dist-info → nautobot-2.0.0b1.dist-info}/entry_points.txt +0 -0
|
@@ -2,7 +2,7 @@ import re
|
|
|
2
2
|
|
|
3
3
|
from django.conf import settings
|
|
4
4
|
from django.core.exceptions import ValidationError
|
|
5
|
-
from django.core.validators import BaseValidator, URLValidator, _lazy_re_compile
|
|
5
|
+
from django.core.validators import BaseValidator, RegexValidator, URLValidator, _lazy_re_compile
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class EnhancedURLValidator(URLValidator):
|
|
@@ -41,12 +41,21 @@ class ExclusionValidator(BaseValidator):
|
|
|
41
41
|
return a in b
|
|
42
42
|
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
class ValidRegexValidator(RegexValidator):
|
|
45
45
|
"""
|
|
46
|
-
Checks that the value is a valid regular expression.
|
|
47
|
-
|
|
46
|
+
Checks that the value is a valid regular expression.
|
|
47
|
+
|
|
48
|
+
Don't confuse this with `RegexValidator`, which *uses* a regex to validate a value.
|
|
48
49
|
"""
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
|
|
51
|
+
message = "%(value)r is not a valid regular expression."
|
|
52
|
+
code = "regex_invalid"
|
|
53
|
+
|
|
54
|
+
def __call__(self, value):
|
|
55
|
+
try:
|
|
56
|
+
return re.compile(value)
|
|
57
|
+
except (re.error, TypeError):
|
|
58
|
+
raise ValidationError(self.message, code=self.code, params={"value": value})
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
validate_regex = ValidRegexValidator()
|
nautobot/core/releases.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from django.core.cache import cache
|
|
4
4
|
|
|
5
5
|
from nautobot.core.utils.config import get_settings_or_config
|
|
6
6
|
from nautobot.core.tasks import get_releases
|
|
@@ -18,15 +18,13 @@ def get_latest_release(pre_releases=False):
|
|
|
18
18
|
"""
|
|
19
19
|
if get_settings_or_config("RELEASE_CHECK_URL"):
|
|
20
20
|
logger.debug("Checking for most recent release")
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
logger.info("Initiating background task to retrieve updated releases list")
|
|
29
|
-
get_releases.delay(pre_releases=pre_releases)
|
|
21
|
+
latest_release = cache.get("latest_release")
|
|
22
|
+
if latest_release is not None:
|
|
23
|
+
logger.debug(f"Found cached release: {latest_release}")
|
|
24
|
+
return latest_release
|
|
25
|
+
# Get the releases in the background worker, it will fill the cache
|
|
26
|
+
logger.info("Initiating background task to retrieve updated releases list")
|
|
27
|
+
get_releases.delay(pre_releases=pre_releases)
|
|
30
28
|
|
|
31
29
|
else:
|
|
32
30
|
logger.debug("Skipping release check; RELEASE_CHECK_URL not defined")
|
nautobot/core/settings.py
CHANGED
|
@@ -13,7 +13,7 @@ from nautobot.core.settings_funcs import is_truthy, parse_redis_connection, Cons
|
|
|
13
13
|
# Environment setup
|
|
14
14
|
#
|
|
15
15
|
|
|
16
|
-
# This is used for display in the UI.
|
|
16
|
+
# This is used for display in the UI. There are also VERSION_MAJOR and VERSION_MINOR derived from this later.
|
|
17
17
|
VERSION = __version__
|
|
18
18
|
|
|
19
19
|
# Hostname of the system. This is displayed in the web UI footers along with the
|
|
@@ -59,6 +59,9 @@ ALLOWED_URL_SCHEMES = (
|
|
|
59
59
|
# Base directory wherein all created files (jobs, git repositories, file uploads, static files) will be stored)
|
|
60
60
|
NAUTOBOT_ROOT = os.getenv("NAUTOBOT_ROOT", os.path.expanduser("~/.nautobot"))
|
|
61
61
|
|
|
62
|
+
# The directory where the Nautobot UI packaging is stored.
|
|
63
|
+
NAUTOBOT_UI_DIR = os.path.join(NAUTOBOT_ROOT, "ui")
|
|
64
|
+
|
|
62
65
|
# Disable linking of Config Context objects via Dynamic Groups by default. This could cause performance impacts
|
|
63
66
|
# when a large number of dynamic groups are present
|
|
64
67
|
CONFIG_CONTEXT_DYNAMIC_GROUPS_ENABLED = is_truthy(os.getenv("NAUTOBOT_CONFIG_CONTEXT_DYNAMIC_GROUPS_ENABLED", "False"))
|
|
@@ -110,7 +113,7 @@ SOCIAL_AUTH_BACKEND_PREFIX = "social_core.backends"
|
|
|
110
113
|
SANITIZER_PATTERNS = [
|
|
111
114
|
# General removal of username-like and password-like tokens
|
|
112
115
|
(re.compile(r"(https?://)?\S+\s*@", re.IGNORECASE), r"\1{replacement}@"),
|
|
113
|
-
(re.compile(r"(username|password|passwd|pwd)(
|
|
116
|
+
(re.compile(r"(username|password|passwd|pwd)((?:\s+is.?|:)?\s+)\S+", re.IGNORECASE), r"\1\2{replacement}"),
|
|
114
117
|
]
|
|
115
118
|
|
|
116
119
|
# Storage
|
|
@@ -161,11 +164,11 @@ STRICT_FILTERING = is_truthy(os.getenv("NAUTOBOT_STRICT_FILTERING", "True"))
|
|
|
161
164
|
#
|
|
162
165
|
|
|
163
166
|
REST_FRAMEWORK_VERSION = VERSION.rsplit(".", 1)[0] # Use major.minor as API version
|
|
164
|
-
|
|
167
|
+
VERSION_MAJOR, VERSION_MINOR = [int(v) for v in REST_FRAMEWORK_VERSION.split(".")]
|
|
165
168
|
# We support all major.minor API versions from 2.0 to the present latest version.
|
|
166
169
|
# Similar logic exists in tasks.py, please keep them in sync!
|
|
167
|
-
assert
|
|
168
|
-
REST_FRAMEWORK_ALLOWED_VERSIONS = [f"{
|
|
170
|
+
assert VERSION_MAJOR == 2, f"REST_FRAMEWORK_ALLOWED_VERSIONS needs to be updated to handle version {VERSION_MAJOR}"
|
|
171
|
+
REST_FRAMEWORK_ALLOWED_VERSIONS = [f"{VERSION_MAJOR}.{minor}" for minor in range(0, VERSION_MINOR + 1)]
|
|
169
172
|
|
|
170
173
|
REST_FRAMEWORK = {
|
|
171
174
|
"ALLOWED_VERSIONS": REST_FRAMEWORK_ALLOWED_VERSIONS,
|
|
@@ -173,20 +176,27 @@ REST_FRAMEWORK = {
|
|
|
173
176
|
"rest_framework.authentication.SessionAuthentication",
|
|
174
177
|
"nautobot.core.api.authentication.TokenAuthentication",
|
|
175
178
|
),
|
|
176
|
-
"DEFAULT_FILTER_BACKENDS": (
|
|
179
|
+
"DEFAULT_FILTER_BACKENDS": (
|
|
180
|
+
"nautobot.core.api.filter_backends.NautobotFilterBackend",
|
|
181
|
+
"rest_framework.filters.OrderingFilter",
|
|
182
|
+
),
|
|
177
183
|
"DEFAULT_METADATA_CLASS": "nautobot.core.api.metadata.NautobotMetadata",
|
|
178
184
|
"DEFAULT_PAGINATION_CLASS": "nautobot.core.api.pagination.OptionalLimitOffsetPagination",
|
|
179
185
|
"DEFAULT_PERMISSION_CLASSES": ("nautobot.core.api.authentication.TokenPermissions",),
|
|
180
186
|
"DEFAULT_RENDERER_CLASSES": (
|
|
181
|
-
"
|
|
187
|
+
"nautobot.core.api.renderers.NautobotJSONRenderer",
|
|
182
188
|
"nautobot.core.api.renderers.FormlessBrowsableAPIRenderer",
|
|
189
|
+
"nautobot.core.api.renderers.NautobotCSVRenderer",
|
|
190
|
+
),
|
|
191
|
+
"DEFAULT_PARSER_CLASSES": (
|
|
192
|
+
"rest_framework.parsers.JSONParser",
|
|
193
|
+
"nautobot.core.api.parsers.NautobotCSVParser",
|
|
183
194
|
),
|
|
184
|
-
"DEFAULT_PARSER_CLASSES": ("rest_framework.parsers.JSONParser",),
|
|
185
195
|
"DEFAULT_SCHEMA_CLASS": "nautobot.core.api.schema.NautobotAutoSchema",
|
|
186
|
-
# Version to use if the client doesn't request otherwise.
|
|
187
|
-
|
|
188
|
-
"DEFAULT_VERSION": "2.0",
|
|
196
|
+
# Version to use if the client doesn't request otherwise. Default to current (i.e. latest)
|
|
197
|
+
"DEFAULT_VERSION": REST_FRAMEWORK_VERSION,
|
|
189
198
|
"DEFAULT_VERSIONING_CLASS": "nautobot.core.api.versioning.NautobotAPIVersioning",
|
|
199
|
+
"ORDERING_PARAM": "sort", # This is not meant to be changed by users, but is used internally by the API
|
|
190
200
|
"PAGE_SIZE": None,
|
|
191
201
|
"SCHEMA_COERCE_METHOD_NAMES": {
|
|
192
202
|
# Default mappings
|
|
@@ -266,7 +276,10 @@ DATABASES = {
|
|
|
266
276
|
"HOST": os.getenv("NAUTOBOT_DB_HOST", "localhost"),
|
|
267
277
|
"PORT": os.getenv("NAUTOBOT_DB_PORT", ""),
|
|
268
278
|
"CONN_MAX_AGE": int(os.getenv("NAUTOBOT_DB_TIMEOUT", "300")),
|
|
269
|
-
"ENGINE": os.getenv(
|
|
279
|
+
"ENGINE": os.getenv(
|
|
280
|
+
"NAUTOBOT_DB_ENGINE",
|
|
281
|
+
"django_prometheus.db.backends.postgresql" if METRICS_ENABLED else "django.db.backends.postgresql",
|
|
282
|
+
),
|
|
270
283
|
}
|
|
271
284
|
}
|
|
272
285
|
|
|
@@ -287,13 +300,18 @@ DEBUG = is_truthy(os.getenv("NAUTOBOT_DEBUG", "False"))
|
|
|
287
300
|
INTERNAL_IPS = ("127.0.0.1", "::1")
|
|
288
301
|
FORCE_SCRIPT_NAME = None
|
|
289
302
|
|
|
290
|
-
TESTING =
|
|
303
|
+
TESTING = "test" in sys.argv
|
|
291
304
|
|
|
292
305
|
LOG_LEVEL = "DEBUG" if DEBUG else "INFO"
|
|
293
306
|
|
|
294
307
|
if TESTING:
|
|
295
|
-
#
|
|
296
|
-
LOGGING = {
|
|
308
|
+
# Log to null handler instead of stderr during testing
|
|
309
|
+
LOGGING = {
|
|
310
|
+
"version": 1,
|
|
311
|
+
"disable_existing_loggers": False,
|
|
312
|
+
"handlers": {"console": {"level": "INFO", "class": "logging.NullHandler"}},
|
|
313
|
+
"loggers": {"nautobot": {"handlers": ["console"], "level": "INFO"}},
|
|
314
|
+
}
|
|
297
315
|
else:
|
|
298
316
|
LOGGING = {
|
|
299
317
|
"version": 1,
|
|
@@ -350,7 +368,6 @@ INSTALLED_APPS = [
|
|
|
350
368
|
"django.contrib.messages",
|
|
351
369
|
"django.contrib.staticfiles",
|
|
352
370
|
"django.contrib.humanize",
|
|
353
|
-
"cacheops", # v2 TODO(jathan); Remove cacheops.
|
|
354
371
|
"corsheaders",
|
|
355
372
|
"django_filters",
|
|
356
373
|
"django_jinja",
|
|
@@ -465,7 +482,10 @@ X_FRAME_OPTIONS = "DENY"
|
|
|
465
482
|
# Static files (CSS, JavaScript, Images)
|
|
466
483
|
STATIC_ROOT = os.path.join(NAUTOBOT_ROOT, "static")
|
|
467
484
|
STATIC_URL = "static/"
|
|
468
|
-
STATICFILES_DIRS = (
|
|
485
|
+
STATICFILES_DIRS = (
|
|
486
|
+
os.path.join(BASE_DIR, "project-static"),
|
|
487
|
+
os.path.join(NAUTOBOT_UI_DIR, "build", "static"),
|
|
488
|
+
)
|
|
469
489
|
|
|
470
490
|
# Media
|
|
471
491
|
MEDIA_URL = "media/"
|
|
@@ -629,31 +649,14 @@ GRAPHQL_COMPUTED_FIELD_PREFIX = "cpf"
|
|
|
629
649
|
# Caching
|
|
630
650
|
#
|
|
631
651
|
|
|
632
|
-
# v2 TODO(jathan): Remove all cacheops settings.
|
|
633
|
-
# The django-cacheops plugin is used to cache querysets. The built-in Django
|
|
634
|
-
# caching is not used.
|
|
635
|
-
CACHEOPS = {
|
|
636
|
-
"auth.user": {"ops": "get", "timeout": 60 * 15},
|
|
637
|
-
"auth.*": {"ops": ("fetch", "get")},
|
|
638
|
-
"auth.permission": {"ops": "all"},
|
|
639
|
-
"circuits.*": {"ops": "all"},
|
|
640
|
-
"dcim.*": {"ops": "all"},
|
|
641
|
-
"ipam.*": {"ops": "all"},
|
|
642
|
-
"extras.*": {"ops": "all"},
|
|
643
|
-
"users.*": {"ops": "all"},
|
|
644
|
-
"tenancy.*": {"ops": "all"},
|
|
645
|
-
"virtualization.*": {"ops": "all"},
|
|
646
|
-
}
|
|
647
|
-
CACHEOPS_DEGRADE_ON_FAILURE = True
|
|
648
|
-
CACHEOPS_ENABLED = is_truthy(os.getenv("NAUTOBOT_CACHEOPS_ENABLED", "False"))
|
|
649
|
-
CACHEOPS_REDIS = os.getenv("NAUTOBOT_CACHEOPS_REDIS", parse_redis_connection(redis_database=1))
|
|
650
|
-
CACHEOPS_DEFAULTS = {"timeout": int(os.getenv("NAUTOBOT_CACHEOPS_TIMEOUT", "900"))}
|
|
651
|
-
|
|
652
652
|
# The django-redis cache is used to establish concurrent locks using Redis.
|
|
653
653
|
CACHES = {
|
|
654
654
|
"default": {
|
|
655
|
-
"BACKEND":
|
|
656
|
-
|
|
655
|
+
"BACKEND": os.getenv(
|
|
656
|
+
"NAUTOBOT_CACHES_BACKEND",
|
|
657
|
+
"django_prometheus.cache.backends.redis.RedisCache" if METRICS_ENABLED else "django_redis.cache.RedisCache",
|
|
658
|
+
),
|
|
659
|
+
"LOCATION": parse_redis_connection(redis_database=1),
|
|
657
660
|
"TIMEOUT": 300,
|
|
658
661
|
"OPTIONS": {
|
|
659
662
|
"CLIENT_CLASS": "django_redis.client.DefaultClient",
|
|
@@ -678,15 +681,18 @@ CELERY_RESULT_EXTENDED = True
|
|
|
678
681
|
# A value of None or 0 means results will never expire (depending on backend specifications).
|
|
679
682
|
CELERY_RESULT_EXPIRES = None
|
|
680
683
|
|
|
681
|
-
# If set to True, result messages will be persistent. This means the messages won’t be lost after a broker restart.
|
|
682
|
-
CELERY_RESULT_PERSISTENT = True
|
|
683
|
-
|
|
684
684
|
# Instruct celery to report the started status of a job, instead of just `pending`, `finished`, or `failed`
|
|
685
685
|
CELERY_TASK_TRACK_STARTED = True
|
|
686
686
|
|
|
687
687
|
# If enabled, a `task-sent` event will be sent for every task so tasks can be tracked before they’re consumed by a worker.
|
|
688
688
|
CELERY_TASK_SEND_SENT_EVENT = True
|
|
689
689
|
|
|
690
|
+
# If enabled stdout and stderr of running jobs will be redirected to the task logger.
|
|
691
|
+
CELERY_WORKER_REDIRECT_STDOUTS = is_truthy(os.getenv("NAUTOBOT_CELERY_WORKER_REDIRECT_STDOUTS", "True"))
|
|
692
|
+
|
|
693
|
+
# The log level of log messages generated by redirected job stdout and stderr. Can be one of `DEBUG`, `INFO`, `WARNING`, `ERROR`, or `CRITICAL`.
|
|
694
|
+
CELERY_WORKER_REDIRECT_STDOUTS_LEVEL = os.getenv("NAUTOBOT_CELERY_WORKER_REDIRECT_STDOUTS_LEVEL", "WARNING")
|
|
695
|
+
|
|
690
696
|
# Send task-related events so that tasks can be monitored using tools like flower. Sets the default value for the workers -E argument.
|
|
691
697
|
CELERY_WORKER_SEND_TASK_EVENTS = True
|
|
692
698
|
|
|
@@ -783,3 +789,35 @@ def UI_RACK_VIEW_TRUNCATE_FUNCTION(device_display_name):
|
|
|
783
789
|
:type: str
|
|
784
790
|
"""
|
|
785
791
|
return str(device_display_name).split(".")[0]
|
|
792
|
+
|
|
793
|
+
|
|
794
|
+
# Custom JSON schema serializer field type mappingss. These will be added to
|
|
795
|
+
# `NautobotProcessingMixin.TYPE_MAP`.
|
|
796
|
+
# Format: `{serializer_field_class.__name__}` => `{json_schema_type}`
|
|
797
|
+
# See: https://github.com/yoyowallet/drf-react-template-framework#settings
|
|
798
|
+
DRF_REACT_TEMPLATE_TYPE_MAP = {
|
|
799
|
+
"ContentTypeField": {"type": "string", "enum": "choices"},
|
|
800
|
+
"CustomFieldsDataField": {"type": "object", "widget": "textarea"},
|
|
801
|
+
"DateTimeField": {"type": "string", "format": "date-time", "widget": "date-time"},
|
|
802
|
+
"ImageField": {"type": "string", "format": "data-url"},
|
|
803
|
+
"IPFieldSerializer": {"type": "string"},
|
|
804
|
+
"JSONField": {"type": "string", "widget": "textarea"},
|
|
805
|
+
"MultipleChoiceJSONField": {"type": "array", "required": [], "enum": "choices"},
|
|
806
|
+
"ManyRelatedField": {"type": "array", "required": []},
|
|
807
|
+
#
|
|
808
|
+
# Foreign Key fields
|
|
809
|
+
#
|
|
810
|
+
# enum=choices is the one that works in the UI as a related field but it
|
|
811
|
+
# includes ALL related objects in the schema.
|
|
812
|
+
# "NautobotHyperlinkedRelatedField": {"type": "string", "enum": "choices"},
|
|
813
|
+
# readOnly=True disables the fields in the UI; not what we want.
|
|
814
|
+
# "NautobotHyperlinkedRelatedField": {"type": "string", "readOnly": True},
|
|
815
|
+
# type=string results in a free text field; also not what we want. For now,
|
|
816
|
+
# however, this will keep things moving so the unit tests pass.
|
|
817
|
+
"NautobotHyperlinkedRelatedField": {"type": "string", "format": "uuid"},
|
|
818
|
+
"PrimaryKeyRelatedField": {"type": "string", "enum": "choices"},
|
|
819
|
+
"RelationshipsDataField": {"type": "object"},
|
|
820
|
+
"SlugField": {"type": "string"},
|
|
821
|
+
"TimeZoneSerializerField": {"type": "string"},
|
|
822
|
+
"UUIDField": {"type": "string", "format": "uuid"},
|
|
823
|
+
}
|
nautobot/core/tables.py
CHANGED
|
@@ -37,21 +37,21 @@ class BaseTable(django_tables2.Table):
|
|
|
37
37
|
self.base_columns[name] = CustomFieldColumn(cf)
|
|
38
38
|
|
|
39
39
|
for cpf in models.ComputedField.objects.filter(content_type=obj_type):
|
|
40
|
-
self.base_columns[f"cpf_{cpf.
|
|
40
|
+
self.base_columns[f"cpf_{cpf.key}"] = ComputedFieldColumn(cpf)
|
|
41
41
|
|
|
42
42
|
for relationship in models.Relationship.objects.filter(source_type=obj_type):
|
|
43
43
|
if not relationship.symmetric:
|
|
44
|
-
self.base_columns[f"cr_{relationship.
|
|
44
|
+
self.base_columns[f"cr_{relationship.key}_src"] = RelationshipColumn(
|
|
45
45
|
relationship, side=choices.RelationshipSideChoices.SIDE_SOURCE
|
|
46
46
|
)
|
|
47
47
|
else:
|
|
48
|
-
self.base_columns[f"cr_{relationship.
|
|
48
|
+
self.base_columns[f"cr_{relationship.key}_peer"] = RelationshipColumn(
|
|
49
49
|
relationship, side=choices.RelationshipSideChoices.SIDE_PEER
|
|
50
50
|
)
|
|
51
51
|
|
|
52
52
|
for relationship in models.Relationship.objects.filter(destination_type=obj_type):
|
|
53
53
|
if not relationship.symmetric:
|
|
54
|
-
self.base_columns[f"cr_{relationship.
|
|
54
|
+
self.base_columns[f"cr_{relationship.key}_dst"] = RelationshipColumn(
|
|
55
55
|
relationship, side=choices.RelationshipSideChoices.SIDE_DESTINATION
|
|
56
56
|
)
|
|
57
57
|
# symmetric relationships are already handled above in the source_type case
|
|
@@ -443,7 +443,7 @@ class RelationshipColumn(django_tables2.Column):
|
|
|
443
443
|
template += format_html(
|
|
444
444
|
'<a href="{}?relationship={}&{}_id={}">{} {}</a>',
|
|
445
445
|
reverse("extras:relationshipassociation_list"),
|
|
446
|
-
self.relationship.
|
|
446
|
+
self.relationship.key,
|
|
447
447
|
self.side,
|
|
448
448
|
record.id,
|
|
449
449
|
len(value),
|
nautobot/core/tasks.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
|
-
from cacheops.simple import CacheMiss, cache
|
|
4
3
|
from django.conf import settings
|
|
4
|
+
from django.core.cache import cache
|
|
5
5
|
from packaging import version
|
|
6
6
|
import requests
|
|
7
7
|
|
|
@@ -21,12 +21,9 @@ def get_releases(pre_releases=False):
|
|
|
21
21
|
releases = []
|
|
22
22
|
|
|
23
23
|
# Check whether this URL has failed recently and shouldn't be retried yet
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return []
|
|
28
|
-
except CacheMiss:
|
|
29
|
-
pass
|
|
24
|
+
if url == cache.get("latest_release_no_retry"):
|
|
25
|
+
logger.info(f"Skipping release check; URL failed recently: {url}")
|
|
26
|
+
return []
|
|
30
27
|
|
|
31
28
|
try:
|
|
32
29
|
logger.debug(f"Fetching new releases from {url}")
|
|
@@ -1,49 +1 @@
|
|
|
1
|
-
{%
|
|
2
|
-
{% load helpers %}
|
|
3
|
-
{% load plugins %}
|
|
4
|
-
|
|
5
|
-
<!DOCTYPE html>
|
|
6
|
-
<html lang="en"{% if request.COOKIES|get_item:"theme" == 'dark' %} data-theme="dark"{% endif %}>
|
|
7
|
-
<head>
|
|
8
|
-
<title>{% block title %}Home{% endblock %} - {{ settings.BRANDING_TITLE }}</title>
|
|
9
|
-
{% include 'inc/media.html' %}
|
|
10
|
-
{% block extra_styles %}{% endblock %}
|
|
11
|
-
</head>
|
|
12
|
-
<body>
|
|
13
|
-
{% include 'inc/nav_menu.html' %}
|
|
14
|
-
<div class="container-fluid wrapper">
|
|
15
|
-
{% if "BANNER_TOP"|settings_or_config %}
|
|
16
|
-
<div class="alert alert-info text-center" role="alert">
|
|
17
|
-
{{ "BANNER_TOP"|settings_or_config|safe }}
|
|
18
|
-
</div>
|
|
19
|
-
{% endif %}
|
|
20
|
-
{% if settings.MAINTENANCE_MODE %}
|
|
21
|
-
<div class="alert alert-warning text-center" role="alert">
|
|
22
|
-
<h4><i class="mdi mdi-alert"></i> Maintenance Mode</h4>
|
|
23
|
-
<p>Nautobot is currently in maintenance mode. Functionality may be limited.</p>
|
|
24
|
-
</div>
|
|
25
|
-
{% endif %}
|
|
26
|
-
{% plugin_banners %}
|
|
27
|
-
{% for message in messages %}
|
|
28
|
-
<div class="alert alert-{{ message.tags }} alert-dismissable" role="alert">
|
|
29
|
-
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
|
30
|
-
<span>×</span>
|
|
31
|
-
</button>
|
|
32
|
-
{{ message }}
|
|
33
|
-
</div>
|
|
34
|
-
{% endfor %}
|
|
35
|
-
{% block header %}{% endblock header %}
|
|
36
|
-
{% block content %}{% endblock content %}
|
|
37
|
-
<div class="push"></div>
|
|
38
|
-
{% if "BANNER_BOTTOM"|settings_or_config %}
|
|
39
|
-
<div class="alert alert-info text-center banner-bottom" role="alert">
|
|
40
|
-
{{ "BANNER_BOTTOM"|settings_or_config|safe }}
|
|
41
|
-
</div>
|
|
42
|
-
{% endif %}
|
|
43
|
-
</div>
|
|
44
|
-
{% include 'modals/modal_theme.html' with name='theme'%}
|
|
45
|
-
{% include 'inc/footer.html' %}
|
|
46
|
-
{% include 'inc/javascript.html' %}
|
|
47
|
-
{% block javascript %}{% endblock %}
|
|
48
|
-
</body>
|
|
49
|
-
</html>
|
|
1
|
+
{% extends root_template|default:'base_django.html' %}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{% load static %}
|
|
2
|
+
{% load helpers %}
|
|
3
|
+
{% load plugins %}
|
|
4
|
+
|
|
5
|
+
<!DOCTYPE html>
|
|
6
|
+
<html lang="en"{% if request.COOKIES|get_item:"theme" == 'dark' %} data-theme="dark"{% endif %}>
|
|
7
|
+
<head>
|
|
8
|
+
<title>{% block title %}Home{% endblock %} - {{ settings.BRANDING_TITLE }}</title>
|
|
9
|
+
{% include 'inc/media.html' %}
|
|
10
|
+
{% block extra_styles %}{% endblock %}
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
{% include 'inc/nav_menu.html' %}
|
|
14
|
+
<div class="container-fluid wrapper">
|
|
15
|
+
{% if "BANNER_TOP"|settings_or_config %}
|
|
16
|
+
<div class="alert alert-info text-center" role="alert">
|
|
17
|
+
{{ "BANNER_TOP"|settings_or_config|safe }}
|
|
18
|
+
</div>
|
|
19
|
+
{% endif %}
|
|
20
|
+
{% if settings.MAINTENANCE_MODE %}
|
|
21
|
+
<div class="alert alert-warning text-center" role="alert">
|
|
22
|
+
<h4><i class="mdi mdi-alert"></i> Maintenance Mode</h4>
|
|
23
|
+
<p>Nautobot is currently in maintenance mode. Functionality may be limited.</p>
|
|
24
|
+
</div>
|
|
25
|
+
{% endif %}
|
|
26
|
+
{% plugin_banners %}
|
|
27
|
+
{% for message in messages %}
|
|
28
|
+
<div class="alert alert-{{ message.tags }} alert-dismissable" role="alert">
|
|
29
|
+
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
|
30
|
+
<span>×</span>
|
|
31
|
+
</button>
|
|
32
|
+
{{ message }}
|
|
33
|
+
</div>
|
|
34
|
+
{% endfor %}
|
|
35
|
+
{% block header %}{% endblock header %}
|
|
36
|
+
{% block content %}{% endblock content %}
|
|
37
|
+
<div class="push"></div>
|
|
38
|
+
{% if "BANNER_BOTTOM"|settings_or_config %}
|
|
39
|
+
<div class="alert alert-info text-center banner-bottom" role="alert">
|
|
40
|
+
{{ "BANNER_BOTTOM"|settings_or_config|safe }}
|
|
41
|
+
</div>
|
|
42
|
+
{% endif %}
|
|
43
|
+
</div>
|
|
44
|
+
{% include 'modals/modal_theme.html' with name='theme'%}
|
|
45
|
+
{% include 'inc/footer.html' %}
|
|
46
|
+
{% include 'inc/javascript.html' %}
|
|
47
|
+
{% block javascript %}{% endblock %}
|
|
48
|
+
</body>
|
|
49
|
+
</html>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{% load static %}
|
|
2
|
+
{% load helpers %}
|
|
3
|
+
{% load plugins %}
|
|
4
|
+
<!DOCTYPE html>
|
|
5
|
+
<html lang="en">
|
|
6
|
+
<head>
|
|
7
|
+
<meta charset="utf-8" />
|
|
8
|
+
<link rel="icon" href="/static/img/favicon.ico" />
|
|
9
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
10
|
+
<meta name="theme-color" content="#000000" />
|
|
11
|
+
<meta
|
|
12
|
+
name="description"
|
|
13
|
+
content="Web site created using create-react-app"
|
|
14
|
+
/>
|
|
15
|
+
<link rel="apple-touch-icon" href="/logo192.png" />
|
|
16
|
+
<!--
|
|
17
|
+
manifest.json provides metadata used when your web app is installed on a
|
|
18
|
+
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
|
19
|
+
-->
|
|
20
|
+
<link rel="manifest" href="{% static 'asset-manifest.json' %}" />
|
|
21
|
+
<link
|
|
22
|
+
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
|
|
23
|
+
rel="stylesheet"
|
|
24
|
+
/>
|
|
25
|
+
<!--
|
|
26
|
+
Notice the use of %PUBLIC_URL% in the tags above.
|
|
27
|
+
It will be replaced with the URL of the `public` folder during the build.
|
|
28
|
+
Only files inside the `public` folder can be referenced from the HTML.
|
|
29
|
+
|
|
30
|
+
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
|
31
|
+
work correctly both with client-side routing and a non-root public URL.
|
|
32
|
+
Learn how to configure a non-root public URL by running `npm run build`.
|
|
33
|
+
-->
|
|
34
|
+
<title>{{ settings.BRANDING_TITLE }}</title>
|
|
35
|
+
<script defer src="{% static 'js/main.js' %}"></script>
|
|
36
|
+
<link href="{% static 'css/main.css' %}" rel="stylesheet">
|
|
37
|
+
</head>
|
|
38
|
+
<body>
|
|
39
|
+
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
40
|
+
<div id="root"></div>
|
|
41
|
+
<div id="legacy-content" style="display:none">
|
|
42
|
+
{% block content %}{% endblock content %}
|
|
43
|
+
</div>
|
|
44
|
+
<!--
|
|
45
|
+
This HTML file is a template.
|
|
46
|
+
If you open it directly in the browser, you will see an empty page.
|
|
47
|
+
|
|
48
|
+
You can add webfonts, meta tags, or analytics to this file.
|
|
49
|
+
The build step will place the bundled scripts into the <body> tag.
|
|
50
|
+
|
|
51
|
+
To begin the development, run `npm start` or `yarn start`.
|
|
52
|
+
To create a production bundle, use `npm run build` or `yarn build`.
|
|
53
|
+
-->
|
|
54
|
+
</body>
|
|
55
|
+
</html>
|
|
@@ -5,15 +5,17 @@
|
|
|
5
5
|
Export <span class="caret"></span>
|
|
6
6
|
</button>
|
|
7
7
|
<ul class="dropdown-menu dropdown-menu-right">
|
|
8
|
-
|
|
8
|
+
{% if export_url %}
|
|
9
|
+
<li><a href="{{ export_url }}?{% if url_params %}{{ url_params.urlencode }}&{% endif %}format=csv">Default format</a></li>
|
|
10
|
+
{% endif %}
|
|
9
11
|
<li class="divider"></li>
|
|
10
12
|
{% for et in export_templates %}
|
|
11
13
|
<li><a href="?{% if url_params %}{{ url_params.urlencode }}&{% endif %}export={{ et.name }}"{% if et.description %} title="{{ et.description }}"{% endif %}>{{ et.name }}</a></li>
|
|
12
14
|
{% endfor %}
|
|
13
15
|
</ul>
|
|
14
16
|
</div>
|
|
15
|
-
{%
|
|
16
|
-
|
|
17
|
+
{% elif export_url %}
|
|
18
|
+
<a href="{{ export_url }}?{% if url_params %}{{ url_params.urlencode }}&{% endif %}format=csv" class="btn btn-success">
|
|
17
19
|
<span class="mdi mdi-database-export" aria-hidden="true"></span> Export
|
|
18
20
|
</a>
|
|
19
|
-
{% endif %}
|
|
21
|
+
{% endif %}
|
|
@@ -80,37 +80,29 @@
|
|
|
80
80
|
<tr>
|
|
81
81
|
<th>Field</th>
|
|
82
82
|
<th>Required</th>
|
|
83
|
-
<th>Accessor</th>
|
|
84
83
|
<th>Description</th>
|
|
85
84
|
</tr>
|
|
86
|
-
{% for
|
|
85
|
+
{% for field in fields %}
|
|
87
86
|
<tr>
|
|
88
87
|
<td>
|
|
89
|
-
<code>{{ name }}</code>
|
|
88
|
+
<code>{{ field.name }}</code>
|
|
90
89
|
</td>
|
|
91
90
|
<td>{{ field.required | render_boolean }}</td>
|
|
92
91
|
<td>
|
|
93
|
-
{% if field.
|
|
94
|
-
<
|
|
95
|
-
{% else %}
|
|
96
|
-
<span class="text-muted">—</span>
|
|
97
|
-
{% endif %}
|
|
98
|
-
</td>
|
|
99
|
-
<td>
|
|
100
|
-
{% if field.STATIC_CHOICES %}
|
|
101
|
-
<button type="button" class="btn btn-link btn-xs pull-right" data-toggle="modal" data-target="#{{ name }}_choices">
|
|
92
|
+
{% if field.choices %}
|
|
93
|
+
<button type="button" class="btn btn-link btn-xs pull-right" data-toggle="modal" data-target="#{{ field.name }}_choices">
|
|
102
94
|
<i class="mdi mdi-help-circle"></i>
|
|
103
95
|
</button>
|
|
104
|
-
<div class="modal fade" id="{{ name }}_choices" tabindex="-1" role="dialog">
|
|
96
|
+
<div class="modal fade" id="{{ field.name }}_choices" tabindex="-1" role="dialog">
|
|
105
97
|
<div class="modal-dialog" role="document">
|
|
106
98
|
<div class="modal-content">
|
|
107
99
|
<div class="modal-header">
|
|
108
100
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
|
109
|
-
<h4 class="modal-title"><code>{{ name }}</code> Choices</h4>
|
|
101
|
+
<h4 class="modal-title"><code>{{ field.name }}</code> Choices</h4>
|
|
110
102
|
</div>
|
|
111
103
|
<table class="table table-striped modal-body">
|
|
112
104
|
<tr><th>Import Value</th><th>Label</th></tr>
|
|
113
|
-
{% for value, label in field.choices %}
|
|
105
|
+
{% for value, label in field.choices.items %}
|
|
114
106
|
{% if value %}<tr><td><samp>{{ value }}</samp></td><td>{{ label }}</td></tr>{% endif %}
|
|
115
107
|
{% endfor %}
|
|
116
108
|
</table>
|
|
@@ -123,10 +115,8 @@
|
|
|
123
115
|
{% elif field.label %}
|
|
124
116
|
{{ field.label }}<br />
|
|
125
117
|
{% endif %}
|
|
126
|
-
{% if field
|
|
127
|
-
<small class="text-muted">Format:
|
|
128
|
-
{% elif field|widget_type == 'checkboxinput' %}
|
|
129
|
-
<small class="text-muted">Specify "true" or "false"</small>
|
|
118
|
+
{% if field.format %}
|
|
119
|
+
<small class="text-muted">Format: {{ field.format }}</small>
|
|
130
120
|
{% endif %}
|
|
131
121
|
</td>
|
|
132
122
|
</tr>
|
|
@@ -138,8 +128,7 @@
|
|
|
138
128
|
objects.
|
|
139
129
|
</p>
|
|
140
130
|
<p class="small text-muted">
|
|
141
|
-
<i class="mdi mdi-information-outline"></i> Related objects
|
|
142
|
-
For example, <code>vrf.rd</code> would identify a VRF by its route distinguisher.
|
|
131
|
+
<i class="mdi mdi-information-outline"></i> Related objects must be referenced by their natural key slugs. You can find this information in the "Advanced" tab of any object's detail view.
|
|
143
132
|
</p>
|
|
144
133
|
{% endif %}
|
|
145
134
|
</div>
|
|
@@ -49,7 +49,9 @@
|
|
|
49
49
|
{% import_button content_type.model_class|validated_viewname:"import" %}
|
|
50
50
|
{% endif %}
|
|
51
51
|
{% if 'export' in action_buttons %}
|
|
52
|
-
{% export_button
|
|
52
|
+
{% block export_button %}
|
|
53
|
+
{% export_button content_type %}
|
|
54
|
+
{% endblock export_button %}
|
|
53
55
|
{% endif %}
|
|
54
56
|
</div>
|
|
55
57
|
<h1>{% block title %}{{ title }}{% endblock %}</h1>
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
</div>
|
|
17
17
|
<div class="col-xs-4 text-right noprint">
|
|
18
18
|
<p class="text-muted">
|
|
19
|
+
<i class="mdi mdi-new-box text-primary"></i> <a href="#" onclick="viewNewUI();">View in New UI</a> ·
|
|
19
20
|
<a href="#theme_modal" data-toggle="modal" data-target="#theme_modal" id="btn-theme-modal"><i class="mdi mdi-theme-light-dark text-primary"></i>Theme</a> ·
|
|
20
21
|
<i class="mdi mdi-book-open-page-variant text-primary"></i>
|
|
21
22
|
{% if settings.BRANDING_URLS.docs %}
|
|
@@ -37,18 +37,4 @@
|
|
|
37
37
|
window.addEventListener("resize", setBodyPaddingTop);
|
|
38
38
|
window.addEventListener("load", setBodyPaddingTop);
|
|
39
39
|
|
|
40
|
-
/*
|
|
41
|
-
Dropdown menu overflow screen view control
|
|
42
|
-
*/
|
|
43
|
-
$(".dropdown .dropdown-toggle").on("click", function(){
|
|
44
|
-
var dropdown = $(this).next("ul");
|
|
45
|
-
var distanceOfDropDownFromNavStart = $(this).offset().left + dropdown.width();
|
|
46
|
-
var navBarWidth = $(".nav.navbar-nav").width();
|
|
47
|
-
var isEntirelyVisible = (distanceOfDropDownFromNavStart <= navBarWidth);
|
|
48
|
-
|
|
49
|
-
if (!isEntirelyVisible)
|
|
50
|
-
dropdown.addClass('edge');
|
|
51
|
-
else
|
|
52
|
-
dropdown.removeClass('edge');
|
|
53
|
-
})
|
|
54
40
|
</script>
|