forward-netbox 3.0.0__tar.gz → 3.0.2__tar.gz
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.
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/PKG-INFO +11 -8
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/README.md +5 -3
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/__init__.py +1 -1
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/api/serializers.py +7 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/api/views.py +298 -9
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/change_control/criteria.py +3 -1
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/choices.py +11 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/filtersets.py +34 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/forms.py +125 -7
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/jobs.py +558 -6
- forward_netbox-3.0.2/forward_netbox/management/commands/forward_apic_cimc_readiness_audit.py +53 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_device_scope_reconciliation_audit.py +67 -1
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_module_readiness.py +5 -2
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_profile_merge.py +57 -1
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_pushdown_profile.py +5 -2
- forward_netbox-3.0.2/forward_netbox/management/commands/forward_routing_dangling_audit.py +31 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_smoke_sync.py +13 -1
- forward_netbox-3.0.2/forward_netbox/migrations/0053_routing_policy_nqe_map_choices.py +18 -0
- forward_netbox-3.0.2/forward_netbox/migrations/0054_aci_tenant_policy_nqe_map_choices.py +18 -0
- forward_netbox-3.0.2/forward_netbox/migrations/0055_operator_delete_releases_ownership.py +18 -0
- forward_netbox-3.0.2/forward_netbox/migrations/0056_aci_attachment_nqe_map_choices.py +18 -0
- forward_netbox-3.0.2/forward_netbox/migrations/0056_routing_policy_nqe_map_choices.py +91 -0
- forward_netbox-3.0.2/forward_netbox/migrations/0057_aci_tenant_policy_nqe_map_choices.py +106 -0
- forward_netbox-3.0.2/forward_netbox/migrations/0057_nqe_map_last_live_drift.py +28 -0
- forward_netbox-3.0.2/forward_netbox/migrations/0058_operator_delete_releases_ownership.py +34 -0
- forward_netbox-3.0.2/forward_netbox/migrations/0059_aci_attachment_nqe_map_choices.py +113 -0
- forward_netbox-3.0.2/forward_netbox/migrations/0060_merge_maint_2_9_x_history.py +19 -0
- forward_netbox-3.0.2/forward_netbox/migrations/0061_static_route_nqe_map_choice.py +115 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/models.py +120 -10
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/navigation.py +10 -1
- forward_netbox-3.0.0/forward_netbox/queries/forward_aci_filters.nqe → forward_netbox-3.0.2/forward_netbox/queries/forward_aci_apic_filters.nqe +10 -8
- forward_netbox-3.0.0/forward_netbox/queries/forward_aci_pods.nqe → forward_netbox-3.0.2/forward_netbox/queries/forward_aci_apic_pods.nqe +8 -5
- forward_netbox-3.0.2/forward_netbox/queries/forward_aci_app_profiles.nqe +34 -0
- forward_netbox-3.0.2/forward_netbox/queries/forward_aci_bridge_domains.nqe +58 -0
- forward_netbox-3.0.2/forward_netbox/queries/forward_aci_contracts.nqe +37 -0
- forward_netbox-3.0.2/forward_netbox/queries/forward_aci_endpoint_groups.nqe +50 -0
- forward_netbox-3.0.2/forward_netbox/queries/forward_aci_fabrics.nqe +38 -0
- forward_netbox-3.0.2/forward_netbox/queries/forward_aci_filter_entries.nqe +45 -0
- forward_netbox-3.0.2/forward_netbox/queries/forward_aci_filters.nqe +65 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_aci_l3outs.nqe +9 -7
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_aci_nodes.nqe +30 -1
- forward_netbox-3.0.2/forward_netbox/queries/forward_aci_pods.nqe +63 -0
- forward_netbox-3.0.2/forward_netbox/queries/forward_aci_source_readiness.nqe +51 -0
- forward_netbox-3.0.2/forward_netbox/queries/forward_aci_static_port_bindings.nqe +51 -0
- forward_netbox-3.0.2/forward_netbox/queries/forward_aci_subject_filters.nqe +51 -0
- forward_netbox-3.0.2/forward_netbox/queries/forward_aci_subjects.nqe +51 -0
- forward_netbox-3.0.2/forward_netbox/queries/forward_bgp_peer_address_families.nqe +189 -0
- forward_netbox-3.0.2/forward_netbox/queries/forward_config_backup.nqe +97 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_devices.nqe +21 -5
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_devices_with_netbox_aliases.nqe +21 -5
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_hsrp_groups.nqe +7 -0
- forward_netbox-3.0.2/forward_netbox/queries/forward_interfaces.nqe +171 -0
- forward_netbox-3.0.2/forward_netbox/queries/forward_ip_addresses_ipv4.nqe +311 -0
- forward_netbox-3.0.2/forward_netbox/queries/forward_routing_community_lists.nqe +87 -0
- forward_netbox-3.0.2/forward_netbox/queries/forward_routing_prefix_lists.nqe +96 -0
- forward_netbox-3.0.2/forward_netbox/queries/forward_routing_route_maps.nqe +78 -0
- forward_netbox-3.0.2/forward_netbox/queries/forward_static_routes.nqe +48 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/signals.py +37 -13
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tables.py +53 -0
- forward_netbox-3.0.2/forward_netbox/template_content.py +309 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/forwardingestionissue.html +26 -3
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/forwardsync.html +48 -2
- forward_netbox-3.0.2/forward_netbox/templates/forward_netbox/forwardsync_audit_report.html +107 -0
- forward_netbox-3.0.2/forward_netbox/templates/forward_netbox/forwardsync_audits.html +62 -0
- forward_netbox-3.0.2/forward_netbox/templates/forward_netbox/forwardsync_delete.html +18 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/forwardsync_drift_report.html +19 -2
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/forwardsync_health.html +159 -1
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/forwardsync_module_readiness.html +26 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/forwardsync_scope_reconciliation.html +201 -10
- forward_netbox-3.0.2/forward_netbox/templates/forward_netbox/htmx/forwardsync_delete_form.html +106 -0
- forward_netbox-3.0.2/forward_netbox/templates/forward_netbox/inc/count_trend.html +15 -0
- forward_netbox-3.0.2/forward_netbox/templates/forward_netbox/inc/device_ownership_panel.html +231 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_absence_quarantine.py +156 -1
- forward_netbox-3.0.2/forward_netbox/tests/test_absent_configuration_detail.py +361 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_aci_drift_comparison.py +2 -1
- forward_netbox-3.0.2/forward_netbox/tests/test_aci_source_readiness.py +179 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_api_views.py +114 -18
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_apic_cimc_readiness_audit_command.py +4 -1
- forward_netbox-3.0.2/forward_netbox/tests/test_audit_report_views.py +289 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_bgp_peer_af_query.py +95 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_bgp_peer_policy_links.py +201 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_bgp_peer_round_trip_variants.py +242 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_builtin_query_id_binding.py +9 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_bulk_merge.py +167 -8
- forward_netbox-3.0.2/forward_netbox/tests/test_bundle_diagnostics_parity.py +146 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_button_jobs.py +86 -23
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_cable_drift_comparison.py +6 -3
- forward_netbox-3.0.2/forward_netbox/tests/test_catalogue_models_compare.py +70 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_change_explainability_full_counts.py +85 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_config_backup.py +1333 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_config_backup_folder.py +320 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_config_backup_job_and_health.py +417 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_config_backup_path.py +117 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_config_backup_query.py +83 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_config_backup_result_evidence.py +288 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_constraint_diagnosis.py +216 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_cross_site_vlan_revalidation.py +6 -1
- forward_netbox-3.0.2/forward_netbox/tests/test_dependency_preview_summary.py +153 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_device_name_case_identity.py +136 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_device_scope_reconciliation_audit_command.py +86 -3
- forward_netbox-3.0.2/forward_netbox/tests/test_device_site_relabel_identity.py +255 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_diagnostics_readback.py +52 -1
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_diff_removal_allowlist.py +35 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_dlm_catalogue_conflicts.py +3 -4
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_dlm_drift_comparison.py +2 -1
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_dlm_inventoryitem_drift_comparison.py +2 -1
- forward_netbox-3.0.2/forward_netbox/tests/test_durable_workload_state_attribution.py +109 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_endpoint_absence_detail.py +192 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_endpoint_ipv4_netmask.py +75 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_endpoints_import.py +64 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_execute_by_query_id_without_commit.py +31 -10
- forward_netbox-3.0.2/forward_netbox/tests/test_export_redaction.py +260 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_failed_run_model_evidence.py +9 -1
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_fast_baseline.py +179 -3
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_fast_paths_report_when_disabled.py +14 -4
- forward_netbox-3.0.2/forward_netbox/tests/test_fast_paths_subset_runtime.py +173 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_fhrpgroup_drift_comparison.py +4 -2
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_forms.py +125 -1
- forward_netbox-3.0.2/forward_netbox/tests/test_forward_api.py +2237 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_forward_client_errors.py +212 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_forward_client_factory.py +124 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_forward_usage_hooks.py +85 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_head_commit_from_listing.py +34 -27
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_health.py +82 -20
- forward_netbox-3.0.2/forward_netbox/tests/test_health_evidence.py +380 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_ingestion_merge.py +3 -1
- forward_netbox-3.0.2/forward_netbox/tests/test_interface_lookup_query_shape.py +114 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_inventoryitem_drift_comparison.py +30 -17
- forward_netbox-3.0.2/forward_netbox/tests/test_issue_diagnosis.py +597 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_jobs.py +11 -3
- forward_netbox-3.0.2/forward_netbox/tests/test_license_tier.py +62 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_log_export.py +497 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_merge_rule_rejection.py +33 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_migration_lineage.py +55 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_models.py +46 -27
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_module_drift_comparison.py +6 -3
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_module_readiness.py +12 -4
- forward_netbox-3.0.2/forward_netbox/tests/test_nqe_lint_blind_spots.py +110 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_operator_delete_releases_ownership.py +267 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_optional_plugin_versions.py +80 -33
- forward_netbox-3.0.2/forward_netbox/tests/test_ospf_neighbour_rows_converge.py +161 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_ownership.py +101 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_ownership_lock_wait.py +88 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_parameter_signature_drift.py +85 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_plan_statistics_monotonic.py +92 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_plugin_integrations.py +11 -11
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_preview_primes_its_lookup_caches.py +98 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_primary_ip.py +84 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_primary_ip_audit.py +10 -1
- forward_netbox-3.0.2/forward_netbox/tests/test_primary_ip_duplicate_names.py +100 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_primary_ip_integration.py +90 -5
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_provision_preflight.py +13 -2
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_query_binding.py +37 -1
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_query_execution_contract.py +52 -8
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_query_registry.py +110 -16
- forward_netbox-3.0.2/forward_netbox/tests/test_query_signature_drift_check.py +88 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_query_variants.py +49 -1
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_refused_deletes_are_not_staged.py +3 -4
- forward_netbox-3.0.2/forward_netbox/tests/test_release_foreign_delete_blockers.py +298 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_routing_apply_compare_round_trip.py +172 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_routing_catalogue_cleanup.py +283 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_routing_catalogue_drift.py +103 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_routing_catalogue_scope.py +107 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_row_collapsing.py +136 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_run_size_anomaly.py +122 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_run_size_guard.py +192 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_runtime_dependency_check.py +1 -1
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_scheduled_jobs.py +71 -8
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_scope_matched_tags.py +14 -9
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_scope_module_ui.py +294 -21
- forward_netbox-3.0.2/forward_netbox/tests/test_scope_reconciliation_site_aware.py +317 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_scope_shrink_guard.py +2 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_sdk_result_contract.py +44 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_site_relabel_pairs_merge.py +706 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_site_relabel_prompts.py +271 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_static_routes_query.py +64 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_stuck_recovery.py +205 -1
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_sync.py +102 -1
- forward_netbox-3.0.2/forward_netbox/tests/test_sync_aci.py +1850 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_sync_facade.py +30 -10
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_sync_orchestration.py +55 -43
- forward_netbox-3.0.2/forward_netbox/tests/test_sync_routing_policy.py +818 -0
- forward_netbox-3.0.2/forward_netbox/tests/test_sync_routing_static.py +339 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_taggeditem_drift_comparison.py +8 -4
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_uncovered_absence_and_trend.py +148 -4
- forward_netbox-3.0.2/forward_netbox/tests/test_uncovered_device_cleanup.py +472 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_uncovered_device_tag.py +8 -2
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_validated_runtime_is_declared_once.py +10 -4
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_validation_org_query_audit_command.py +76 -12
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_vsys_parent.py +10 -4
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_workload_state.py +89 -5
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/__init__.py +1 -5
- forward_netbox-3.0.2/forward_netbox/utilities/apic_cimc_readiness.py +77 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/apply_engine_bulk.py +321 -44
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/apply_engine_decision.py +71 -32
- forward_netbox-3.0.2/forward_netbox/utilities/audit_reports.py +684 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/branch_budget.py +58 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/branch_lifecycle.py +64 -2
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/bulk_merge.py +12 -2
- forward_netbox-3.0.2/forward_netbox/utilities/bundle_diagnostics.py +520 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/change_explainability.py +44 -4
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/config_backup.py +424 -59
- forward_netbox-3.0.2/forward_netbox/utilities/config_backup_path.py +98 -0
- forward_netbox-3.0.2/forward_netbox/utilities/constraint_diagnosis.py +322 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/device_analysis.py +3 -1
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/diagnostics.py +104 -4
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/dlm_notice_audit.py +3 -1
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/drift_comparison.py +110 -17
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/drift_report.py +56 -0
- forward_netbox-3.0.2/forward_netbox/utilities/export_redaction.py +95 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/fast_baseline.py +71 -10
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/fast_baseline_models.py +19 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/forward_api.py +22 -1
- forward_netbox-3.0.2/forward_netbox/utilities/forward_api_impl.py +1830 -0
- forward_netbox-3.0.2/forward_netbox/utilities/forward_client_config.py +151 -0
- forward_netbox-3.0.2/forward_netbox/utilities/forward_client_errors.py +105 -0
- forward_netbox-3.0.2/forward_netbox/utilities/forward_client_factory.py +103 -0
- forward_netbox-3.0.2/forward_netbox/utilities/forward_read_cache.py +100 -0
- forward_netbox-3.0.2/forward_netbox/utilities/forward_throttle.py +98 -0
- forward_netbox-3.0.2/forward_netbox/utilities/forward_usage.py +144 -0
- forward_netbox-3.0.2/forward_netbox/utilities/forward_usage_hooks.py +70 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/full_removal_reconciliation.py +15 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/health.py +859 -121
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/health_checks.py +82 -34
- forward_netbox-3.0.2/forward_netbox/utilities/health_evidence.py +307 -0
- forward_netbox-3.0.2/forward_netbox/utilities/ingestion_issues.py +91 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/interface_vlan_audit.py +76 -2
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/merge.py +30 -5
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/merge_set_based.py +6 -30
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/model_validation.py +14 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/module_readiness.py +4 -1
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/ownership.py +156 -15
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/plugin_integrations/registry.py +52 -5
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/primary_ip.py +131 -17
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/primary_ip_audit.py +3 -1
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/query_binding_resolution.py +124 -21
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/query_diagnostics.py +182 -2
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/query_fetch_execution.py +137 -44
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/query_registry.py +158 -9
- forward_netbox-3.0.2/forward_netbox/utilities/routing_catalogue_cleanup.py +313 -0
- forward_netbox-3.0.2/forward_netbox/utilities/routing_dangling_audit.py +57 -0
- forward_netbox-3.0.2/forward_netbox/utilities/row_collapsing.py +140 -0
- forward_netbox-3.0.2/forward_netbox/utilities/run_size_anomaly.py +138 -0
- forward_netbox-3.0.2/forward_netbox/utilities/run_size_guard.py +76 -0
- forward_netbox-3.0.2/forward_netbox/utilities/scope_reconciliation.py +2845 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/single_branch_executor.py +53 -6
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/snapshot_freshness.py +5 -2
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/stuck_recovery.py +94 -7
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/support_bundle_archive.py +5 -1
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/sync.py +35 -1
- forward_netbox-3.0.2/forward_netbox/utilities/sync_aci.py +1420 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/sync_contracts.py +125 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/sync_core_models.py +30 -3
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/sync_device.py +109 -4
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/sync_execution.py +12 -5
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/sync_facade.py +95 -3
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/sync_ipam.py +162 -23
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/sync_orchestration.py +7 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/sync_primitives.py +239 -3
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/sync_reporting.py +179 -1
- forward_netbox-3.0.2/forward_netbox/utilities/sync_routing.py +3 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/sync_routing_impl.py +58 -0
- forward_netbox-3.0.2/forward_netbox/utilities/sync_routing_policy.py +963 -0
- forward_netbox-3.0.2/forward_netbox/utilities/sync_routing_static.py +304 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/sync_runner_adapters.py +129 -9
- forward_netbox-3.0.2/forward_netbox/utilities/validated_runtime.py +168 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/vsys_parent.py +3 -1
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/workload_state.py +221 -13
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/views.py +1539 -78
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/pyproject.toml +11 -6
- forward_netbox-3.0.0/forward_netbox/management/commands/forward_apic_cimc_readiness_audit.py +0 -118
- forward_netbox-3.0.0/forward_netbox/management/commands/forward_routing_dangling_audit.py +0 -82
- forward_netbox-3.0.0/forward_netbox/queries/forward_aci_bridge_domains.nqe +0 -45
- forward_netbox-3.0.0/forward_netbox/queries/forward_aci_fabrics.nqe +0 -25
- forward_netbox-3.0.0/forward_netbox/queries/forward_bgp_peer_address_families.nqe +0 -65
- forward_netbox-3.0.0/forward_netbox/queries/forward_config_backup.nqe +0 -38
- forward_netbox-3.0.0/forward_netbox/queries/forward_interfaces.nqe +0 -66
- forward_netbox-3.0.0/forward_netbox/queries/forward_ip_addresses_ipv4.nqe +0 -154
- forward_netbox-3.0.0/forward_netbox/template_content.py +0 -31
- forward_netbox-3.0.0/forward_netbox/tests/test_config_backup.py +0 -608
- forward_netbox-3.0.0/forward_netbox/tests/test_dependency_preview_summary.py +0 -64
- forward_netbox-3.0.0/forward_netbox/tests/test_forward_api.py +0 -2831
- forward_netbox-3.0.0/forward_netbox/tests/test_issue_diagnosis.py +0 -260
- forward_netbox-3.0.0/forward_netbox/tests/test_license_tier.py +0 -131
- forward_netbox-3.0.0/forward_netbox/tests/test_sync_aci.py +0 -951
- forward_netbox-3.0.0/forward_netbox/utilities/forward_api_impl.py +0 -2308
- forward_netbox-3.0.0/forward_netbox/utilities/ingestion_issues.py +0 -22
- forward_netbox-3.0.0/forward_netbox/utilities/scope_reconciliation.py +0 -1385
- forward_netbox-3.0.0/forward_netbox/utilities/sync_aci.py +0 -614
- forward_netbox-3.0.0/forward_netbox/utilities/sync_routing.py +0 -1
- forward_netbox-3.0.0/forward_netbox/utilities/validated_runtime.py +0 -84
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/LICENSE +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/api/__init__.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/api/urls.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/change_control/__init__.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/change_control/choices.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/change_control/evidence.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/change_control/gates.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/change_control/policy.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/change_control/predict.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/change_control/state_machine.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/exceptions.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/__init__.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/__init__.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_accept_merge_failures.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_apply_identity_audit.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_blocker_audit.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_changediff_audit.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_collection_gap_alert.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_device_name_ambiguity_audit.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_dlm_hardware_notice_audit.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_fast_baseline_preflight.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_interface_vlan_audit.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_link_vsys_parents.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_metrics.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_ownership_audit.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_primary_ip_audit.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_query_diff_coverage_audit.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_resolve_query_ids.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_scope_ipam_audit.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_seed_ui_harness.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_stuck_job_alert.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_stuck_job_recover.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_tag_delete_eligible.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_validation_org_query_audit.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_warning_audit.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/management/commands/forward_watch_sync.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0001_initial.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0002_add_coalesce_fields.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0003_forwardingestionissue_context_fields.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0004_forwardingestion_baseline_fields.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0005_validation_and_reporting.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0006_alter_forwardnqemap_netbox_model.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0007_forwardingestion_persisted_change_counters.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0008_alter_forwardnqemap_netbox_model.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0009_alter_forwardnqemap_netbox_model.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0010_forwardvalidationrun_override_applied_and_more.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0011_forwardingestion_change_request_id.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0012_forwardnqemap_query_reference.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0013_execution_run_step.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0014_execution_step_fetch_scope.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0015_execution_step_apply_engine.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0016_execution_step_query_metrics.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0017_execution_step_row_counters.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0018_execution_run_reconciliation_events.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0019_forwardexecutionstep_query_parameters.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0020_execution_step_operation.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0021_add_fhrpgroup_nqe_map_choice.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0022_alter_forwardnqemap_netbox_model.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0023_split_ip_address_maps.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0024_forwarddeviceanalysis.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0025_device_analysis_netboxmodel.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0026_forwarddeviceanalysis_collection_result.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0027_alter_forwardexecutionrun_backend.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0028_remove_forwardexecutionstep_run_and_more.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0029_forward_parent_device_cf.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0030_forwarddeviceanalysis_cve_ids.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0031_encrypt_source_password.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0032_alter_forwardnqemap_netbox_model.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0033_alter_forwardnqemap_netbox_model.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0034_source_ownership_provenance.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0035_initialize_ownership_control_plane.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0036_protect_ownership_provenance.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0037_merge_identity_and_assignment_provenance.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0038_managed_tag_domain_guard.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0039_forwardingestion_catchup_state.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0040_remove_redundant_nqe_settings.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0041_forwardworkloadstate.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0042_device_generic_relation_guards.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0043_forwardnqemap_diff_contract.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0044_contributor_baseline_cache.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0045_forwardmergeattempt.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0046_alter_forwardnqemap_netbox_model.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0047_ownership_reconciliation_cascade.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0048_forwardingestion_skipped_change_count.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0049_drift_policy_row_shrink_floor.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0050_contributor_baseline_cascade.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0051_ownership_provenance_stamp_nullable.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0052_device_absence_quarantine.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0053_alter_forwardsource_owner.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0054_forwardchange_forwardchangecriterion_and_more.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/0055_change_control_approvals.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/migrations/__init__.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/__init__.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_aci_apic_cimc_inventory.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_aci_apic_nodes.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_aci_command_inventory.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_aci_tenants.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_aci_vrfs.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_bgp_address_families.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_bgp_peers.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_cimc_endpoint_inventory.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_device_analysis.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_device_feature_tags.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_device_feature_tags_with_rules.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_device_models.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_device_models_with_netbox_aliases.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_device_types.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_device_vendors.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_dlm_apic_cimc_inventory_item_software.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_dlm_cves.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_dlm_device_software.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_dlm_hardware_notices.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_dlm_hardware_notices_with_netbox_aliases.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_dlm_inventory_item_software.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_dlm_software_versions.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_dlm_vulnerabilities.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_inferred_interface_cables.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_inventory_items.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_ip_addresses_ipv6.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_ip_addresses_unassignable_diagnostics.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_locations.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_mac_addresses.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_modules.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_ospf_areas.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_ospf_instances.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_ospf_interfaces.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_peering_sessions.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_platforms.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_prefixes_ipv4.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_prefixes_ipv6.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_routing_import_diagnostics.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_virtual_chassis.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_vlans.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/forward_vrfs.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/queries/netbox_utilities.nqe +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/static/forward_netbox/img/fn-logo.svg +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/device_cves.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/forwardchange.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/forwardchangepolicy.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/forwarddeviceanalysis.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/forwarddriftpolicy.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/forwardingestion.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/forwardnqemap.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/forwardsource.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/forwardsync_dependency_preview.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/forwardsync_uncovered_devices.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/forwardvalidationrun.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/inc/brand_bar.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/inc/device_analysis_panel.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/inc/diff.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/inc/execution_insights.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/inc/logs_pending.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/inc/merge_form.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/inc/validation_force_allow_form.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/partials/change_explainability.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/partials/ingestion_all.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/partials/ingestion_merge_button.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/partials/ingestion_progress.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/partials/ingestion_statistics.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/partials/ingestion_status.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/partials/job_logs.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/partials/object_tabs.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/partials/stage_switcher_buttons.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templates/forward_netbox/partials/validation_force_allow_button.html +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templatetags/__init__.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/templatetags/forward_netbox_helpers.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/__init__.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/fixtures/aci_command_inventory_expected.json +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/fixtures/aci_discovery_expected.json +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_a_warning_is_not_a_failure.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_absent_device_does_not_block_tag_domain.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_accepted_merge_failures.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_adapter_drift_scale.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_api_serializer_base.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_api_usage.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_apply_engine.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_apply_identity_audit.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_bgp_peer_comment_churn.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_branch_budget_split.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_branching.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_brand_bar.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_bulk_adapter_parity.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_bulk_merge_scale.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_change_control_evidence.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_change_control_gates.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_change_control_policy.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_change_control_predict.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_change_control_state_machine.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_changediff_audit.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_collection_collapse_guard.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_contract_preflight_message.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_contributor_baseline.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_converged_models_are_measured.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_copy_sql_apply_engine.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_crypto.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_density_observation.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_device_analysis_query.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_device_scope_tagging.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_dlm_hardware_notice_audit.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_dlm_integration.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_drift_comparison.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_drift_coverage_is_explained.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_drift_rows_are_distinguishable.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_empty_comparison_is_not_a_measurement.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_empty_workload_failure.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_execution_insights_delete_label.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_field_reported_integrity_failures.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_force_allow_override.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_full_removal_reconciliation.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_ingestion_delete.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_ingestion_is_deletable.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_interface_naming.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_interface_vlan_audit.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_ip_address_dedup_query.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_ipaddress_dup_global.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_issue_rendering.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_job_liveness.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_job_queue.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_keyerror_names_its_key.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_logging.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_merge_observability.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_merge_profiling.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_migration_dependencies.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_migrations.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_mixed_model_change_diffs.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_model_view_routes.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_module_readiness_rollup.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_operator_commands.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_ospf_drift_comparison.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_ownership_command.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_ownership_completes_with_preexisting_status_tag.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_ownership_conflict_reason.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_ownership_migration.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_peering_drift_comparison.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_post_sync.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_preview_isolation.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_preview_reports_its_cost.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_preview_runner_satisfies_the_priming_contract.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_protected_delete_is_a_skip.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_protecting_reference_deletes.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_protecting_relations.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_quarantine_cadence.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_query_diff_coverage_audit_command.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_query_id_binding_end_to_end.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_raise_site_is_recorded.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_refused_deletes_are_retried.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_release_readiness_audit.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_reserved_status_tag_adoption.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_row_count_floor.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_scope_audit_full.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_scope_ipam_audit.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_scope_reconciliation_view.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_scope_tag_slug_collision.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_set_based_merge.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_skip_dependency_direction.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_skip_names_netbox_row.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_skip_raisers_name_dependency.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_skip_rollup_direction.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_smoke_sync_command.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_source_parameter_keys_agree.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_stability_hardening.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_support_bundle_archive.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_sync_recurrence_pinning.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_sync_runner_contracts.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_sync_state.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_tier3_reducers.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_tree_model_detection.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_upgrade_reconciliation.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_virtualchassis_drift_comparison.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/tests/test_workload_normalization.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/urls.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/api_usage.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/apply_engine.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/apply_engine_copy_sql.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/apply_identity_audit.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/branching.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/bulk_delete.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/changediff_audit.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/contributor_baseline.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/crypto.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/delete_policy.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/density_learning.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/direct_changes.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/execution_telemetry.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/executor_base.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/health_apply_fetch.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/health_summary_blocks.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/ingestion_merge.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/ingestion_presentation.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/interface_naming.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/job_liveness.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/job_queue.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/json_safe.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/license_tier.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/logging.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/merge_observability.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/merge_profiling.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/model_contracts.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/plugin_integrations/__init__.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/post_sync.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/query_binding.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/query_execution_contract.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/query_fetch.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/runtime_guidance.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/scope_ipam_audit.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/sync_cable.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/sync_dlm.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/sync_events.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/sync_interface.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/sync_inventory_module.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/sync_runner_contracts.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/sync_state.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/tag_contracts.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/tier3_reducers.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/upgrade_reconciliation.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/validation.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/validation_org_query.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/version_series.py +0 -0
- {forward_netbox-3.0.0 → forward_netbox-3.0.2}/forward_netbox/utilities/workload_normalization.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: forward-netbox
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.2
|
|
4
4
|
Summary: NetBox plugin to sync Forward data into NetBox via built-in NQE queries
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -27,12 +27,13 @@ Provides-Extra: integrations
|
|
|
27
27
|
Provides-Extra: peering
|
|
28
28
|
Provides-Extra: routing
|
|
29
29
|
Provides-Extra: validity
|
|
30
|
+
Requires-Dist: forward-sdk (==0.1.20)
|
|
30
31
|
Requires-Dist: httpx (>0.26,<0.29)
|
|
31
32
|
Requires-Dist: netbox-cisco-aci (==0.4.0) ; (python_version >= "3.12" and python_version < "3.15") and (extra == "aci" or extra == "integrations")
|
|
32
|
-
Requires-Dist: netbox-dlm (>=0.4.1,<0.
|
|
33
|
-
Requires-Dist: netbox-peering-manager (==0.3.
|
|
34
|
-
Requires-Dist: netbox-routing (
|
|
35
|
-
Requires-Dist: netbox-validity (==3.
|
|
33
|
+
Requires-Dist: netbox-dlm (>=0.4.1,<0.11.0) ; (python_version >= "3.12" and python_version < "3.15") and (extra == "dlm" or extra == "integrations")
|
|
34
|
+
Requires-Dist: netbox-peering-manager (==0.3.1) ; (python_version >= "3.12" and python_version < "3.15") and (extra == "peering" or extra == "integrations")
|
|
35
|
+
Requires-Dist: netbox-routing (>=0.5.0,<0.6.0) ; (python_version >= "3.12" and python_version < "3.15") and (extra == "routing" or extra == "integrations")
|
|
36
|
+
Requires-Dist: netbox-validity (==3.6.0) ; (python_version >= "3.12" and python_version < "3.15") and (extra == "validity" or extra == "integrations")
|
|
36
37
|
Requires-Dist: netboxlabs-netbox-branching (>=1.2.0,<1.3.0) ; python_version >= "3.12" and python_version < "3.15"
|
|
37
38
|
Requires-Dist: pyzipper (>=0.4.0,<0.5.0)
|
|
38
39
|
Project-URL: Changelog, https://github.com/forwardnetworks/forward-netbox/blob/main/CHANGELOG.md
|
|
@@ -108,15 +109,17 @@ See the
|
|
|
108
109
|
|
|
109
110
|
## Release Compatibility
|
|
110
111
|
|
|
111
|
-
The `3.0.
|
|
112
|
+
The `3.0.2` release candidate requires NetBox `4.7.x` (tested on `4.7.1`) and `netbox-branching` `1.2.x` (tested on `1.2.0`). Expand for the published release history and candidate notes.
|
|
112
113
|
|
|
113
114
|
<details>
|
|
114
115
|
<summary>Release compatibility history</summary>
|
|
115
116
|
|
|
116
117
|
| Plugin Release | NetBox Version | Status |
|
|
117
118
|
| --- | --- | --- |
|
|
118
|
-
| `v3.0.
|
|
119
|
-
| `
|
|
119
|
+
| `v3.0.2` | NetBox `4.7.x` supported, tested on `4.7.1`; needs netbox-branching `1.2.x`, tested on `1.2.0` | Release candidate; Port of 2.9.13's PeeringSession crash + endpoint /32 fixes, plus the 3.0.1 upgrade-runtime override fix |
|
|
120
|
+
| `v3.0.1` | NetBox `4.7.x` supported, tested on `4.7.1`; needs netbox-branching `1.2.x`, tested on `1.2.0` | Current release; Release candidate; Fix: every fix shipped on the 2.9.x line as 2.9.7 through 2.9.11 now ships on NetBox 4.7 - the 3.x line had none of them. Fix: renaming a device's site in Forward moves the existing device instead of creating a duplicate, devices are matched case-insensitively the way NetBox identifies them, and the new Scope Reconciliation action Merge site-relabel duplicates repairs pairs already created (keeps the older device at the site Forward reports; held pairs are listed with a reason and never pruned). Fix: scope membership is by name, so no in-scope device is called out of scope. Feature: duplicates and other silent problems are no longer silent - a Health check, a sync-page banner, a Scope Reconciliation card and a job-log line. Fix: config backup reaches the repository through the proxy NetBox uses, no longer writes credentials to the worker log, fails when the remote refuses the branch, and names the cause of a failure in the job, Health and the support bundle. Fix: the fast baseline, COPY/SQL and set-based merge run on any subset of the validated plugins. Fix: routing-policy scope counts every device that holds a definition, pending removals are what the next sync removes, and Scope Reconciliation offers Remove out-of-scope routing policy (an allowlisted, gated operator action). Fix: the SDK repository lookup read attributes the forward-sdk RepositoryQuery does not have, so committed-query lookups by path failed against a real Forward; forward-sdk is now 0.1.20. Fix: protection against deleting a sync or ingestion while a job runs, and support bundles and log exports no longer carry operator values such as include-tag names. Feature: the support bundle carries a diagnostics section, and a live query-drift check flags a published query whose parameter list no longer matches this release. Feature: Auto merge stops for review when a run is far larger than the sync has been - only with Auto merge on, only after the sync has finished a run before, and only for a model that stages at least 10,000 changes at 3x the table's size (or 10x the typical earlier run); a held run stays staged, with the ingestion's Merge and Delete actions as Merge anyway and Discard. Feature: Health and the support bundle show Forward's row count next to NetBox's per model, the last three ingestions with job and merge status, statistics and merged changes by model and action, and a BGP peer duplicate count, and flag an abnormal run, a baseline that never completed and a NetBox table far smaller than Forward's. Feature: the config backup folder is configurable (nested folders allowed), Health shows the Validity device_config_path for it, and the last backup reports rows, written, unchanged, unmapped, managed devices with no collected configuration and files in the folder. Fix: the Include unmanaged configuration checkbox never persisted from the source form. Migrations 0053 through 0057 and 0060 adopt the 2.9.x schema history. Org-backed deployments: run Publish Bundled Queries after upgrading, because the interface and IPv4 address queries changed their parameter lists (a stale published copy fails every execution against it until republished) and the three routing-policy queries gained an output column. |
|
|
121
|
+
| `v3.0.0` | NetBox `4.7.x` supported, tested on `4.7.0`; needs netbox-branching `1.2.x`, tested on `1.2.0` | Superseded by `v3.0.1`; NetBox 4.7 with netbox-branching 1.2, and change control gated on what Forward saw before and after the change. |
|
|
122
|
+
| `v2.9.2` | `4.6.x` (>= `4.6.5`) supported, tested on `4.6.8`; needs netbox-branching `1.1.x`, tested on `1.1.2` | Superseded by `v3.0.0`; Drift is measured exactly for every fetched model, the uncovered-device count says why it grows and warns when it does, and five delete and diagnostic defects are closed. |
|
|
120
123
|
| `v2.9.1` | `4.6.x` (>= `4.6.5`) supported, tested on `4.6.8`; needs netbox-branching `1.1.x`, tested on `1.1.2` | Superseded by `v2.9.2`; Accepts netbox-branching 1.1.3 and records the validated runtime in the lockfile. |
|
|
121
124
|
| `v2.9.0` | `4.6.x` (>= `4.6.5`) supported, tested on `4.6.8`; needs netbox-branching `1.1.x`, tested on `1.1.2` | Superseded by `v2.9.1`; Feature: back up device configurations from Forward into a git data source for Validity golden-config checks, plus the runtime-validation refactor and health check it required. |
|
|
122
125
|
| `v2.8.9` | `4.6.x` (>= `4.6.5`) supported, tested on `4.6.8`; needs netbox-branching `1.1.x`, tested on `1.1.2` | Superseded by `v2.9.0`; Fix: a sync deletes a device only on the same quarantined evidence the operator prune requires, and never stages a delete the database will refuse. |
|
|
@@ -64,15 +64,17 @@ See the
|
|
|
64
64
|
|
|
65
65
|
## Release Compatibility
|
|
66
66
|
|
|
67
|
-
The `3.0.
|
|
67
|
+
The `3.0.2` release candidate requires NetBox `4.7.x` (tested on `4.7.1`) and `netbox-branching` `1.2.x` (tested on `1.2.0`). Expand for the published release history and candidate notes.
|
|
68
68
|
|
|
69
69
|
<details>
|
|
70
70
|
<summary>Release compatibility history</summary>
|
|
71
71
|
|
|
72
72
|
| Plugin Release | NetBox Version | Status |
|
|
73
73
|
| --- | --- | --- |
|
|
74
|
-
| `v3.0.
|
|
75
|
-
| `
|
|
74
|
+
| `v3.0.2` | NetBox `4.7.x` supported, tested on `4.7.1`; needs netbox-branching `1.2.x`, tested on `1.2.0` | Release candidate; Port of 2.9.13's PeeringSession crash + endpoint /32 fixes, plus the 3.0.1 upgrade-runtime override fix |
|
|
75
|
+
| `v3.0.1` | NetBox `4.7.x` supported, tested on `4.7.1`; needs netbox-branching `1.2.x`, tested on `1.2.0` | Current release; Release candidate; Fix: every fix shipped on the 2.9.x line as 2.9.7 through 2.9.11 now ships on NetBox 4.7 - the 3.x line had none of them. Fix: renaming a device's site in Forward moves the existing device instead of creating a duplicate, devices are matched case-insensitively the way NetBox identifies them, and the new Scope Reconciliation action Merge site-relabel duplicates repairs pairs already created (keeps the older device at the site Forward reports; held pairs are listed with a reason and never pruned). Fix: scope membership is by name, so no in-scope device is called out of scope. Feature: duplicates and other silent problems are no longer silent - a Health check, a sync-page banner, a Scope Reconciliation card and a job-log line. Fix: config backup reaches the repository through the proxy NetBox uses, no longer writes credentials to the worker log, fails when the remote refuses the branch, and names the cause of a failure in the job, Health and the support bundle. Fix: the fast baseline, COPY/SQL and set-based merge run on any subset of the validated plugins. Fix: routing-policy scope counts every device that holds a definition, pending removals are what the next sync removes, and Scope Reconciliation offers Remove out-of-scope routing policy (an allowlisted, gated operator action). Fix: the SDK repository lookup read attributes the forward-sdk RepositoryQuery does not have, so committed-query lookups by path failed against a real Forward; forward-sdk is now 0.1.20. Fix: protection against deleting a sync or ingestion while a job runs, and support bundles and log exports no longer carry operator values such as include-tag names. Feature: the support bundle carries a diagnostics section, and a live query-drift check flags a published query whose parameter list no longer matches this release. Feature: Auto merge stops for review when a run is far larger than the sync has been - only with Auto merge on, only after the sync has finished a run before, and only for a model that stages at least 10,000 changes at 3x the table's size (or 10x the typical earlier run); a held run stays staged, with the ingestion's Merge and Delete actions as Merge anyway and Discard. Feature: Health and the support bundle show Forward's row count next to NetBox's per model, the last three ingestions with job and merge status, statistics and merged changes by model and action, and a BGP peer duplicate count, and flag an abnormal run, a baseline that never completed and a NetBox table far smaller than Forward's. Feature: the config backup folder is configurable (nested folders allowed), Health shows the Validity device_config_path for it, and the last backup reports rows, written, unchanged, unmapped, managed devices with no collected configuration and files in the folder. Fix: the Include unmanaged configuration checkbox never persisted from the source form. Migrations 0053 through 0057 and 0060 adopt the 2.9.x schema history. Org-backed deployments: run Publish Bundled Queries after upgrading, because the interface and IPv4 address queries changed their parameter lists (a stale published copy fails every execution against it until republished) and the three routing-policy queries gained an output column. |
|
|
76
|
+
| `v3.0.0` | NetBox `4.7.x` supported, tested on `4.7.0`; needs netbox-branching `1.2.x`, tested on `1.2.0` | Superseded by `v3.0.1`; NetBox 4.7 with netbox-branching 1.2, and change control gated on what Forward saw before and after the change. |
|
|
77
|
+
| `v2.9.2` | `4.6.x` (>= `4.6.5`) supported, tested on `4.6.8`; needs netbox-branching `1.1.x`, tested on `1.1.2` | Superseded by `v3.0.0`; Drift is measured exactly for every fetched model, the uncovered-device count says why it grows and warns when it does, and five delete and diagnostic defects are closed. |
|
|
76
78
|
| `v2.9.1` | `4.6.x` (>= `4.6.5`) supported, tested on `4.6.8`; needs netbox-branching `1.1.x`, tested on `1.1.2` | Superseded by `v2.9.2`; Accepts netbox-branching 1.1.3 and records the validated runtime in the lockfile. |
|
|
77
79
|
| `v2.9.0` | `4.6.x` (>= `4.6.5`) supported, tested on `4.6.8`; needs netbox-branching `1.1.x`, tested on `1.1.2` | Superseded by `v2.9.1`; Feature: back up device configurations from Forward into a git data source for Validity golden-config checks, plus the runtime-validation refactor and health check it required. |
|
|
78
80
|
| `v2.8.9` | `4.6.x` (>= `4.6.5`) supported, tested on `4.6.8`; needs netbox-branching `1.1.x`, tested on `1.1.2` | Superseded by `v2.9.0`; Fix: a sync deletes a device only on the same quarantined evidence the operator prune requires, and never stages a delete the database will refuse. |
|
|
@@ -5,7 +5,7 @@ class NetboxForwardConfig(PluginConfig):
|
|
|
5
5
|
name = "forward_netbox"
|
|
6
6
|
verbose_name = "Forward"
|
|
7
7
|
description = "Sync Forward data into NetBox using built-in NQE queries."
|
|
8
|
-
version = "3.0.
|
|
8
|
+
version = "3.0.2"
|
|
9
9
|
base_url = "forward"
|
|
10
10
|
min_version = "4.7.0"
|
|
11
11
|
max_version = "4.7.99"
|
|
@@ -378,6 +378,13 @@ class ForwardIngestionIssueSerializer(OrganizationalModelSerializer):
|
|
|
378
378
|
ingestion = ForwardIngestionSerializer(nested=True)
|
|
379
379
|
|
|
380
380
|
def to_representation(self, instance):
|
|
381
|
+
# Tier 1, deliberately: this is an authenticated in-deployment read,
|
|
382
|
+
# the same trust level as the GUI, so `raw_data` keeps its
|
|
383
|
+
# `operator_detail` values here. The redaction applies to FILES - a
|
|
384
|
+
# support bundle is exported to be sent to us, and
|
|
385
|
+
# `export_redaction.export_safe_payload` drops that key on every
|
|
386
|
+
# download path. Do not "fix" this by filtering here; the operator
|
|
387
|
+
# troubleshooting their own estate is the reason the values exist.
|
|
381
388
|
data = super().to_representation(instance)
|
|
382
389
|
data["coalesce_fields"] = json_safe_value(data.get("coalesce_fields"))
|
|
383
390
|
data["defaults"] = json_safe_value(data.get("defaults"))
|
|
@@ -40,8 +40,15 @@ from forward_netbox.models import ForwardNQEMap
|
|
|
40
40
|
from forward_netbox.models import ForwardSource
|
|
41
41
|
from forward_netbox.models import ForwardSync
|
|
42
42
|
from forward_netbox.models import ForwardValidationRun
|
|
43
|
+
from forward_netbox.utilities.forward_api import get_committed_nqe_query
|
|
44
|
+
from forward_netbox.utilities.forward_api import get_latest_processed_snapshot
|
|
45
|
+
from forward_netbox.utilities.forward_api import get_networks
|
|
46
|
+
from forward_netbox.utilities.forward_api import get_nqe_query_history
|
|
47
|
+
from forward_netbox.utilities.forward_api import get_nqe_repository_query_index
|
|
48
|
+
from forward_netbox.utilities.forward_api import get_snapshots
|
|
43
49
|
from forward_netbox.utilities.forward_api import LATEST_COLLECTED_SNAPSHOT
|
|
44
50
|
from forward_netbox.utilities.forward_api import LATEST_PROCESSED_SNAPSHOT
|
|
51
|
+
from forward_netbox.utilities.forward_api import run_nqe_query
|
|
45
52
|
from forward_netbox.utilities.query_binding import builtin_filename_to_query_default
|
|
46
53
|
from forward_netbox.utilities.query_binding import query_filename_from_path
|
|
47
54
|
|
|
@@ -139,7 +146,7 @@ class ForwardSourceViewSet(NetBoxModelViewSet):
|
|
|
139
146
|
results = []
|
|
140
147
|
if source is not None:
|
|
141
148
|
try:
|
|
142
|
-
for network in source.get_client()
|
|
149
|
+
for network in get_networks(source.get_client()):
|
|
143
150
|
if (
|
|
144
151
|
q
|
|
145
152
|
and q not in network["label"].lower()
|
|
@@ -245,7 +252,7 @@ class ForwardSourceViewSet(NetBoxModelViewSet):
|
|
|
245
252
|
tag_set = set()
|
|
246
253
|
try:
|
|
247
254
|
client = source.get_client()
|
|
248
|
-
snapshot =
|
|
255
|
+
snapshot = get_latest_processed_snapshot(client, network_id)
|
|
249
256
|
snapshot_id = str(snapshot.get("id") or "").strip()
|
|
250
257
|
if not snapshot_id:
|
|
251
258
|
return Response(
|
|
@@ -259,7 +266,8 @@ class ForwardSourceViewSet(NetBoxModelViewSet):
|
|
|
259
266
|
}
|
|
260
267
|
)
|
|
261
268
|
|
|
262
|
-
rows =
|
|
269
|
+
rows = run_nqe_query(
|
|
270
|
+
client,
|
|
263
271
|
query=(
|
|
264
272
|
"foreach device in network.devices\n"
|
|
265
273
|
"where device.snapshotInfo.result == DeviceSnapshotResult.completed\n"
|
|
@@ -336,7 +344,8 @@ class ForwardNQEMapViewSet(NetBoxModelViewSet):
|
|
|
336
344
|
)
|
|
337
345
|
|
|
338
346
|
try:
|
|
339
|
-
query_index =
|
|
347
|
+
query_index = get_nqe_repository_query_index(
|
|
348
|
+
source.get_client(),
|
|
340
349
|
repository=repository,
|
|
341
350
|
directory="/",
|
|
342
351
|
)
|
|
@@ -392,7 +401,8 @@ class ForwardNQEMapViewSet(NetBoxModelViewSet):
|
|
|
392
401
|
|
|
393
402
|
results = []
|
|
394
403
|
try:
|
|
395
|
-
query_index =
|
|
404
|
+
query_index = get_nqe_repository_query_index(
|
|
405
|
+
source.get_client(),
|
|
396
406
|
repository=repository,
|
|
397
407
|
directory=directory,
|
|
398
408
|
)
|
|
@@ -472,7 +482,8 @@ class ForwardNQEMapViewSet(NetBoxModelViewSet):
|
|
|
472
482
|
client = source.get_client()
|
|
473
483
|
if query_path and not query_id:
|
|
474
484
|
try:
|
|
475
|
-
query_index =
|
|
485
|
+
query_index = get_nqe_repository_query_index(
|
|
486
|
+
client,
|
|
476
487
|
repository=repository,
|
|
477
488
|
directory="/",
|
|
478
489
|
)
|
|
@@ -482,14 +493,15 @@ class ForwardNQEMapViewSet(NetBoxModelViewSet):
|
|
|
482
493
|
if indexed_query and indexed_query.get("queryId"):
|
|
483
494
|
query_id = str(indexed_query.get("queryId") or "").strip()
|
|
484
495
|
else:
|
|
485
|
-
committed_query =
|
|
496
|
+
committed_query = get_committed_nqe_query(
|
|
497
|
+
client,
|
|
486
498
|
repository=repository,
|
|
487
499
|
query_path=query_path,
|
|
488
500
|
commit_id="head",
|
|
489
501
|
query_index=query_index,
|
|
490
502
|
)
|
|
491
503
|
query_id = str(committed_query.get("queryId") or "").strip()
|
|
492
|
-
commits =
|
|
504
|
+
commits = get_nqe_query_history(client, query_id)
|
|
493
505
|
except Exception:
|
|
494
506
|
return Response(
|
|
495
507
|
{
|
|
@@ -592,7 +604,7 @@ class ForwardSyncViewSet(NetBoxModelViewSet):
|
|
|
592
604
|
return Response({"count": len(results), "results": results})
|
|
593
605
|
|
|
594
606
|
try:
|
|
595
|
-
for snapshot in source.get_client()
|
|
607
|
+
for snapshot in get_snapshots(source.get_client(), network_id):
|
|
596
608
|
display = snapshot["label"]
|
|
597
609
|
if q and q not in display.lower() and q not in snapshot["id"].lower():
|
|
598
610
|
continue
|
|
@@ -928,6 +940,283 @@ class ForwardSyncViewSet(NetBoxModelViewSet):
|
|
|
928
940
|
def tag_delete_eligible_ipam(self, request, pk):
|
|
929
941
|
return self._enqueue_button_job_response(request, "tag_delete_eligible_ipam")
|
|
930
942
|
|
|
943
|
+
@extend_schema(
|
|
944
|
+
methods=["post"],
|
|
945
|
+
request=EmptySerializer(),
|
|
946
|
+
responses={
|
|
947
|
+
201: JobSerializer(),
|
|
948
|
+
202: OpenApiResponse(
|
|
949
|
+
description='{"status": "already_running", "job_id": N}'
|
|
950
|
+
),
|
|
951
|
+
},
|
|
952
|
+
)
|
|
953
|
+
@action(detail=True, methods=["post"], url_path="recover-stuck-sync")
|
|
954
|
+
def recover_stuck_sync(self, request, pk):
|
|
955
|
+
return self._enqueue_button_job_response(request, "recover_stuck_sync")
|
|
956
|
+
|
|
957
|
+
@extend_schema(
|
|
958
|
+
methods=["post"],
|
|
959
|
+
request=EmptySerializer(),
|
|
960
|
+
responses={
|
|
961
|
+
201: JobSerializer(),
|
|
962
|
+
202: OpenApiResponse(
|
|
963
|
+
description=(
|
|
964
|
+
'{"status": "already_running"|"blocked_by_sync_run", '
|
|
965
|
+
'"job_id": N}'
|
|
966
|
+
)
|
|
967
|
+
),
|
|
968
|
+
},
|
|
969
|
+
)
|
|
970
|
+
@action(detail=True, methods=["post"], url_path="prune-uncovered")
|
|
971
|
+
def prune_uncovered(self, request, pk):
|
|
972
|
+
return self._enqueue_button_job_response(request, "prune_uncovered")
|
|
973
|
+
|
|
974
|
+
@extend_schema(
|
|
975
|
+
methods=["post"],
|
|
976
|
+
request=EmptySerializer(),
|
|
977
|
+
responses={
|
|
978
|
+
201: JobSerializer(),
|
|
979
|
+
202: OpenApiResponse(
|
|
980
|
+
description=(
|
|
981
|
+
'{"status": "already_running"|"blocked_by_sync_run", '
|
|
982
|
+
'"job_id": N}'
|
|
983
|
+
)
|
|
984
|
+
),
|
|
985
|
+
},
|
|
986
|
+
)
|
|
987
|
+
@action(detail=True, methods=["post"], url_path="prune-out-of-scope-catalogue")
|
|
988
|
+
def prune_out_of_scope_catalogue(self, request, pk):
|
|
989
|
+
return self._enqueue_button_job_response(
|
|
990
|
+
request, "prune_out_of_scope_catalogue"
|
|
991
|
+
)
|
|
992
|
+
|
|
993
|
+
@extend_schema(
|
|
994
|
+
methods=["post"],
|
|
995
|
+
request=EmptySerializer(),
|
|
996
|
+
responses={
|
|
997
|
+
201: JobSerializer(),
|
|
998
|
+
202: OpenApiResponse(
|
|
999
|
+
description=(
|
|
1000
|
+
'{"status": "already_running"|"blocked_by_sync_run", '
|
|
1001
|
+
'"job_id": N}'
|
|
1002
|
+
)
|
|
1003
|
+
),
|
|
1004
|
+
},
|
|
1005
|
+
)
|
|
1006
|
+
@action(detail=True, methods=["post"], url_path="merge-site-relabel-duplicates")
|
|
1007
|
+
def merge_site_relabel_duplicates(self, request, pk):
|
|
1008
|
+
return self._enqueue_button_job_response(
|
|
1009
|
+
request, "merge_site_relabel_duplicates"
|
|
1010
|
+
)
|
|
1011
|
+
|
|
1012
|
+
@extend_schema(
|
|
1013
|
+
methods=["post"],
|
|
1014
|
+
responses={
|
|
1015
|
+
201: JobSerializer(),
|
|
1016
|
+
202: OpenApiResponse(
|
|
1017
|
+
description=(
|
|
1018
|
+
'{"status": "already_running"|"blocked_by_sync_run", '
|
|
1019
|
+
'"job_id": N}'
|
|
1020
|
+
)
|
|
1021
|
+
),
|
|
1022
|
+
400: OpenApiResponse(
|
|
1023
|
+
description="missing or malformed `device`/`expected_blockers`"
|
|
1024
|
+
),
|
|
1025
|
+
},
|
|
1026
|
+
)
|
|
1027
|
+
@action(detail=True, methods=["post"], url_path="release-foreign-delete-blockers")
|
|
1028
|
+
def release_foreign_delete_blockers(self, request, pk):
|
|
1029
|
+
"""Release exactly the netbox_routing rows named as delete blockers.
|
|
1030
|
+
|
|
1031
|
+
Unlike every other button action here, this one has no whole-set
|
|
1032
|
+
meaning - there is no device to act on without one being named - so
|
|
1033
|
+
it validates its own body rather than going through
|
|
1034
|
+
`_enqueue_button_job_response`, which assumes an empty POST is a
|
|
1035
|
+
complete request.
|
|
1036
|
+
"""
|
|
1037
|
+
from ..utilities.sync_facade import button_job_permission
|
|
1038
|
+
from ..utilities.sync_facade import enqueue_button_job
|
|
1039
|
+
from ..utilities.sync_facade import JobAlreadyActive
|
|
1040
|
+
from ..utilities.sync_facade import JobBlockedBySyncRun
|
|
1041
|
+
|
|
1042
|
+
permission = button_job_permission("release_foreign_delete_blockers")
|
|
1043
|
+
if not request.user.has_perm(permission):
|
|
1044
|
+
raise PermissionDenied(
|
|
1045
|
+
f"This user does not have the `{permission}` permission."
|
|
1046
|
+
)
|
|
1047
|
+
data = request.data if isinstance(request.data, dict) else {}
|
|
1048
|
+
try:
|
|
1049
|
+
device_pk = int(data.get("device") or "")
|
|
1050
|
+
except (TypeError, ValueError):
|
|
1051
|
+
return Response(
|
|
1052
|
+
{"detail": "A `device` id is required."},
|
|
1053
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
1054
|
+
)
|
|
1055
|
+
expected_blockers = data.get("expected_blockers")
|
|
1056
|
+
if (
|
|
1057
|
+
not isinstance(expected_blockers, dict)
|
|
1058
|
+
or not expected_blockers
|
|
1059
|
+
or not all(
|
|
1060
|
+
isinstance(label, str) and isinstance(count, int)
|
|
1061
|
+
for label, count in expected_blockers.items()
|
|
1062
|
+
)
|
|
1063
|
+
):
|
|
1064
|
+
return Response(
|
|
1065
|
+
{
|
|
1066
|
+
"detail": (
|
|
1067
|
+
"`expected_blockers` must name at least one blocking "
|
|
1068
|
+
"row as {label: count}."
|
|
1069
|
+
)
|
|
1070
|
+
},
|
|
1071
|
+
status=status.HTTP_400_BAD_REQUEST,
|
|
1072
|
+
)
|
|
1073
|
+
sync = self.get_object()
|
|
1074
|
+
try:
|
|
1075
|
+
job = enqueue_button_job(
|
|
1076
|
+
sync,
|
|
1077
|
+
"release_foreign_delete_blockers",
|
|
1078
|
+
request.user,
|
|
1079
|
+
job_kwargs={
|
|
1080
|
+
"device_pk": device_pk,
|
|
1081
|
+
"expected_blockers": expected_blockers,
|
|
1082
|
+
},
|
|
1083
|
+
)
|
|
1084
|
+
except JobBlockedBySyncRun as exc:
|
|
1085
|
+
return Response(
|
|
1086
|
+
{
|
|
1087
|
+
"status": "blocked_by_sync_run",
|
|
1088
|
+
"job_id": exc.job.pk,
|
|
1089
|
+
"detail": (
|
|
1090
|
+
"This operation is blocked while a Forward sync job "
|
|
1091
|
+
"is active."
|
|
1092
|
+
),
|
|
1093
|
+
},
|
|
1094
|
+
status=status.HTTP_202_ACCEPTED,
|
|
1095
|
+
)
|
|
1096
|
+
except JobAlreadyActive as exc:
|
|
1097
|
+
return Response(
|
|
1098
|
+
{
|
|
1099
|
+
"status": "already_running",
|
|
1100
|
+
"job_id": exc.job.pk,
|
|
1101
|
+
"detail": "An equivalent job is already queued or running.",
|
|
1102
|
+
},
|
|
1103
|
+
status=status.HTTP_202_ACCEPTED,
|
|
1104
|
+
)
|
|
1105
|
+
return Response(
|
|
1106
|
+
JobSerializer(job, context={"request": request}).data, status=201
|
|
1107
|
+
)
|
|
1108
|
+
|
|
1109
|
+
@extend_schema(
|
|
1110
|
+
methods=["post"],
|
|
1111
|
+
request=EmptySerializer(),
|
|
1112
|
+
responses={
|
|
1113
|
+
201: JobSerializer(),
|
|
1114
|
+
202: OpenApiResponse(
|
|
1115
|
+
description=(
|
|
1116
|
+
'{"status": "already_running"|"blocked_by_sync_run", '
|
|
1117
|
+
'"job_id": N}'
|
|
1118
|
+
)
|
|
1119
|
+
),
|
|
1120
|
+
},
|
|
1121
|
+
)
|
|
1122
|
+
@action(detail=True, methods=["post"], url_path="config-backup")
|
|
1123
|
+
def config_backup(self, request, pk):
|
|
1124
|
+
return self._enqueue_button_job_response(request, "config_backup")
|
|
1125
|
+
|
|
1126
|
+
@extend_schema(
|
|
1127
|
+
methods=["post"],
|
|
1128
|
+
request=EmptySerializer(),
|
|
1129
|
+
responses={
|
|
1130
|
+
201: JobSerializer(),
|
|
1131
|
+
202: OpenApiResponse(
|
|
1132
|
+
description='{"status": "already_running", "job_id": N}'
|
|
1133
|
+
),
|
|
1134
|
+
},
|
|
1135
|
+
)
|
|
1136
|
+
@action(detail=True, methods=["post"], url_path="prune-stale-hardware-notices")
|
|
1137
|
+
def prune_stale_hardware_notices(self, request, pk):
|
|
1138
|
+
return self._enqueue_button_job_response(
|
|
1139
|
+
request, "prune_stale_hardware_notices"
|
|
1140
|
+
)
|
|
1141
|
+
|
|
1142
|
+
# Read-only audits that talk to Forward; the report pages render the
|
|
1143
|
+
# latest job. Same overlap guard and permission check as every button.
|
|
1144
|
+
@extend_schema(
|
|
1145
|
+
methods=["post"],
|
|
1146
|
+
request=EmptySerializer(),
|
|
1147
|
+
responses={
|
|
1148
|
+
201: JobSerializer(),
|
|
1149
|
+
202: OpenApiResponse(description="already running"),
|
|
1150
|
+
},
|
|
1151
|
+
)
|
|
1152
|
+
@action(detail=True, methods=["post"], url_path="audits/primary-ip")
|
|
1153
|
+
def audit_primary_ip(self, request, pk):
|
|
1154
|
+
return self._enqueue_button_job_response(request, "audit_primary_ip")
|
|
1155
|
+
|
|
1156
|
+
@extend_schema(
|
|
1157
|
+
methods=["post"],
|
|
1158
|
+
request=EmptySerializer(),
|
|
1159
|
+
responses={
|
|
1160
|
+
201: JobSerializer(),
|
|
1161
|
+
202: OpenApiResponse(description="already running"),
|
|
1162
|
+
},
|
|
1163
|
+
)
|
|
1164
|
+
@action(detail=True, methods=["post"], url_path="audits/global-ipam")
|
|
1165
|
+
def audit_global_ipam(self, request, pk):
|
|
1166
|
+
return self._enqueue_button_job_response(request, "audit_global_ipam")
|
|
1167
|
+
|
|
1168
|
+
@extend_schema(
|
|
1169
|
+
methods=["post"],
|
|
1170
|
+
request=EmptySerializer(),
|
|
1171
|
+
responses={
|
|
1172
|
+
201: JobSerializer(),
|
|
1173
|
+
202: OpenApiResponse(description="already running"),
|
|
1174
|
+
},
|
|
1175
|
+
)
|
|
1176
|
+
@action(detail=True, methods=["post"], url_path="audits/stale-hardware-notices")
|
|
1177
|
+
def audit_stale_hardware_notices(self, request, pk):
|
|
1178
|
+
return self._enqueue_button_job_response(
|
|
1179
|
+
request, "audit_stale_hardware_notices"
|
|
1180
|
+
)
|
|
1181
|
+
|
|
1182
|
+
@extend_schema(
|
|
1183
|
+
methods=["post"],
|
|
1184
|
+
request=EmptySerializer(),
|
|
1185
|
+
responses={
|
|
1186
|
+
201: JobSerializer(),
|
|
1187
|
+
202: OpenApiResponse(description="already running"),
|
|
1188
|
+
},
|
|
1189
|
+
)
|
|
1190
|
+
@action(detail=True, methods=["post"], url_path="audits/apply-identity")
|
|
1191
|
+
def audit_apply_identity(self, request, pk):
|
|
1192
|
+
return self._enqueue_button_job_response(request, "audit_apply_identity")
|
|
1193
|
+
|
|
1194
|
+
@extend_schema(
|
|
1195
|
+
methods=["post"],
|
|
1196
|
+
request=EmptySerializer(),
|
|
1197
|
+
responses={
|
|
1198
|
+
201: JobSerializer(),
|
|
1199
|
+
202: OpenApiResponse(description="already running"),
|
|
1200
|
+
},
|
|
1201
|
+
)
|
|
1202
|
+
@action(detail=True, methods=["post"], url_path="audits/apic-cimc-readiness")
|
|
1203
|
+
def audit_apic_cimc_readiness(self, request, pk):
|
|
1204
|
+
return self._enqueue_button_job_response(request, "audit_apic_cimc_readiness")
|
|
1205
|
+
|
|
1206
|
+
@extend_schema(
|
|
1207
|
+
methods=["post"],
|
|
1208
|
+
request=EmptySerializer(),
|
|
1209
|
+
responses={
|
|
1210
|
+
201: JobSerializer(),
|
|
1211
|
+
202: OpenApiResponse(description="already running"),
|
|
1212
|
+
},
|
|
1213
|
+
)
|
|
1214
|
+
@action(detail=True, methods=["post"], url_path="audits/fast-baseline-preflight")
|
|
1215
|
+
def audit_fast_baseline_preflight(self, request, pk):
|
|
1216
|
+
return self._enqueue_button_job_response(
|
|
1217
|
+
request, "audit_fast_baseline_preflight"
|
|
1218
|
+
)
|
|
1219
|
+
|
|
931
1220
|
|
|
932
1221
|
class ForwardIngestionViewSet(NetBoxReadOnlyModelViewSet):
|
|
933
1222
|
queryset = ForwardIngestion.objects.all()
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
# would silently compare two different questions.
|
|
7
7
|
from dataclasses import dataclass
|
|
8
8
|
|
|
9
|
+
from ..utilities.forward_api import resolve_nqe_query_reference
|
|
9
10
|
from ..utilities.query_execution_contract import query_source_sha256
|
|
10
11
|
from .choices import ForwardCriterionExpectationChoices as Expectation
|
|
11
12
|
|
|
@@ -31,7 +32,8 @@ def bind_criterion(criterion, client) -> BindResult:
|
|
|
31
32
|
if not criterion.query_path:
|
|
32
33
|
return BindResult(False, error="The criterion has no query path to bind.")
|
|
33
34
|
try:
|
|
34
|
-
resolved =
|
|
35
|
+
resolved = resolve_nqe_query_reference(
|
|
36
|
+
client,
|
|
35
37
|
repository="org",
|
|
36
38
|
query_path=criterion.query_path,
|
|
37
39
|
commit_id=criterion.commit_id or None,
|
|
@@ -10,6 +10,10 @@ FORWARD_BGP_MODELS = (
|
|
|
10
10
|
"netbox_routing.ospfinstance",
|
|
11
11
|
"netbox_routing.ospfarea",
|
|
12
12
|
"netbox_routing.ospfinterface",
|
|
13
|
+
"netbox_routing.prefixlistentry",
|
|
14
|
+
"netbox_routing.communitylistentry",
|
|
15
|
+
"netbox_routing.routemapentry",
|
|
16
|
+
"netbox_routing.staticroute",
|
|
13
17
|
"netbox_peering_manager.peeringsession",
|
|
14
18
|
)
|
|
15
19
|
|
|
@@ -33,6 +37,13 @@ FORWARD_ACI_MODELS = (
|
|
|
33
37
|
"netbox_cisco_aci.acibridgedomain",
|
|
34
38
|
"netbox_cisco_aci.acifilter",
|
|
35
39
|
"netbox_cisco_aci.acil3out",
|
|
40
|
+
"netbox_cisco_aci.aciappprofile",
|
|
41
|
+
"netbox_cisco_aci.aciendpointgroup",
|
|
42
|
+
"netbox_cisco_aci.acicontract",
|
|
43
|
+
"netbox_cisco_aci.acisubject",
|
|
44
|
+
"netbox_cisco_aci.acifilterentry",
|
|
45
|
+
"netbox_cisco_aci.acisubjectfilter",
|
|
46
|
+
"netbox_cisco_aci.acistaticportbinding",
|
|
36
47
|
)
|
|
37
48
|
|
|
38
49
|
FORWARD_SUPPORTED_MODELS = (
|
|
@@ -162,11 +162,45 @@ class ForwardIngestionIssueFilterSet(BaseFilterSet):
|
|
|
162
162
|
choices=ForwardIngestionPhaseChoices,
|
|
163
163
|
null_value=None,
|
|
164
164
|
)
|
|
165
|
+
# "Which of these actually stops the baseline" was answerable only by
|
|
166
|
+
# running a command against the ingestion. Same predicate as readiness.
|
|
167
|
+
blocking = django_filters.BooleanFilter(
|
|
168
|
+
method="filter_blocking",
|
|
169
|
+
label="Blocks baseline readiness",
|
|
170
|
+
)
|
|
165
171
|
|
|
166
172
|
class Meta:
|
|
167
173
|
model = ForwardIngestionIssue
|
|
168
174
|
fields = ("phase", "model", "timestamp", "exception", "message")
|
|
169
175
|
|
|
176
|
+
def filter_blocking(self, queryset, name, value):
|
|
177
|
+
from django.db.models import Q
|
|
178
|
+
|
|
179
|
+
from .utilities.ingestion_issues import blocking_issue_q
|
|
180
|
+
|
|
181
|
+
if value is None:
|
|
182
|
+
return queryset
|
|
183
|
+
# Matches the column, in both its exclusions. A row whose ingestion
|
|
184
|
+
# promoted blocked nothing; and a row the merge recorded as skipped
|
|
185
|
+
# blocked nothing either, because no retry can satisfy it - that is
|
|
186
|
+
# true whether or not the run went on to promote. Filtering to rows
|
|
187
|
+
# the column calls Blocking and getting back rows it calls Skipped or
|
|
188
|
+
# Promoted over is the same disagreement in the other direction.
|
|
189
|
+
#
|
|
190
|
+
# Rows written before 2.9.5 carry no `disposition` key, and they must
|
|
191
|
+
# keep their old behaviour with no migration. `~Q(disposition=...)`
|
|
192
|
+
# alone does NOT do that: a missing JSONB key reads as NULL, `NOT NULL`
|
|
193
|
+
# is NULL rather than true, and every legacy row would be dropped from
|
|
194
|
+
# the Blocking filter it used to match. The key's absence has to be
|
|
195
|
+
# tested explicitly.
|
|
196
|
+
not_skipped = ~Q(raw_data__has_key="disposition") | ~Q(
|
|
197
|
+
raw_data__disposition="skipped"
|
|
198
|
+
)
|
|
199
|
+
predicate = (
|
|
200
|
+
blocking_issue_q() & Q(ingestion__baseline_ready=False) & not_skipped
|
|
201
|
+
)
|
|
202
|
+
return queryset.filter(predicate if value else ~predicate)
|
|
203
|
+
|
|
170
204
|
def search(self, queryset, name, value):
|
|
171
205
|
if not value.strip():
|
|
172
206
|
return queryset
|