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
|
@@ -5,6 +5,7 @@ import logging
|
|
|
5
5
|
import mimetypes
|
|
6
6
|
import os
|
|
7
7
|
import re
|
|
8
|
+
import sys
|
|
8
9
|
from urllib.parse import quote
|
|
9
10
|
|
|
10
11
|
from django.conf import settings
|
|
@@ -14,13 +15,10 @@ from django.db import transaction
|
|
|
14
15
|
from django.utils.text import slugify
|
|
15
16
|
import yaml
|
|
16
17
|
|
|
17
|
-
from nautobot.core.celery import
|
|
18
|
+
from nautobot.core.celery import app as celery_app
|
|
18
19
|
from nautobot.core.utils.git import GitRepo
|
|
19
|
-
from nautobot.core.utils.requests import copy_safe_request
|
|
20
20
|
from nautobot.dcim.models import Device, DeviceType, Location, Platform
|
|
21
21
|
from nautobot.extras.choices import (
|
|
22
|
-
JobSourceChoices,
|
|
23
|
-
JobResultStatusChoices,
|
|
24
22
|
LogLevelChoices,
|
|
25
23
|
SecretsGroupAccessTypeChoices,
|
|
26
24
|
SecretsGroupSecretTypeChoices,
|
|
@@ -32,16 +30,14 @@ from nautobot.extras.models import (
|
|
|
32
30
|
ExportTemplate,
|
|
33
31
|
GitRepository,
|
|
34
32
|
Job,
|
|
35
|
-
JobLogEntry,
|
|
36
33
|
JobResult,
|
|
37
34
|
Role,
|
|
38
35
|
Tag,
|
|
39
36
|
)
|
|
40
37
|
from nautobot.extras.registry import DatasourceContent, register_datasource_contents
|
|
41
|
-
from nautobot.extras.utils import
|
|
38
|
+
from nautobot.extras.utils import refresh_job_model_from_job_class
|
|
42
39
|
from nautobot.tenancy.models import TenantGroup, Tenant
|
|
43
40
|
from nautobot.virtualization.models import ClusterGroup, Cluster, VirtualMachine
|
|
44
|
-
from .registry import refresh_datasource_content
|
|
45
41
|
from .utils import files_from_contenttype_directories
|
|
46
42
|
|
|
47
43
|
|
|
@@ -54,31 +50,29 @@ GitJobResult = namedtuple("GitJobResult", ["job_result", "repository_record"])
|
|
|
54
50
|
GitRepoInfo = namedtuple("GitRepoInfo", ["from_url", "to_path", "from_branch"])
|
|
55
51
|
|
|
56
52
|
|
|
57
|
-
def enqueue_git_repository_helper(repository,
|
|
53
|
+
def enqueue_git_repository_helper(repository, user, job_class, **kwargs):
|
|
58
54
|
"""
|
|
59
55
|
Wrapper for JobResult.enqueue_job() to enqueue one of several possible Git repository functions.
|
|
60
56
|
"""
|
|
61
|
-
|
|
62
|
-
JobResult.enqueue_job(
|
|
63
|
-
func,
|
|
64
|
-
repository.name,
|
|
65
|
-
git_repository_content_type,
|
|
66
|
-
request.user,
|
|
67
|
-
repository_pk=repository.pk,
|
|
68
|
-
request=copy_safe_request(request),
|
|
69
|
-
)
|
|
57
|
+
job_model = job_class().job_model
|
|
70
58
|
|
|
59
|
+
return JobResult.enqueue_job(job_model, user, repository=repository.pk)
|
|
71
60
|
|
|
72
|
-
|
|
61
|
+
|
|
62
|
+
def enqueue_git_repository_diff_origin_and_local(repository, user):
|
|
73
63
|
"""Convenience wrapper for JobResult.enqueue_job() to enqueue the git_repository_diff_origin_and_local job."""
|
|
74
|
-
|
|
64
|
+
from nautobot.core.jobs import GitRepositoryDryRun
|
|
65
|
+
|
|
66
|
+
return enqueue_git_repository_helper(repository, user, GitRepositoryDryRun)
|
|
75
67
|
|
|
76
68
|
|
|
77
|
-
def enqueue_pull_git_repository_and_refresh_data(repository,
|
|
69
|
+
def enqueue_pull_git_repository_and_refresh_data(repository, user):
|
|
78
70
|
"""
|
|
79
71
|
Convenience wrapper for JobResult.enqueue_job() to enqueue the pull_git_repository_and_refresh_data job.
|
|
80
72
|
"""
|
|
81
|
-
|
|
73
|
+
from nautobot.core.jobs import GitRepositorySync
|
|
74
|
+
|
|
75
|
+
return enqueue_git_repository_helper(repository, user, GitRepositorySync)
|
|
82
76
|
|
|
83
77
|
|
|
84
78
|
def get_job_result_and_repository_record(repository_pk, job_result_pk, logger): # pylint: disable=redefined-outer-name
|
|
@@ -97,121 +91,14 @@ def get_job_result_and_repository_record(repository_pk, job_result_pk, logger):
|
|
|
97
91
|
if not repository_record:
|
|
98
92
|
job_result.log(
|
|
99
93
|
f"No GitRepository {repository_pk} found!",
|
|
100
|
-
level_choice=LogLevelChoices.
|
|
94
|
+
level_choice=LogLevelChoices.LOG_ERROR,
|
|
101
95
|
logger=logger,
|
|
102
96
|
)
|
|
103
|
-
job_result.set_status(JobResultStatusChoices.STATUS_FAILURE)
|
|
104
|
-
job_result.save()
|
|
105
97
|
return GitJobResult(job_result=job_result, repository_record=None)
|
|
106
98
|
|
|
107
99
|
return GitJobResult(job_result=job_result, repository_record=repository_record)
|
|
108
100
|
|
|
109
101
|
|
|
110
|
-
# TODO(jathan): This should likely be deleted since it's coercing state and this
|
|
111
|
-
# should be managed by the database backend.
|
|
112
|
-
def log_job_result_final_status(job_result, job_type):
|
|
113
|
-
"""Check Job status and save log to DB
|
|
114
|
-
Args:
|
|
115
|
-
job_result (JobResult): JobResult Instance
|
|
116
|
-
job_type (str): job type which is used in log message, e.g dry run/synchronization etc.
|
|
117
|
-
"""
|
|
118
|
-
if job_result.status not in JobResultStatusChoices.READY_STATES:
|
|
119
|
-
if JobLogEntry.objects.filter(job_result__pk=job_result.pk, log_level=LogLevelChoices.LOG_FAILURE).exists():
|
|
120
|
-
job_result.set_status(JobResultStatusChoices.STATUS_FAILURE)
|
|
121
|
-
else:
|
|
122
|
-
job_result.set_status(JobResultStatusChoices.STATUS_SUCCESS)
|
|
123
|
-
job_result.log(
|
|
124
|
-
f"Repository {job_type} completed in {job_result.duration}",
|
|
125
|
-
level_choice=LogLevelChoices.LOG_INFO,
|
|
126
|
-
logger=logger,
|
|
127
|
-
)
|
|
128
|
-
job_result.save()
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
# TODO(jathan): The state transition stuff here should be deleted in exchange
|
|
132
|
-
# for trusting the database backend.
|
|
133
|
-
@nautobot_task
|
|
134
|
-
def pull_git_repository_and_refresh_data(repository_pk, request, job_result_pk):
|
|
135
|
-
"""
|
|
136
|
-
Worker function to clone and/or pull a Git repository into Nautobot, then invoke refresh_datasource_content().
|
|
137
|
-
"""
|
|
138
|
-
job_result, repository_record = get_job_result_and_repository_record(
|
|
139
|
-
repository_pk=repository_pk,
|
|
140
|
-
job_result_pk=job_result_pk,
|
|
141
|
-
logger=logger,
|
|
142
|
-
)
|
|
143
|
-
|
|
144
|
-
if not repository_record:
|
|
145
|
-
return
|
|
146
|
-
|
|
147
|
-
job_result.log(f'Creating/refreshing local copy of Git repository "{repository_record.name}"...', logger=logger)
|
|
148
|
-
job_result.set_status(JobResultStatusChoices.STATUS_STARTED)
|
|
149
|
-
job_result.save()
|
|
150
|
-
|
|
151
|
-
try:
|
|
152
|
-
if not os.path.exists(settings.GIT_ROOT):
|
|
153
|
-
os.makedirs(settings.GIT_ROOT)
|
|
154
|
-
|
|
155
|
-
ensure_git_repository(
|
|
156
|
-
repository_record,
|
|
157
|
-
job_result=job_result,
|
|
158
|
-
logger=logger,
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
job_result.log(
|
|
162
|
-
f'The current Git repository hash is "{repository_record.current_head}"',
|
|
163
|
-
level_choice=LogLevelChoices.LOG_INFO,
|
|
164
|
-
logger=logger,
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
refresh_datasource_content("extras.gitrepository", repository_record, request, job_result, delete=False)
|
|
168
|
-
|
|
169
|
-
except Exception as exc:
|
|
170
|
-
job_result.log(
|
|
171
|
-
f"Error while refreshing {repository_record.name}: {exc}",
|
|
172
|
-
level_choice=LogLevelChoices.LOG_FAILURE,
|
|
173
|
-
)
|
|
174
|
-
job_result.set_status(JobResultStatusChoices.STATUS_FAILURE)
|
|
175
|
-
|
|
176
|
-
finally:
|
|
177
|
-
log_job_result_final_status(job_result, "synchronization")
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
# TODO(jathan): The state transition stuff here should be deleted in exchange
|
|
181
|
-
# for trusting the database backend.
|
|
182
|
-
@nautobot_task
|
|
183
|
-
def git_repository_diff_origin_and_local(repository_pk, request, job_result_pk, **kwargs):
|
|
184
|
-
"""
|
|
185
|
-
Worker function to run a dry run on a Git repository.
|
|
186
|
-
"""
|
|
187
|
-
job_result, repository_record = get_job_result_and_repository_record(
|
|
188
|
-
repository_pk,
|
|
189
|
-
job_result_pk,
|
|
190
|
-
logger=logger,
|
|
191
|
-
)
|
|
192
|
-
if not repository_record:
|
|
193
|
-
return
|
|
194
|
-
|
|
195
|
-
job_result.log(f'Running a Dry Run on Git repository "{repository_record.name}"...', logger=logger)
|
|
196
|
-
job_result.set_status(JobResultStatusChoices.STATUS_STARTED)
|
|
197
|
-
job_result.save()
|
|
198
|
-
try:
|
|
199
|
-
if not os.path.exists(settings.GIT_ROOT):
|
|
200
|
-
os.makedirs(settings.GIT_ROOT)
|
|
201
|
-
|
|
202
|
-
git_repository_dry_run(repository_record, job_result=job_result, logger=logger)
|
|
203
|
-
|
|
204
|
-
except Exception as exc:
|
|
205
|
-
job_result.log(
|
|
206
|
-
f"Error while running a dry run on {repository_record.name}: {exc}",
|
|
207
|
-
level_choice=LogLevelChoices.LOG_FAILURE,
|
|
208
|
-
)
|
|
209
|
-
job_result.set_status(JobResultStatusChoices.STATUS_FAILURE)
|
|
210
|
-
|
|
211
|
-
finally:
|
|
212
|
-
log_job_result_final_status(job_result, "dry run")
|
|
213
|
-
|
|
214
|
-
|
|
215
102
|
def get_repo_from_url_to_path_and_from_branch(repository_record):
|
|
216
103
|
"""Returns the from_url, to_path and from_branch of a Git Repo
|
|
217
104
|
Returns:
|
|
@@ -266,43 +153,58 @@ def ensure_git_repository(
|
|
|
266
153
|
repository_record, job_result=None, logger=None, head=None # pylint: disable=redefined-outer-name
|
|
267
154
|
):
|
|
268
155
|
"""Ensure that the given Git repo is present, up-to-date, and has the correct branch selected.
|
|
269
|
-
|
|
156
|
+
|
|
157
|
+
Note that this function may be called independently of the `GitRepositorySync` job,
|
|
270
158
|
such as to ensure that different Nautobot instances and/or worker instances all have a local copy of the same HEAD.
|
|
159
|
+
|
|
271
160
|
Args:
|
|
272
161
|
repository_record (GitRepository): Repository to ensure the state of.
|
|
273
162
|
job_result (JobResult): Optional JobResult to store results into.
|
|
274
163
|
logger (logging.Logger): Optional Logger to additionally log results to.
|
|
275
164
|
head (str): Optional Git commit hash to check out instead of pulling branch latest.
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
bool: Whether any change to the local repo actually occurred.
|
|
276
168
|
"""
|
|
277
169
|
|
|
278
170
|
from_url, to_path, from_branch = get_repo_from_url_to_path_and_from_branch(repository_record)
|
|
279
171
|
|
|
280
172
|
try:
|
|
281
173
|
repo_helper = GitRepo(to_path, from_url)
|
|
282
|
-
head = repo_helper.checkout(from_branch, head)
|
|
174
|
+
head, changed = repo_helper.checkout(from_branch, head)
|
|
283
175
|
if repository_record.current_head != head:
|
|
284
176
|
repository_record.current_head = head
|
|
285
|
-
|
|
286
|
-
repository_record.save(trigger_resync=False)
|
|
177
|
+
repository_record.save()
|
|
287
178
|
|
|
179
|
+
# FIXME(jathan): As a part of jobs overhaul, this error-handling should be removed since this
|
|
180
|
+
# should only ever be called in the context of a Git sync job. Also, all logging directly from a
|
|
181
|
+
# JobResult should also be replaced with just trusting the logger to do the correct thing (such
|
|
182
|
+
# as from the Job class).
|
|
288
183
|
except Exception as exc:
|
|
289
184
|
if job_result:
|
|
290
|
-
job_result.
|
|
291
|
-
job_result.log(str(exc), level_choice=LogLevelChoices.LOG_FAILURE, logger=logger)
|
|
292
|
-
job_result.save()
|
|
185
|
+
job_result.log(str(exc), level_choice=LogLevelChoices.LOG_ERROR, logger=logger)
|
|
293
186
|
elif logger:
|
|
294
187
|
logger.error(str(exc))
|
|
295
188
|
raise
|
|
296
189
|
|
|
297
190
|
if job_result:
|
|
191
|
+
if changed:
|
|
192
|
+
job_result.log(
|
|
193
|
+
"Repository successfully refreshed",
|
|
194
|
+
level_choice=LogLevelChoices.LOG_INFO,
|
|
195
|
+
logger=logger,
|
|
196
|
+
)
|
|
298
197
|
job_result.log(
|
|
299
|
-
|
|
300
|
-
level_choice=LogLevelChoices.
|
|
198
|
+
f'The current Git repository hash is "{repository_record.current_head}"',
|
|
199
|
+
level_choice=LogLevelChoices.LOG_INFO,
|
|
301
200
|
logger=logger,
|
|
302
201
|
)
|
|
303
|
-
job_result.save()
|
|
304
202
|
elif logger:
|
|
305
|
-
|
|
203
|
+
if changed:
|
|
204
|
+
logger.info("Repository successfully refreshed")
|
|
205
|
+
logger.info(f'The current Git repository hash is "{repository_record.current_head}"')
|
|
206
|
+
|
|
207
|
+
return changed
|
|
306
208
|
|
|
307
209
|
|
|
308
210
|
def git_repository_dry_run(repository_record, job_result=None, logger=None): # pylint: disable=redefined-outer-name
|
|
@@ -328,15 +230,13 @@ def git_repository_dry_run(repository_record, job_result=None, logger=None): #
|
|
|
328
230
|
|
|
329
231
|
except Exception as exc:
|
|
330
232
|
if job_result:
|
|
331
|
-
job_result.
|
|
332
|
-
job_result.log(str(exc), level_choice=LogLevelChoices.LOG_FAILURE, logger=logger)
|
|
333
|
-
job_result.save()
|
|
233
|
+
job_result.log(str(exc), level_choice=LogLevelChoices.LOG_ERROR, logger=logger)
|
|
334
234
|
elif logger:
|
|
335
235
|
logger.error(str(exc))
|
|
336
236
|
raise
|
|
337
237
|
|
|
338
238
|
if job_result:
|
|
339
|
-
job_result.log("Repository dry run successful", level_choice=LogLevelChoices.
|
|
239
|
+
job_result.log("Repository dry run successful", level_choice=LogLevelChoices.LOG_INFO, logger=logger)
|
|
340
240
|
elif logger:
|
|
341
241
|
logger.info("Repository dry run successful")
|
|
342
242
|
|
|
@@ -392,11 +292,10 @@ def update_git_config_contexts(repository_record, job_result):
|
|
|
392
292
|
except Exception as exc:
|
|
393
293
|
job_result.log(
|
|
394
294
|
f"Error in loading config context data from `{file_name}`: {exc}",
|
|
395
|
-
level_choice=LogLevelChoices.
|
|
295
|
+
level_choice=LogLevelChoices.LOG_ERROR,
|
|
396
296
|
grouping="config contexts",
|
|
397
297
|
logger=logger,
|
|
398
298
|
)
|
|
399
|
-
job_result.save()
|
|
400
299
|
|
|
401
300
|
# Next, handle the "filter/slug directory structure case - files in <filter_type>/<slug>.(json|yaml)
|
|
402
301
|
for filter_type in (
|
|
@@ -446,11 +345,10 @@ def update_git_config_contexts(repository_record, job_result):
|
|
|
446
345
|
except Exception as exc:
|
|
447
346
|
job_result.log(
|
|
448
347
|
f"Error in loading config context data from `{file_name}`: {exc}",
|
|
449
|
-
level_choice=LogLevelChoices.
|
|
348
|
+
level_choice=LogLevelChoices.LOG_ERROR,
|
|
450
349
|
grouping="config contexts",
|
|
451
350
|
logger=logger,
|
|
452
351
|
)
|
|
453
|
-
job_result.save()
|
|
454
352
|
|
|
455
353
|
# Finally, handle device- and virtual-machine-specific "local" context in (devices|virtual_machines)/<name>.(json|yaml)
|
|
456
354
|
for local_type in ("devices", "virtual_machines"):
|
|
@@ -490,11 +388,10 @@ def update_git_config_contexts(repository_record, job_result):
|
|
|
490
388
|
except Exception as exc:
|
|
491
389
|
job_result.log(
|
|
492
390
|
f"Error in loading local config context from `{local_type}/{file_name}`: {exc}",
|
|
493
|
-
level_choice=LogLevelChoices.
|
|
391
|
+
level_choice=LogLevelChoices.LOG_ERROR,
|
|
494
392
|
grouping="local config contexts",
|
|
495
393
|
logger=logger,
|
|
496
394
|
)
|
|
497
|
-
job_result.save()
|
|
498
395
|
|
|
499
396
|
# Delete any prior contexts that are owned by this repository but were not created/updated above
|
|
500
397
|
delete_git_config_contexts(
|
|
@@ -616,7 +513,7 @@ def import_config_context(context_data, repository_record, job_result, logger):
|
|
|
616
513
|
job_result.log(
|
|
617
514
|
f"ConfigContextSchema {context_metadata['config_context_schema']} does not exist.",
|
|
618
515
|
obj=context_record,
|
|
619
|
-
level_choice=LogLevelChoices.
|
|
516
|
+
level_choice=LogLevelChoices.LOG_ERROR,
|
|
620
517
|
grouping="config contexts",
|
|
621
518
|
logger=logger,
|
|
622
519
|
)
|
|
@@ -650,7 +547,7 @@ def import_config_context(context_data, repository_record, job_result, logger):
|
|
|
650
547
|
job_result.log(
|
|
651
548
|
"Successfully created config context",
|
|
652
549
|
obj=context_record,
|
|
653
|
-
level_choice=LogLevelChoices.
|
|
550
|
+
level_choice=LogLevelChoices.LOG_INFO,
|
|
654
551
|
grouping="config contexts",
|
|
655
552
|
logger=logger,
|
|
656
553
|
)
|
|
@@ -658,7 +555,7 @@ def import_config_context(context_data, repository_record, job_result, logger):
|
|
|
658
555
|
job_result.log(
|
|
659
556
|
"Successfully refreshed config context",
|
|
660
557
|
obj=context_record,
|
|
661
|
-
level_choice=LogLevelChoices.
|
|
558
|
+
level_choice=LogLevelChoices.LOG_INFO,
|
|
662
559
|
grouping="config contexts",
|
|
663
560
|
logger=logger,
|
|
664
561
|
)
|
|
@@ -699,7 +596,7 @@ def import_local_config_context(
|
|
|
699
596
|
job_result.log(
|
|
700
597
|
f"DATA CONFLICT: Local context data is owned by another owner, {record.local_config_context_data_owner}",
|
|
701
598
|
obj=record,
|
|
702
|
-
level_choice=LogLevelChoices.
|
|
599
|
+
level_choice=LogLevelChoices.LOG_ERROR,
|
|
703
600
|
grouping="local config contexts",
|
|
704
601
|
logger=logger,
|
|
705
602
|
)
|
|
@@ -722,7 +619,7 @@ def import_local_config_context(
|
|
|
722
619
|
job_result.log(
|
|
723
620
|
"Successfully updated local config context",
|
|
724
621
|
obj=record,
|
|
725
|
-
level_choice=LogLevelChoices.
|
|
622
|
+
level_choice=LogLevelChoices.LOG_INFO,
|
|
726
623
|
grouping="local config contexts",
|
|
727
624
|
logger=logger,
|
|
728
625
|
)
|
|
@@ -821,11 +718,10 @@ def update_git_config_context_schemas(repository_record, job_result):
|
|
|
821
718
|
except Exception as exc:
|
|
822
719
|
job_result.log(
|
|
823
720
|
f"Error in loading config context schema data from `{file_name}`: {exc}",
|
|
824
|
-
level_choice=LogLevelChoices.
|
|
721
|
+
level_choice=LogLevelChoices.LOG_ERROR,
|
|
825
722
|
grouping="config context schemas",
|
|
826
723
|
logger=logger,
|
|
827
724
|
)
|
|
828
|
-
job_result.save()
|
|
829
725
|
|
|
830
726
|
# Delete any prior contexts that are owned by this repository but were not created/updated above
|
|
831
727
|
delete_git_config_context_schemas(
|
|
@@ -880,7 +776,7 @@ def import_config_context_schema(
|
|
|
880
776
|
job_result.log(
|
|
881
777
|
"Successfully created config context schema",
|
|
882
778
|
obj=schema_record,
|
|
883
|
-
level_choice=LogLevelChoices.
|
|
779
|
+
level_choice=LogLevelChoices.LOG_INFO,
|
|
884
780
|
grouping="config context schemas",
|
|
885
781
|
logger=logger,
|
|
886
782
|
)
|
|
@@ -889,7 +785,7 @@ def import_config_context_schema(
|
|
|
889
785
|
job_result.log(
|
|
890
786
|
"Successfully refreshed config context schema",
|
|
891
787
|
obj=schema_record,
|
|
892
|
-
level_choice=LogLevelChoices.
|
|
788
|
+
level_choice=LogLevelChoices.LOG_INFO,
|
|
893
789
|
grouping="config context schemas",
|
|
894
790
|
logger=logger,
|
|
895
791
|
)
|
|
@@ -927,34 +823,77 @@ def delete_git_config_context_schemas(repository_record, job_result, preserve=()
|
|
|
927
823
|
#
|
|
928
824
|
|
|
929
825
|
|
|
826
|
+
def refresh_code_from_repository(repository_slug, consumer=None, skip_reimport=False):
|
|
827
|
+
"""
|
|
828
|
+
After cloning/updating a GitRepository on disk, call this function to reload and reregister the repo's Python code.
|
|
829
|
+
|
|
830
|
+
Args:
|
|
831
|
+
repository_slug (str): Repository directory in GIT_ROOT that was refreshed.
|
|
832
|
+
consumer (celery.worker.Consumer): Celery Consumer to update as well
|
|
833
|
+
skip_reimport (bool): If True, unload existing code from this repository but do not re-import it.
|
|
834
|
+
"""
|
|
835
|
+
if settings.GIT_ROOT not in sys.path:
|
|
836
|
+
sys.path.append(settings.GIT_ROOT)
|
|
837
|
+
|
|
838
|
+
app = consumer.app if consumer is not None else celery_app
|
|
839
|
+
# TODO: This is ugly, but when app.use_fast_trace_task is set (true by default), Celery calls
|
|
840
|
+
# celery.app.trace.fast_trace_task(...) which assumes that all tasks are cached and have a valid `__trace__()`
|
|
841
|
+
# function defined. In theory consumer.update_strategies() (below) should ensure this, but it doesn't
|
|
842
|
+
# go far enough (possibly a discrepancy between the main worker process and the prefork executors?)
|
|
843
|
+
# as we can and do still encounter errors where `task.__trace__` is unexpectedly None.
|
|
844
|
+
# For now, simply disabling use_fast_trace_task forces the task trace function to be rebuilt each time,
|
|
845
|
+
# which avoids the issue at the cost of very slight overhead.
|
|
846
|
+
app.use_fast_trace_task = False
|
|
847
|
+
|
|
848
|
+
# Unload any previous version of this module and its submodules if present
|
|
849
|
+
for module_name in list(sys.modules):
|
|
850
|
+
if module_name == repository_slug or module_name.startswith(f"{repository_slug}."):
|
|
851
|
+
logger.debug("Unloading module %s", module_name)
|
|
852
|
+
if module_name in app.loader.task_modules:
|
|
853
|
+
app.loader.task_modules.remove(module_name)
|
|
854
|
+
del sys.modules[module_name]
|
|
855
|
+
|
|
856
|
+
# Unregister any previous Celery tasks from this module
|
|
857
|
+
for task_name in list(app.tasks):
|
|
858
|
+
if task_name.startswith(f"{repository_slug}."):
|
|
859
|
+
logger.debug("Unregistering Celery task %s", task_name)
|
|
860
|
+
app.tasks.unregister(task_name)
|
|
861
|
+
if consumer is not None:
|
|
862
|
+
del consumer.strategies[task_name]
|
|
863
|
+
|
|
864
|
+
if not skip_reimport:
|
|
865
|
+
try:
|
|
866
|
+
repository = GitRepository.objects.get(slug=repository_slug)
|
|
867
|
+
if "extras.job" in repository.provided_contents:
|
|
868
|
+
# Re-import Celery tasks from this module
|
|
869
|
+
logger.debug("Importing Jobs from %s.jobs in GIT_ROOT", repository_slug)
|
|
870
|
+
app.loader.import_task_module(f"{repository_slug}.jobs")
|
|
871
|
+
if consumer is not None:
|
|
872
|
+
consumer.update_strategies()
|
|
873
|
+
except GitRepository.DoesNotExist as exc:
|
|
874
|
+
logger.error("Unable to reload Jobs from %s.jobs: %s", repository_slug, exc)
|
|
875
|
+
raise
|
|
876
|
+
|
|
877
|
+
|
|
930
878
|
def refresh_git_jobs(repository_record, job_result, delete=False):
|
|
931
879
|
"""Callback function for GitRepository updates - refresh all Job records managed by this repository."""
|
|
932
880
|
installed_jobs = []
|
|
933
881
|
if "extras.job" in repository_record.provided_contents and not delete:
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
if job_info.error is not None:
|
|
938
|
-
job_result.log(
|
|
939
|
-
message=f"Error in loading Jobs from `{job_info.module_name}`: `{job_info.error}`",
|
|
940
|
-
grouping="jobs",
|
|
941
|
-
level_choice=LogLevelChoices.LOG_FAILURE,
|
|
942
|
-
logger=logger,
|
|
943
|
-
)
|
|
944
|
-
continue
|
|
882
|
+
found_jobs = False
|
|
883
|
+
try:
|
|
884
|
+
refresh_code_from_repository(repository_record.slug)
|
|
945
885
|
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
)
|
|
886
|
+
for task_name, task in celery_app.tasks.items():
|
|
887
|
+
if not task_name.startswith(f"{repository_record.slug}."):
|
|
888
|
+
continue
|
|
889
|
+
found_jobs = True
|
|
890
|
+
job_model, created = refresh_job_model_from_job_class(Job, task.__class__)
|
|
952
891
|
|
|
953
892
|
if job_model is None:
|
|
954
893
|
job_result.log(
|
|
955
894
|
message="Failed to create Job record; check Nautobot logs for details",
|
|
956
895
|
grouping="jobs",
|
|
957
|
-
level_choice=LogLevelChoices.
|
|
896
|
+
level_choice=LogLevelChoices.LOG_ERROR,
|
|
958
897
|
logger=logger,
|
|
959
898
|
)
|
|
960
899
|
continue
|
|
@@ -967,19 +906,30 @@ def refresh_git_jobs(repository_record, job_result, delete=False):
|
|
|
967
906
|
message=message,
|
|
968
907
|
obj=job_model,
|
|
969
908
|
grouping="jobs",
|
|
970
|
-
level_choice=LogLevelChoices.
|
|
909
|
+
level_choice=LogLevelChoices.LOG_INFO,
|
|
971
910
|
logger=logger,
|
|
972
911
|
)
|
|
973
912
|
installed_jobs.append(job_model)
|
|
974
|
-
|
|
913
|
+
|
|
914
|
+
if not found_jobs:
|
|
915
|
+
job_result.log(
|
|
916
|
+
"No jobs were registered on loading the `jobs` submodule. Did you miss a `register_jobs()` call?",
|
|
917
|
+
grouping="jobs",
|
|
918
|
+
level_choice=LogLevelChoices.LOG_WARNING,
|
|
919
|
+
logger=logger,
|
|
920
|
+
)
|
|
921
|
+
except Exception as exc:
|
|
975
922
|
job_result.log(
|
|
976
|
-
"
|
|
923
|
+
f"Error in loading Jobs from Git repository: {exc}",
|
|
977
924
|
grouping="jobs",
|
|
978
|
-
level_choice=LogLevelChoices.
|
|
925
|
+
level_choice=LogLevelChoices.LOG_ERROR,
|
|
979
926
|
logger=logger,
|
|
980
927
|
)
|
|
928
|
+
else:
|
|
929
|
+
# Unload code from this repository, do not reimport it
|
|
930
|
+
refresh_code_from_repository(repository_record.slug, skip_reimport=True)
|
|
981
931
|
|
|
982
|
-
for job_model in Job.objects.filter(
|
|
932
|
+
for job_model in Job.objects.filter(module_name__startswith=f"{repository_record.slug}."):
|
|
983
933
|
if job_model.installed and job_model not in installed_jobs:
|
|
984
934
|
job_result.log(
|
|
985
935
|
message="Marking Job record as no longer installed",
|
|
@@ -1093,7 +1043,7 @@ def update_git_export_templates(repository_record, job_result):
|
|
|
1093
1043
|
job_result.log(
|
|
1094
1044
|
"Successfully created export template",
|
|
1095
1045
|
obj=template_record,
|
|
1096
|
-
level_choice=LogLevelChoices.
|
|
1046
|
+
level_choice=LogLevelChoices.LOG_INFO,
|
|
1097
1047
|
grouping="export templates",
|
|
1098
1048
|
logger=logger,
|
|
1099
1049
|
)
|
|
@@ -1101,7 +1051,7 @@ def update_git_export_templates(repository_record, job_result):
|
|
|
1101
1051
|
job_result.log(
|
|
1102
1052
|
"Successfully refreshed export template",
|
|
1103
1053
|
obj=template_record,
|
|
1104
|
-
level_choice=LogLevelChoices.
|
|
1054
|
+
level_choice=LogLevelChoices.LOG_INFO,
|
|
1105
1055
|
grouping="export templates",
|
|
1106
1056
|
logger=logger,
|
|
1107
1057
|
)
|
|
@@ -1118,11 +1068,10 @@ def update_git_export_templates(repository_record, job_result):
|
|
|
1118
1068
|
job_result.log(
|
|
1119
1069
|
str(exc),
|
|
1120
1070
|
obj=template_record,
|
|
1121
|
-
level_choice=LogLevelChoices.
|
|
1071
|
+
level_choice=LogLevelChoices.LOG_ERROR,
|
|
1122
1072
|
grouping="export templates",
|
|
1123
1073
|
logger=logger,
|
|
1124
1074
|
)
|
|
1125
|
-
job_result.save()
|
|
1126
1075
|
|
|
1127
1076
|
# Delete any prior templates that are owned by this repository but were not discovered above
|
|
1128
1077
|
delete_git_export_templates(repository_record, job_result, preserve=managed_export_templates)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"""Registry-related APIs for datasources."""
|
|
2
2
|
|
|
3
|
-
from nautobot.extras.choices import
|
|
4
|
-
from nautobot.extras.context_managers import change_logging, JobChangeContext
|
|
3
|
+
from nautobot.extras.choices import LogLevelChoices
|
|
5
4
|
from nautobot.extras.registry import registry
|
|
6
5
|
|
|
7
6
|
|
|
@@ -19,7 +18,7 @@ def get_datasource_content_choices(model_name):
|
|
|
19
18
|
)
|
|
20
19
|
|
|
21
20
|
|
|
22
|
-
def refresh_datasource_content(model_name, record,
|
|
21
|
+
def refresh_datasource_content(model_name, record, user, job_result, delete=False):
|
|
23
22
|
"""Invoke the refresh callbacks for every content type registered for this model.
|
|
24
23
|
|
|
25
24
|
Note that these callback functions are invoked regardless of whether a given model instance actually is flagged
|
|
@@ -29,39 +28,30 @@ def refresh_datasource_content(model_name, record, request, job_result, delete=F
|
|
|
29
28
|
Args:
|
|
30
29
|
model_name (str): Identifier of the datasource owner, such as "extras.gitrepository"
|
|
31
30
|
record (models.Model): Datasource model instance, such as a GitRepository record
|
|
32
|
-
|
|
31
|
+
user (User): Initiating user for this refresh, optional, used for change logging if provided
|
|
33
32
|
job_result (JobResult): Passed through to the callback functions to use with logging their actions.
|
|
34
33
|
delete (bool): True if the record is being deleted; False if it is being created/updated.
|
|
35
34
|
"""
|
|
36
35
|
job_result.log(f"Refreshing data provided by {record}...", level_choice=LogLevelChoices.LOG_INFO)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
job_result.log(f"Refreshing {entry.name}...", level_choice=LogLevelChoices.LOG_INFO)
|
|
60
|
-
try:
|
|
61
|
-
entry.callback(record, job_result, delete=delete)
|
|
62
|
-
except Exception as exc:
|
|
63
|
-
job_result.log(f"Error while refreshing {entry.name}: {exc}", level_choice=LogLevelChoices.LOG_FAILURE)
|
|
64
|
-
job_result.set_status(JobResultStatusChoices.STATUS_FAILURE)
|
|
65
|
-
job_result.save()
|
|
66
|
-
job_result.log(f"Data refresh from {record} complete!", level_choice=LogLevelChoices.LOG_INFO)
|
|
67
|
-
job_result.save()
|
|
36
|
+
|
|
37
|
+
for entry in get_datasource_contents(model_name):
|
|
38
|
+
job_result.log(f"Refreshing {entry.name}...", level_choice=LogLevelChoices.LOG_INFO)
|
|
39
|
+
try:
|
|
40
|
+
entry.callback(record, job_result, delete=delete)
|
|
41
|
+
except Exception as exc:
|
|
42
|
+
job_result.log(f"Error while refreshing {entry.name}: {exc}", level_choice=LogLevelChoices.LOG_ERROR)
|
|
43
|
+
raise
|
|
44
|
+
|
|
45
|
+
# Now that any exception will fail a Job and Git Repository syncs are jobs,
|
|
46
|
+
# and we also cannot micro-manage the JobResult state, we had to add a final
|
|
47
|
+
# check here to ensure that any failed log events by the various content
|
|
48
|
+
# callbacks will result in this task "failing successfully" by raising an
|
|
49
|
+
# exception.
|
|
50
|
+
failure_logs = job_result.job_log_entries.filter(log_level=LogLevelChoices.LOG_ERROR)
|
|
51
|
+
if failure_logs.exists():
|
|
52
|
+
msg = f"Failed to refresh data provided by {record}. Please see logs."
|
|
53
|
+
job_result.log(msg, level_choice=LogLevelChoices.LOG_ERROR)
|
|
54
|
+
raise RuntimeError(msg)
|
|
55
|
+
|
|
56
|
+
# Otherwise, log a friendly info message.
|
|
57
|
+
job_result.log(f"Data refresh from {record} complete!", level_choice=LogLevelChoices.LOG_INFO)
|
nautobot/extras/factory.py
CHANGED
|
@@ -23,7 +23,6 @@ class RoleFactory(OrganizationalModelFactory):
|
|
|
23
23
|
name = factory.LazyFunction(
|
|
24
24
|
lambda: "".join(word.title() for word in faker.Faker().words(nb=2, part_of_speech="adjective", unique=True))
|
|
25
25
|
)
|
|
26
|
-
slug = factory.LazyAttribute(lambda role: slugify(role.name))
|
|
27
26
|
color = factory.Iterator(ColorChoices.CHOICES, getter=lambda choice: choice[0])
|
|
28
27
|
has_weight = NautobotBoolIterator()
|
|
29
28
|
weight = factory.Maybe("has_weight", factory.Faker("pyint"), None)
|
|
@@ -50,7 +49,6 @@ class StatusFactory(OrganizationalModelFactory):
|
|
|
50
49
|
name = factory.LazyFunction(
|
|
51
50
|
lambda: "".join(word.title() for word in faker.Faker().words(nb=2, part_of_speech="adjective", unique=True))
|
|
52
51
|
)
|
|
53
|
-
slug = factory.LazyAttribute(lambda status: slugify(status.name))
|
|
54
52
|
color = factory.Iterator(ColorChoices.CHOICES, getter=lambda choice: choice[0])
|
|
55
53
|
|
|
56
54
|
has_description = NautobotBoolIterator()
|
|
@@ -89,4 +87,4 @@ class TagFactory(OrganizationalModelFactory):
|
|
|
89
87
|
if extracted:
|
|
90
88
|
self.content_types.set(extracted)
|
|
91
89
|
else:
|
|
92
|
-
self.content_types.set(get_random_instances(lambda: TaggableClassesQuery().as_queryset(), minimum=
|
|
90
|
+
self.content_types.set(get_random_instances(lambda: TaggableClassesQuery().as_queryset(), minimum=2))
|