forward-netbox 3.0.2__tar.gz → 3.0.4__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.2 → forward_netbox-3.0.4}/PKG-INFO +7 -4
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/README.md +5 -3
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/__init__.py +1 -1
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_seed_ui_harness.py +2 -2
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_devices.nqe +12 -3
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_devices_with_netbox_aliases.nqe +12 -3
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/forwardsync_scope_reconciliation.html +5 -1
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_apply_engine.py +60 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_bulk_merge.py +14 -3
- forward_netbox-3.0.4/forward_netbox/tests/test_bundle_triage_diagnostics.py +208 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_endpoints_import.py +26 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_merge_rule_rejection.py +12 -0
- forward_netbox-3.0.4/forward_netbox/tests/test_null_vrf_identity.py +119 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_optional_plugin_versions.py +3 -3
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_ospf_drift_comparison.py +23 -1
- forward_netbox-3.0.4/forward_netbox/tests/test_ospf_instance_names.py +188 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_plugin_integrations.py +14 -4
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_primary_ip.py +55 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_primary_ip_integration.py +43 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_runtime_dependency_check.py +1 -1
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_scope_reconciliation_site_aware.py +56 -4
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_site_relabel_pairs_merge.py +34 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_site_relabel_prompts.py +20 -0
- forward_netbox-3.0.4/forward_netbox/tests/test_stale_untagged_vlan_cleared.py +141 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_sync.py +12 -12
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/apply_engine_bulk.py +99 -16
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/bundle_diagnostics.py +29 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/diagnostics.py +8 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/fast_baseline.py +1 -1
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/plugin_integrations/registry.py +28 -3
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/primary_ip.py +110 -6
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/scope_reconciliation.py +60 -19
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_contracts.py +8 -4
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_interface.py +33 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_routing_impl.py +90 -17
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/validated_runtime.py +1 -1
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/views.py +236 -1
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/pyproject.toml +8 -2
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/LICENSE +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/api/__init__.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/api/serializers.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/api/urls.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/api/views.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/change_control/__init__.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/change_control/choices.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/change_control/criteria.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/change_control/evidence.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/change_control/gates.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/change_control/policy.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/change_control/predict.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/change_control/state_machine.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/choices.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/exceptions.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/filtersets.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/forms.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/jobs.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/__init__.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/__init__.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_accept_merge_failures.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_apic_cimc_readiness_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_apply_identity_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_blocker_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_changediff_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_collection_gap_alert.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_device_name_ambiguity_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_device_scope_reconciliation_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_dlm_hardware_notice_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_fast_baseline_preflight.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_interface_vlan_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_link_vsys_parents.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_metrics.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_module_readiness.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_ownership_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_primary_ip_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_profile_merge.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_pushdown_profile.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_query_diff_coverage_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_resolve_query_ids.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_routing_dangling_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_scope_ipam_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_smoke_sync.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_stuck_job_alert.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_stuck_job_recover.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_tag_delete_eligible.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_validation_org_query_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_warning_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/management/commands/forward_watch_sync.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0001_initial.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0002_add_coalesce_fields.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0003_forwardingestionissue_context_fields.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0004_forwardingestion_baseline_fields.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0005_validation_and_reporting.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0006_alter_forwardnqemap_netbox_model.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0007_forwardingestion_persisted_change_counters.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0008_alter_forwardnqemap_netbox_model.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0009_alter_forwardnqemap_netbox_model.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0010_forwardvalidationrun_override_applied_and_more.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0011_forwardingestion_change_request_id.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0012_forwardnqemap_query_reference.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0013_execution_run_step.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0014_execution_step_fetch_scope.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0015_execution_step_apply_engine.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0016_execution_step_query_metrics.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0017_execution_step_row_counters.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0018_execution_run_reconciliation_events.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0019_forwardexecutionstep_query_parameters.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0020_execution_step_operation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0021_add_fhrpgroup_nqe_map_choice.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0022_alter_forwardnqemap_netbox_model.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0023_split_ip_address_maps.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0024_forwarddeviceanalysis.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0025_device_analysis_netboxmodel.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0026_forwarddeviceanalysis_collection_result.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0027_alter_forwardexecutionrun_backend.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0028_remove_forwardexecutionstep_run_and_more.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0029_forward_parent_device_cf.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0030_forwarddeviceanalysis_cve_ids.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0031_encrypt_source_password.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0032_alter_forwardnqemap_netbox_model.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0033_alter_forwardnqemap_netbox_model.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0034_source_ownership_provenance.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0035_initialize_ownership_control_plane.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0036_protect_ownership_provenance.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0037_merge_identity_and_assignment_provenance.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0038_managed_tag_domain_guard.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0039_forwardingestion_catchup_state.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0040_remove_redundant_nqe_settings.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0041_forwardworkloadstate.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0042_device_generic_relation_guards.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0043_forwardnqemap_diff_contract.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0044_contributor_baseline_cache.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0045_forwardmergeattempt.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0046_alter_forwardnqemap_netbox_model.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0047_ownership_reconciliation_cascade.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0048_forwardingestion_skipped_change_count.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0049_drift_policy_row_shrink_floor.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0050_contributor_baseline_cascade.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0051_ownership_provenance_stamp_nullable.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0052_device_absence_quarantine.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0053_alter_forwardsource_owner.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0053_routing_policy_nqe_map_choices.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0054_aci_tenant_policy_nqe_map_choices.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0054_forwardchange_forwardchangecriterion_and_more.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0055_change_control_approvals.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0055_operator_delete_releases_ownership.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0056_aci_attachment_nqe_map_choices.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0056_routing_policy_nqe_map_choices.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0057_aci_tenant_policy_nqe_map_choices.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0057_nqe_map_last_live_drift.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0058_operator_delete_releases_ownership.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0059_aci_attachment_nqe_map_choices.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0060_merge_maint_2_9_x_history.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/0061_static_route_nqe_map_choice.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/migrations/__init__.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/models.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/navigation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/__init__.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_aci_apic_cimc_inventory.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_aci_apic_filters.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_aci_apic_nodes.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_aci_apic_pods.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_aci_app_profiles.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_aci_bridge_domains.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_aci_command_inventory.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_aci_contracts.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_aci_endpoint_groups.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_aci_fabrics.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_aci_filter_entries.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_aci_filters.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_aci_l3outs.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_aci_nodes.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_aci_pods.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_aci_source_readiness.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_aci_static_port_bindings.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_aci_subject_filters.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_aci_subjects.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_aci_tenants.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_aci_vrfs.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_bgp_address_families.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_bgp_peer_address_families.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_bgp_peers.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_cimc_endpoint_inventory.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_config_backup.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_device_analysis.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_device_feature_tags.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_device_feature_tags_with_rules.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_device_models.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_device_models_with_netbox_aliases.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_device_types.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_device_vendors.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_dlm_apic_cimc_inventory_item_software.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_dlm_cves.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_dlm_device_software.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_dlm_hardware_notices.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_dlm_hardware_notices_with_netbox_aliases.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_dlm_inventory_item_software.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_dlm_software_versions.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_dlm_vulnerabilities.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_hsrp_groups.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_inferred_interface_cables.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_interfaces.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_inventory_items.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_ip_addresses_ipv4.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_ip_addresses_ipv6.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_ip_addresses_unassignable_diagnostics.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_locations.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_mac_addresses.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_modules.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_ospf_areas.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_ospf_instances.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_ospf_interfaces.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_peering_sessions.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_platforms.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_prefixes_ipv4.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_prefixes_ipv6.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_routing_community_lists.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_routing_import_diagnostics.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_routing_prefix_lists.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_routing_route_maps.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_static_routes.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_virtual_chassis.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_vlans.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/forward_vrfs.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/queries/netbox_utilities.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/signals.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/static/forward_netbox/img/fn-logo.svg +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tables.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/template_content.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/device_cves.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/forwardchange.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/forwardchangepolicy.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/forwarddeviceanalysis.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/forwarddriftpolicy.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/forwardingestion.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/forwardingestionissue.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/forwardnqemap.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/forwardsource.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/forwardsync.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/forwardsync_audit_report.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/forwardsync_audits.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/forwardsync_delete.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/forwardsync_dependency_preview.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/forwardsync_drift_report.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/forwardsync_health.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/forwardsync_module_readiness.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/forwardsync_uncovered_devices.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/forwardvalidationrun.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/htmx/forwardsync_delete_form.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/inc/brand_bar.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/inc/count_trend.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/inc/device_analysis_panel.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/inc/device_ownership_panel.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/inc/diff.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/inc/execution_insights.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/inc/logs_pending.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/inc/merge_form.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/inc/validation_force_allow_form.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/partials/change_explainability.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/partials/ingestion_all.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/partials/ingestion_merge_button.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/partials/ingestion_progress.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/partials/ingestion_statistics.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/partials/ingestion_status.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/partials/job_logs.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/partials/object_tabs.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/partials/stage_switcher_buttons.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templates/forward_netbox/partials/validation_force_allow_button.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templatetags/__init__.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/templatetags/forward_netbox_helpers.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/__init__.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/fixtures/aci_command_inventory_expected.json +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/fixtures/aci_discovery_expected.json +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_a_warning_is_not_a_failure.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_absence_quarantine.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_absent_configuration_detail.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_absent_device_does_not_block_tag_domain.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_accepted_merge_failures.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_aci_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_aci_source_readiness.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_adapter_drift_scale.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_api_serializer_base.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_api_usage.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_api_views.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_apic_cimc_readiness_audit_command.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_apply_identity_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_audit_report_views.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_bgp_peer_af_query.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_bgp_peer_comment_churn.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_bgp_peer_policy_links.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_bgp_peer_round_trip_variants.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_branch_budget_split.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_branching.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_brand_bar.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_builtin_query_id_binding.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_bulk_adapter_parity.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_bulk_merge_scale.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_bundle_diagnostics_parity.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_button_jobs.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_cable_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_catalogue_models_compare.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_change_control_evidence.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_change_control_gates.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_change_control_policy.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_change_control_predict.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_change_control_state_machine.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_change_explainability_full_counts.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_changediff_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_collection_collapse_guard.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_config_backup.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_config_backup_folder.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_config_backup_job_and_health.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_config_backup_path.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_config_backup_query.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_config_backup_result_evidence.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_constraint_diagnosis.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_contract_preflight_message.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_contributor_baseline.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_converged_models_are_measured.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_copy_sql_apply_engine.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_cross_site_vlan_revalidation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_crypto.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_density_observation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_dependency_preview_summary.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_device_analysis_query.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_device_name_case_identity.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_device_scope_reconciliation_audit_command.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_device_scope_tagging.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_device_site_relabel_identity.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_diagnostics_readback.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_diff_removal_allowlist.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_dlm_catalogue_conflicts.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_dlm_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_dlm_hardware_notice_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_dlm_integration.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_dlm_inventoryitem_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_drift_coverage_is_explained.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_drift_rows_are_distinguishable.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_durable_workload_state_attribution.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_empty_comparison_is_not_a_measurement.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_empty_workload_failure.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_endpoint_absence_detail.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_endpoint_ipv4_netmask.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_execute_by_query_id_without_commit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_execution_insights_delete_label.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_export_redaction.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_failed_run_model_evidence.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_fast_baseline.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_fast_paths_report_when_disabled.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_fast_paths_subset_runtime.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_fhrpgroup_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_field_reported_integrity_failures.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_force_allow_override.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_forms.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_forward_api.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_forward_client_errors.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_forward_client_factory.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_forward_usage_hooks.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_full_removal_reconciliation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_head_commit_from_listing.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_health.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_health_evidence.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_ingestion_delete.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_ingestion_is_deletable.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_ingestion_merge.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_interface_lookup_query_shape.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_interface_naming.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_interface_vlan_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_inventoryitem_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_ip_address_dedup_query.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_ipaddress_dup_global.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_issue_diagnosis.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_issue_rendering.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_job_liveness.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_job_queue.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_jobs.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_keyerror_names_its_key.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_license_tier.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_log_export.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_logging.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_merge_observability.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_merge_profiling.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_migration_dependencies.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_migration_lineage.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_migrations.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_mixed_model_change_diffs.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_model_view_routes.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_models.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_module_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_module_readiness.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_module_readiness_rollup.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_nqe_lint_blind_spots.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_operator_commands.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_operator_delete_releases_ownership.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_ospf_neighbour_rows_converge.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_ownership.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_ownership_command.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_ownership_completes_with_preexisting_status_tag.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_ownership_conflict_reason.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_ownership_lock_wait.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_ownership_migration.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_parameter_signature_drift.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_peering_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_plan_statistics_monotonic.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_post_sync.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_preview_isolation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_preview_primes_its_lookup_caches.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_preview_reports_its_cost.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_preview_runner_satisfies_the_priming_contract.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_primary_ip_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_primary_ip_duplicate_names.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_protected_delete_is_a_skip.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_protecting_reference_deletes.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_protecting_relations.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_provision_preflight.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_quarantine_cadence.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_query_binding.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_query_diff_coverage_audit_command.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_query_execution_contract.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_query_id_binding_end_to_end.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_query_registry.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_query_signature_drift_check.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_query_variants.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_raise_site_is_recorded.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_refused_deletes_are_not_staged.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_refused_deletes_are_retried.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_release_foreign_delete_blockers.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_release_readiness_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_reserved_status_tag_adoption.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_routing_apply_compare_round_trip.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_routing_catalogue_cleanup.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_routing_catalogue_drift.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_routing_catalogue_scope.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_row_collapsing.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_row_count_floor.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_run_size_anomaly.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_run_size_guard.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_scheduled_jobs.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_scope_audit_full.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_scope_ipam_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_scope_matched_tags.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_scope_module_ui.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_scope_reconciliation_view.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_scope_shrink_guard.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_scope_tag_slug_collision.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_sdk_result_contract.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_set_based_merge.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_skip_dependency_direction.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_skip_names_netbox_row.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_skip_raisers_name_dependency.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_skip_rollup_direction.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_smoke_sync_command.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_source_parameter_keys_agree.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_stability_hardening.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_static_routes_query.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_stuck_recovery.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_support_bundle_archive.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_sync_aci.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_sync_facade.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_sync_orchestration.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_sync_recurrence_pinning.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_sync_routing_policy.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_sync_routing_static.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_sync_runner_contracts.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_sync_state.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_taggeditem_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_tier3_reducers.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_tree_model_detection.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_uncovered_absence_and_trend.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_uncovered_device_cleanup.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_uncovered_device_tag.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_upgrade_reconciliation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_validated_runtime_is_declared_once.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_validation_org_query_audit_command.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_virtualchassis_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_vsys_parent.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_workload_normalization.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_workload_state.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/urls.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/__init__.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/api_usage.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/apic_cimc_readiness.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/apply_engine.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/apply_engine_copy_sql.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/apply_engine_decision.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/apply_identity_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/audit_reports.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/branch_budget.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/branch_lifecycle.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/branching.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/bulk_delete.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/bulk_merge.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/change_explainability.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/changediff_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/config_backup.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/config_backup_path.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/constraint_diagnosis.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/contributor_baseline.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/crypto.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/delete_policy.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/density_learning.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/device_analysis.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/direct_changes.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/dlm_notice_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/drift_report.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/execution_telemetry.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/executor_base.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/export_redaction.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/fast_baseline_models.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/forward_api.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/forward_api_impl.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/forward_client_config.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/forward_client_errors.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/forward_client_factory.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/forward_read_cache.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/forward_throttle.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/forward_usage.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/forward_usage_hooks.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/full_removal_reconciliation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/health.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/health_apply_fetch.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/health_checks.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/health_evidence.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/health_summary_blocks.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/ingestion_issues.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/ingestion_merge.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/ingestion_presentation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/interface_naming.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/interface_vlan_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/job_liveness.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/job_queue.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/json_safe.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/license_tier.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/logging.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/merge.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/merge_observability.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/merge_profiling.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/merge_set_based.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/model_contracts.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/model_validation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/module_readiness.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/ownership.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/plugin_integrations/__init__.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/post_sync.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/primary_ip_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/query_binding.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/query_binding_resolution.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/query_diagnostics.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/query_execution_contract.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/query_fetch.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/query_fetch_execution.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/query_registry.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/routing_catalogue_cleanup.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/routing_dangling_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/row_collapsing.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/run_size_anomaly.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/run_size_guard.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/runtime_guidance.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/scope_ipam_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/single_branch_executor.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/snapshot_freshness.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/stuck_recovery.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/support_bundle_archive.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_aci.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_cable.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_core_models.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_device.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_dlm.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_events.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_execution.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_facade.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_inventory_module.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_ipam.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_orchestration.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_primitives.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_reporting.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_routing.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_routing_policy.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_routing_static.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_runner_adapters.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_runner_contracts.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/sync_state.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/tag_contracts.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/tier3_reducers.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/upgrade_reconciliation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/validation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/validation_org_query.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/version_series.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/vsys_parent.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/workload_normalization.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/utilities/workload_state.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.4
|
|
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
|
|
@@ -36,6 +36,7 @@ Requires-Dist: netbox-routing (>=0.5.0,<0.6.0) ; (python_version >= "3.12" and p
|
|
|
36
36
|
Requires-Dist: netbox-validity (==3.6.0) ; (python_version >= "3.12" and python_version < "3.15") and (extra == "validity" or extra == "integrations")
|
|
37
37
|
Requires-Dist: netboxlabs-netbox-branching (>=1.2.0,<1.3.0) ; python_version >= "3.12" and python_version < "3.15"
|
|
38
38
|
Requires-Dist: pyzipper (>=0.4.0,<0.5.0)
|
|
39
|
+
Requires-Dist: scrapli (>=2022.7.30,<2026.10) ; (python_version >= "3.12" and python_version < "3.15") and (extra == "validity" or extra == "integrations")
|
|
39
40
|
Project-URL: Changelog, https://github.com/forwardnetworks/forward-netbox/blob/main/CHANGELOG.md
|
|
40
41
|
Project-URL: Documentation, https://github.com/forwardnetworks/forward-netbox/tree/main/docs
|
|
41
42
|
Project-URL: Homepage, https://github.com/forwardnetworks/forward-netbox
|
|
@@ -109,15 +110,17 @@ See the
|
|
|
109
110
|
|
|
110
111
|
## Release Compatibility
|
|
111
112
|
|
|
112
|
-
The `3.0.
|
|
113
|
+
The `3.0.4` 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.
|
|
113
114
|
|
|
114
115
|
<details>
|
|
115
116
|
<summary>Release compatibility history</summary>
|
|
116
117
|
|
|
117
118
|
| Plugin Release | NetBox Version | Status |
|
|
118
119
|
| --- | --- | --- |
|
|
119
|
-
| `v3.0.
|
|
120
|
-
| `v3.0.
|
|
120
|
+
| `v3.0.4` | NetBox `4.7.x` supported, tested on `4.7.1`; needs netbox-branching `1.2.x`, tested on `1.2.0` | Release candidate; OSPF instance name clashes keep a stable per-process name instead of being skipped; Infoblox and Palo Alto endpoints are named by vendor; netbox-dlm 0.10.1 and 0.10.2 accepted; the UI gate runs on agent-browser; support bundle gains endpoint mask, site placement and fallback-reason figures; tested on NetBox 4.7.2 and netbox-branching 1.2.1 |
|
|
121
|
+
| `v3.0.3` | NetBox `4.7.x` supported, tested on `4.7.1`; needs netbox-branching `1.2.x`, tested on `1.2.0` | Current release; Static routes in the global table import; site-relabel repair releases BGP address families; primary IP falls back to the management address when a tag cannot resolve; interfaces holding a VLAN from a previous site are cleared instead of refused on every sync; scrapli capped so NetBox starts with netbox-validity; OSPF instances named per VRF for netbox-routing 0.5.0; support bundle gains dependency versions, scope-report age, site mismatch, a primary-IP split and mask breakdown, and per-rule issue counts; tested on NetBox 4.7.2 and netbox-branching 1.2.1 |
|
|
122
|
+
| `v3.0.2` | NetBox `4.7.x` supported, tested on `4.7.1`; needs netbox-branching `1.2.x`, tested on `1.2.0` | Superseded by `v3.0.3`; Port of 2.9.13's PeeringSession crash + endpoint /32 fixes, plus the 3.0.1 upgrade-runtime override fix |
|
|
123
|
+
| `v3.0.1` | NetBox `4.7.x` supported, tested on `4.7.1`; needs netbox-branching `1.2.x`, tested on `1.2.0` | Superseded by `v3.0.2`; 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
124
|
| `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
125
|
| `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. |
|
|
123
126
|
| `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. |
|
|
@@ -64,15 +64,17 @@ See the
|
|
|
64
64
|
|
|
65
65
|
## Release Compatibility
|
|
66
66
|
|
|
67
|
-
The `3.0.
|
|
67
|
+
The `3.0.4` 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
|
-
| `v3.0.
|
|
74
|
+
| `v3.0.4` | NetBox `4.7.x` supported, tested on `4.7.1`; needs netbox-branching `1.2.x`, tested on `1.2.0` | Release candidate; OSPF instance name clashes keep a stable per-process name instead of being skipped; Infoblox and Palo Alto endpoints are named by vendor; netbox-dlm 0.10.1 and 0.10.2 accepted; the UI gate runs on agent-browser; support bundle gains endpoint mask, site placement and fallback-reason figures; tested on NetBox 4.7.2 and netbox-branching 1.2.1 |
|
|
75
|
+
| `v3.0.3` | NetBox `4.7.x` supported, tested on `4.7.1`; needs netbox-branching `1.2.x`, tested on `1.2.0` | Current release; Static routes in the global table import; site-relabel repair releases BGP address families; primary IP falls back to the management address when a tag cannot resolve; interfaces holding a VLAN from a previous site are cleared instead of refused on every sync; scrapli capped so NetBox starts with netbox-validity; OSPF instances named per VRF for netbox-routing 0.5.0; support bundle gains dependency versions, scope-report age, site mismatch, a primary-IP split and mask breakdown, and per-rule issue counts; tested on NetBox 4.7.2 and netbox-branching 1.2.1 |
|
|
76
|
+
| `v3.0.2` | NetBox `4.7.x` supported, tested on `4.7.1`; needs netbox-branching `1.2.x`, tested on `1.2.0` | Superseded by `v3.0.3`; Port of 2.9.13's PeeringSession crash + endpoint /32 fixes, plus the 3.0.1 upgrade-runtime override fix |
|
|
77
|
+
| `v3.0.1` | NetBox `4.7.x` supported, tested on `4.7.1`; needs netbox-branching `1.2.x`, tested on `1.2.0` | Superseded by `v3.0.2`; 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
78
|
| `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
79
|
| `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. |
|
|
78
80
|
| `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. |
|
|
@@ -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.4"
|
|
9
9
|
base_url = "forward"
|
|
10
10
|
min_version = "4.7.0"
|
|
11
11
|
max_version = "4.7.99"
|
|
@@ -27,7 +27,7 @@ from forward_netbox.utilities.ownership import required_ownership_domains
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
class Command(BaseCommand):
|
|
30
|
-
help = "Seed synthetic Forward NetBox records for the
|
|
30
|
+
help = "Seed synthetic Forward NetBox records for the agent-browser UI harness."
|
|
31
31
|
|
|
32
32
|
def add_arguments(self, parser):
|
|
33
33
|
parser.add_argument(
|
|
@@ -59,7 +59,7 @@ class Command(BaseCommand):
|
|
|
59
59
|
if os.getenv("FORWARD_UI_HARNESS_ISOLATED", "").lower() != "true":
|
|
60
60
|
raise CommandError(
|
|
61
61
|
"Synthetic UI fixtures may only be seeded in the isolated "
|
|
62
|
-
"`invoke
|
|
62
|
+
"`invoke ui-test` runtime."
|
|
63
63
|
)
|
|
64
64
|
user = self._ensure_superuser(
|
|
65
65
|
username=options["username"],
|
|
@@ -111,8 +111,17 @@ foreach row in (
|
|
|
111
111
|
// overlay like Avocent/Opengear (these are ordinary SNMP-GENERIC-class
|
|
112
112
|
// endpoints, ungated by sync_generic_endpoints), just a manufacturer
|
|
113
113
|
// signal for when SNMP returned no sysDescr/sysObjectID to read one from.
|
|
114
|
-
|
|
115
|
-
|
|
114
|
+
// These appliances answer sysDescr, but with text that does not name the
|
|
115
|
+
// vendor: an Infoblox NIOS box reports `Linux <hostname> <kernel>` (so the
|
|
116
|
+
// first token read as the manufacturer made it "Linux"), and a Panorama
|
|
117
|
+
// reports `Palo Alto Networks M-Series Appliance` (first token "Palo").
|
|
118
|
+
// The vendor's enterprise OID and the profile name identify them instead.
|
|
119
|
+
let isInfoblox = matches(sysObjId, "1.3.6.1.4.1.7779.*")
|
|
120
|
+
|| matches(sdLower, "*infoblox*")
|
|
121
|
+
|| matches(endpointProfileName, "*infoblox*")
|
|
122
|
+
let isPaloAlto = matches(sysObjId, "1.3.6.1.4.1.25461.*")
|
|
123
|
+
|| matches(sdLower, "*palo alto*")
|
|
124
|
+
|| matches(endpointProfileName, "*pano*")
|
|
116
125
|
|| matches(endpointProfileName, "*panorama*")
|
|
117
126
|
// Manufacturer: the overlay/profile match when one applies; else the
|
|
118
127
|
// first token of the cleaned sysDescr; "Unknown" only when none of the
|
|
@@ -120,9 +129,9 @@ foreach row in (
|
|
|
120
129
|
// profile is generic).
|
|
121
130
|
let ep_manuf_raw = if isAvocent then "Avocent"
|
|
122
131
|
else if isOpengear then "Opengear"
|
|
123
|
-
else if hasDescr then substring(replaceRegexMatches(sysDescrClean, re` .*`, ""), 0, 100)
|
|
124
132
|
else if isInfoblox then "Infoblox"
|
|
125
133
|
else if isPaloAlto then "Palo Alto Networks"
|
|
134
|
+
else if hasDescr then substring(replaceRegexMatches(sysDescrClean, re` .*`, ""), 0, 100)
|
|
126
135
|
else "Unknown"
|
|
127
136
|
let ep_manuf = if ep_manuf_raw == "" then "Unknown" else ep_manuf_raw
|
|
128
137
|
let ep_manuf_slug_raw = slugify(ep_manuf)
|
|
@@ -152,8 +152,17 @@ foreach row in (
|
|
|
152
152
|
// overlay like Avocent/Opengear (these are ordinary SNMP-GENERIC-class
|
|
153
153
|
// endpoints, ungated by sync_generic_endpoints), just a manufacturer
|
|
154
154
|
// signal for when SNMP returned no sysDescr/sysObjectID to read one from.
|
|
155
|
-
|
|
156
|
-
|
|
155
|
+
// These appliances answer sysDescr, but with text that does not name the
|
|
156
|
+
// vendor: an Infoblox NIOS box reports `Linux <hostname> <kernel>` (so the
|
|
157
|
+
// first token read as the manufacturer made it "Linux"), and a Panorama
|
|
158
|
+
// reports `Palo Alto Networks M-Series Appliance` (first token "Palo").
|
|
159
|
+
// The vendor's enterprise OID and the profile name identify them instead.
|
|
160
|
+
let isInfoblox = matches(sysObjId, "1.3.6.1.4.1.7779.*")
|
|
161
|
+
|| matches(sdLower, "*infoblox*")
|
|
162
|
+
|| matches(endpointProfileName, "*infoblox*")
|
|
163
|
+
let isPaloAlto = matches(sysObjId, "1.3.6.1.4.1.25461.*")
|
|
164
|
+
|| matches(sdLower, "*palo alto*")
|
|
165
|
+
|| matches(endpointProfileName, "*pano*")
|
|
157
166
|
|| matches(endpointProfileName, "*panorama*")
|
|
158
167
|
// Manufacturer: the overlay/profile match when one applies; else the
|
|
159
168
|
// first token of the cleaned sysDescr; "Unknown" only when none of the
|
|
@@ -161,9 +170,9 @@ foreach row in (
|
|
|
161
170
|
// profile is generic).
|
|
162
171
|
let ep_manuf_raw = if isAvocent then "Avocent"
|
|
163
172
|
else if isOpengear then "Opengear"
|
|
164
|
-
else if hasDescr then substring(replaceRegexMatches(sysDescrClean, re` .*`, ""), 0, 100)
|
|
165
173
|
else if isInfoblox then "Infoblox"
|
|
166
174
|
else if isPaloAlto then "Palo Alto Networks"
|
|
175
|
+
else if hasDescr then substring(replaceRegexMatches(sysDescrClean, re` .*`, ""), 0, 100)
|
|
167
176
|
else "Unknown"
|
|
168
177
|
let ep_manuf = if ep_manuf_raw == "" then "Unknown" else ep_manuf_raw
|
|
169
178
|
let ep_manuf_slug_raw = slugify(ep_manuf)
|
|
@@ -489,7 +489,11 @@
|
|
|
489
489
|
</p>
|
|
490
490
|
<ul class="mb-0">
|
|
491
491
|
{% for entry in site_relabel_pairs.held_by_reason %}
|
|
492
|
-
<li><strong>{{ entry.count }}</strong> - {{ entry.remedy|default:entry.reason }}
|
|
492
|
+
<li><strong>{{ entry.count }}</strong> - {{ entry.remedy|default:entry.reason }}
|
|
493
|
+
{% if entry.names %}
|
|
494
|
+
<div class="text-muted small">{{ entry.names|join:", " }}{% if entry.more_names %}, +{{ entry.more_names }} {% trans "more" %}{% endif %}</div>
|
|
495
|
+
{% endif %}
|
|
496
|
+
</li>
|
|
493
497
|
{% endfor %}
|
|
494
498
|
</ul>
|
|
495
499
|
{% endif %}
|
|
@@ -174,6 +174,66 @@ class ForwardBulkOrmApplyEngineTest(TestCase):
|
|
|
174
174
|
self.assertEqual(Site.objects.filter(name="Bad").count(), 0)
|
|
175
175
|
runner._record_issue.assert_called_once()
|
|
176
176
|
|
|
177
|
+
def test_isolate_bulk_objects_indexes_a_rescued_shard_once(self):
|
|
178
|
+
# A shard that fell back to row-by-row saves must cost the search cache
|
|
179
|
+
# one update, not one per row: every "Search cache update" is a queued
|
|
180
|
+
# job, and a large shard used to queue thousands.
|
|
181
|
+
from netbox.search import deferred
|
|
182
|
+
|
|
183
|
+
from forward_netbox.utilities.apply_engine_bulk import _isolate_bulk_objects
|
|
184
|
+
|
|
185
|
+
flushed = []
|
|
186
|
+
sites = [Site(name=f"Rescued {i}", slug=f"rescued-{i}") for i in range(25)]
|
|
187
|
+
|
|
188
|
+
with patch.object(
|
|
189
|
+
deferred, "_flush", lambda batch, using: flushed.append(dict(batch))
|
|
190
|
+
):
|
|
191
|
+
with self.captureOnCommitCallbacks(execute=True):
|
|
192
|
+
_isolate_bulk_objects(
|
|
193
|
+
Site, sites, "create", self._runner(), "dcim.site"
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
self.assertEqual(Site.objects.filter(slug__startswith="rescued-").count(), 25)
|
|
197
|
+
self.assertEqual(len(flushed), 1)
|
|
198
|
+
self.assertEqual(len(flushed[0]), 25)
|
|
199
|
+
|
|
200
|
+
def test_isolate_bulk_objects_does_not_index_a_row_that_failed(self):
|
|
201
|
+
from netbox.search import deferred
|
|
202
|
+
|
|
203
|
+
from forward_netbox.utilities.apply_engine_bulk import _isolate_bulk_objects
|
|
204
|
+
|
|
205
|
+
Site.objects.create(name="Taken", slug="taken")
|
|
206
|
+
flushed = []
|
|
207
|
+
good = Site(name="Good", slug="good")
|
|
208
|
+
bad = Site(name="Bad", slug="taken") # duplicate slug -> IntegrityError
|
|
209
|
+
|
|
210
|
+
with patch.object(
|
|
211
|
+
deferred, "_flush", lambda batch, using: flushed.append(dict(batch))
|
|
212
|
+
):
|
|
213
|
+
with self.captureOnCommitCallbacks(execute=True):
|
|
214
|
+
_isolate_bulk_objects(
|
|
215
|
+
Site, [good, bad], "create", self._runner(), "dcim.site"
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
indexed_pks = {pk for batch in flushed for (_type, pk) in batch}
|
|
219
|
+
self.assertEqual(indexed_pks, {good.pk})
|
|
220
|
+
|
|
221
|
+
def test_isolate_bulk_objects_restores_the_search_handler(self):
|
|
222
|
+
from netbox.search.backends import search_backend
|
|
223
|
+
|
|
224
|
+
from forward_netbox.utilities.apply_engine_bulk import _isolate_bulk_objects
|
|
225
|
+
|
|
226
|
+
before = search_backend.caching_handler
|
|
227
|
+
_isolate_bulk_objects(
|
|
228
|
+
Site,
|
|
229
|
+
[Site(name="Restore", slug="restore")],
|
|
230
|
+
"create",
|
|
231
|
+
self._runner(),
|
|
232
|
+
"dcim.site",
|
|
233
|
+
)
|
|
234
|
+
self.assertEqual(search_backend.caching_handler, before)
|
|
235
|
+
self.assertNotIn("caching_handler", vars(search_backend))
|
|
236
|
+
|
|
177
237
|
def test_bulk_orm_creates_and_updates_manufacturers(self):
|
|
178
238
|
self.sync.parameters["enable_bulk_orm"] = True
|
|
179
239
|
self.sync.save(update_fields=["parameters"])
|
|
@@ -4516,8 +4516,19 @@ class Phase4BulkStageTest(CleanTransactionTestCase):
|
|
|
4516
4516
|
request_id=merge_request_id,
|
|
4517
4517
|
)
|
|
4518
4518
|
# The member is audited as CREATE plus the internal deferred-LAG UPDATE;
|
|
4519
|
-
# the two audit rows still count as one logical branch change.
|
|
4520
|
-
|
|
4519
|
+
# the two audit rows still count as one logical branch change. Deleting
|
|
4520
|
+
# the cable also clears the parent's cached cable fields (`cable`,
|
|
4521
|
+
# `_path`, `cable_end`), which netbox-branching 1.2.1 records as its own
|
|
4522
|
+
# UPDATE: five rows, still all attributed to the invoking user.
|
|
4523
|
+
self.assertEqual(audits.count(), 5)
|
|
4524
|
+
self.assertEqual(
|
|
4525
|
+
audits.filter(
|
|
4526
|
+
changed_object_type=interface_type,
|
|
4527
|
+
changed_object_id=main_parent.pk,
|
|
4528
|
+
action="update",
|
|
4529
|
+
).count(),
|
|
4530
|
+
2,
|
|
4531
|
+
)
|
|
4521
4532
|
self.assertEqual(
|
|
4522
4533
|
set(audits.values_list("user_id", flat=True)), {invoking_user.pk}
|
|
4523
4534
|
)
|
|
@@ -4530,7 +4541,7 @@ class Phase4BulkStageTest(CleanTransactionTestCase):
|
|
|
4530
4541
|
)
|
|
4531
4542
|
self.assertEqual(
|
|
4532
4543
|
branch.get_merged_changes().filter(pk__in=audits).count(),
|
|
4533
|
-
|
|
4544
|
+
5,
|
|
4534
4545
|
)
|
|
4535
4546
|
self.assertEqual(
|
|
4536
4547
|
list(
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# The support bundle answers the questions a customer report actually asks.
|
|
2
|
+
#
|
|
3
|
+
# A customer's report this cycle could not be matched to its bundle: a three-day-old
|
|
4
|
+
# scope report sat beside a same-day sync, the primary-IP count had no split to
|
|
5
|
+
# reconcile against the device list, 147 issues had to be tallied by hand to find
|
|
6
|
+
# that 130 were one rule, and a dependency release that stopped NetBox starting left
|
|
7
|
+
# no version in the file. These pin the figures that close each gap, and that the
|
|
8
|
+
# export still carries counts rather than names.
|
|
9
|
+
import json
|
|
10
|
+
|
|
11
|
+
from dcim.models import Device
|
|
12
|
+
from dcim.models import DeviceRole
|
|
13
|
+
from dcim.models import DeviceType
|
|
14
|
+
from dcim.models import Manufacturer
|
|
15
|
+
from dcim.models import Site
|
|
16
|
+
from django.test import TestCase
|
|
17
|
+
from extras.models import Tag
|
|
18
|
+
|
|
19
|
+
from forward_netbox.models import ForwardDeviceIdentity
|
|
20
|
+
from forward_netbox.models import ForwardIngestion
|
|
21
|
+
from forward_netbox.models import ForwardIngestionIssue
|
|
22
|
+
from forward_netbox.models import ForwardSource
|
|
23
|
+
from forward_netbox.models import ForwardSync
|
|
24
|
+
from forward_netbox.utilities.bundle_diagnostics import bundle_diagnostics
|
|
25
|
+
from forward_netbox.utilities.export_redaction import export_safe_payload
|
|
26
|
+
from forward_netbox.views import _environment_bundle_payload
|
|
27
|
+
from forward_netbox.views import _ingestion_issue_bundle_payload
|
|
28
|
+
from forward_netbox.views import _primary_ip_bundle_payload
|
|
29
|
+
from forward_netbox.views import _scope_reconciliation_bundle_payload
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class BundleTriageDiagnosticsTest(TestCase):
|
|
33
|
+
def setUp(self):
|
|
34
|
+
self.site = Site.objects.create(name="Secret Street Site", slug="secret")
|
|
35
|
+
mfr = Manufacturer.objects.create(name="Cisco", slug="cisco")
|
|
36
|
+
self.device_type = DeviceType.objects.create(
|
|
37
|
+
manufacturer=mfr, model="M1", slug="m1"
|
|
38
|
+
)
|
|
39
|
+
self.role = DeviceRole.objects.create(name="firewall", slug="firewall")
|
|
40
|
+
source = ForwardSource.objects.create(
|
|
41
|
+
name="src", url="https://fwd.example.invalid"
|
|
42
|
+
)
|
|
43
|
+
self.sync = ForwardSync.objects.create(name="sync", source=source)
|
|
44
|
+
|
|
45
|
+
def _device(self, name, *, managed=True, tag=None):
|
|
46
|
+
device = Device.objects.create(
|
|
47
|
+
name=name,
|
|
48
|
+
site=self.site,
|
|
49
|
+
device_type=self.device_type,
|
|
50
|
+
role=self.role,
|
|
51
|
+
status="active",
|
|
52
|
+
)
|
|
53
|
+
if managed:
|
|
54
|
+
ForwardDeviceIdentity.objects.create(
|
|
55
|
+
sync=self.sync, device=device, source_device_key=name
|
|
56
|
+
)
|
|
57
|
+
if tag:
|
|
58
|
+
device.tags.add(Tag.objects.get_or_create(name=tag, slug=tag.lower())[0])
|
|
59
|
+
return device
|
|
60
|
+
|
|
61
|
+
def test_the_primary_ip_count_is_split_so_it_can_be_reconciled(self):
|
|
62
|
+
self._device("fw-uncovered", tag="forward-uncovered")
|
|
63
|
+
self._device("fw-mgmt", tag="Mgmt_Vl211")
|
|
64
|
+
self._device("fw-plain")
|
|
65
|
+
self._device("unmanaged", managed=False)
|
|
66
|
+
|
|
67
|
+
payload = _primary_ip_bundle_payload(self.sync)
|
|
68
|
+
|
|
69
|
+
self.assertEqual(payload["sync_devices"], 3)
|
|
70
|
+
self.assertEqual(payload["without_primary_ip"], 3)
|
|
71
|
+
split = payload["without_primary_ip_split"]
|
|
72
|
+
self.assertEqual(split["tagged_uncovered"], 1)
|
|
73
|
+
self.assertEqual(split["with_a_mgmt_tag"], 1)
|
|
74
|
+
self.assertEqual(split["with_no_ip_at_all"], 3)
|
|
75
|
+
self.assertEqual(split["with_an_interface_ip"], 0)
|
|
76
|
+
# The figure on the device list covers devices this sync does not own.
|
|
77
|
+
self.assertEqual(payload["netbox_devices_without_primary_ip"], 4)
|
|
78
|
+
|
|
79
|
+
def test_primary_addresses_are_counted_by_mask_and_host_masks_by_role(self):
|
|
80
|
+
from ipam.models import IPAddress
|
|
81
|
+
|
|
82
|
+
loopback = self._device("fw-loopback")
|
|
83
|
+
subnet = self._device("fw-subnet")
|
|
84
|
+
for device, address in ((loopback, "10.0.0.1/32"), (subnet, "10.0.1.1/24")):
|
|
85
|
+
ip = IPAddress.objects.create(address=address)
|
|
86
|
+
Device.objects.filter(pk=device.pk).update(primary_ip4=ip)
|
|
87
|
+
|
|
88
|
+
masks = _primary_ip_bundle_payload(self.sync)["primary_ip4_prefix_lengths"]
|
|
89
|
+
|
|
90
|
+
self.assertEqual(
|
|
91
|
+
{row["prefix_length"]: row["devices"] for row in masks["by_prefix_length"]},
|
|
92
|
+
{32: 1, 24: 1},
|
|
93
|
+
)
|
|
94
|
+
self.assertEqual(
|
|
95
|
+
masks["host_mask_by_role"], [{"role": "firewall", "devices": 1}]
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
def test_interface_addresses_are_counted_by_mask_and_the_default_site_is_listed(
|
|
99
|
+
self,
|
|
100
|
+
):
|
|
101
|
+
from dcim.models import Interface
|
|
102
|
+
from ipam.models import IPAddress
|
|
103
|
+
|
|
104
|
+
default = Site.objects.create(name="Default", slug="default")
|
|
105
|
+
endpoint = self._device("endpoint-1")
|
|
106
|
+
Device.objects.filter(pk=endpoint.pk).update(site=default)
|
|
107
|
+
switch = self._device("switch-1")
|
|
108
|
+
for device, address in ((endpoint, "10.0.0.9/32"), (switch, "10.0.1.1/24")):
|
|
109
|
+
interface = Interface.objects.create(
|
|
110
|
+
device=device, name="Gi0/1", type="1000base-t"
|
|
111
|
+
)
|
|
112
|
+
IPAddress.objects.create(address=address, assigned_object=interface)
|
|
113
|
+
|
|
114
|
+
payload = _primary_ip_bundle_payload(self.sync)
|
|
115
|
+
|
|
116
|
+
masks = payload["interface_ip4_prefix_lengths"]
|
|
117
|
+
self.assertEqual(
|
|
118
|
+
{
|
|
119
|
+
row["prefix_length"]: row["addresses"]
|
|
120
|
+
for row in masks["by_prefix_length"]
|
|
121
|
+
},
|
|
122
|
+
{32: 1, 24: 1},
|
|
123
|
+
)
|
|
124
|
+
self.assertEqual(
|
|
125
|
+
masks["host_mask_by_role"], [{"role": "firewall", "addresses": 1}]
|
|
126
|
+
)
|
|
127
|
+
placement = payload["site_placement"]
|
|
128
|
+
self.assertEqual(placement["at_default_site"], 1)
|
|
129
|
+
self.assertEqual(placement["at_default_site_by_role"], {"firewall": 1})
|
|
130
|
+
self.assertEqual(placement["at_default_site_without_primary_ip"], 1)
|
|
131
|
+
self.assertNotIn("endpoint-1", json.dumps(payload))
|
|
132
|
+
|
|
133
|
+
def test_issues_are_tallied_by_model_exception_and_rule_over_every_row(self):
|
|
134
|
+
ingestion = ForwardIngestion.objects.create(sync=self.sync)
|
|
135
|
+
for _ in range(3):
|
|
136
|
+
ForwardIngestionIssue.objects.create(
|
|
137
|
+
ingestion=ingestion,
|
|
138
|
+
model="dcim.interface",
|
|
139
|
+
exception="ValidationError",
|
|
140
|
+
message="Merge failed",
|
|
141
|
+
raw_data={"validation_rules": ["untagged-vlan-outside-device-site"]},
|
|
142
|
+
)
|
|
143
|
+
ForwardIngestionIssue.objects.create(
|
|
144
|
+
ingestion=ingestion,
|
|
145
|
+
model="dcim.site",
|
|
146
|
+
exception="ForwardDependencySkipError",
|
|
147
|
+
message="skipped",
|
|
148
|
+
raw_data={},
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
summary = _ingestion_issue_bundle_payload(ingestion)["summary"]
|
|
152
|
+
|
|
153
|
+
self.assertEqual(summary["counted"], 4)
|
|
154
|
+
self.assertEqual(
|
|
155
|
+
summary["by_model_and_exception"][0],
|
|
156
|
+
{"model": "dcim.interface", "exception": "ValidationError", "count": 3},
|
|
157
|
+
)
|
|
158
|
+
self.assertEqual(
|
|
159
|
+
summary["by_validation_rule"],
|
|
160
|
+
[
|
|
161
|
+
{
|
|
162
|
+
"model": "dcim.interface",
|
|
163
|
+
"rule": "untagged-vlan-outside-device-site",
|
|
164
|
+
"count": 3,
|
|
165
|
+
}
|
|
166
|
+
],
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
def test_the_environment_names_the_dependency_versions(self):
|
|
170
|
+
deps = _environment_bundle_payload()["dependency_versions"]
|
|
171
|
+
|
|
172
|
+
for name in ("scrapli", "scrapli-netconf", "forward-sdk", "django"):
|
|
173
|
+
self.assertIn(name, deps)
|
|
174
|
+
# A package that is not installed reads None, never an error.
|
|
175
|
+
self.assertTrue(all(v is None or isinstance(v, str) for v in deps.values()))
|
|
176
|
+
self.assertTrue(deps["django"])
|
|
177
|
+
|
|
178
|
+
def test_a_missing_scope_report_has_no_age_rather_than_a_wrong_one(self):
|
|
179
|
+
payload = _scope_reconciliation_bundle_payload(self.sync)
|
|
180
|
+
|
|
181
|
+
self.assertIsNone(payload["generated_at"])
|
|
182
|
+
self.assertIsNone(payload["age_hours"])
|
|
183
|
+
self.assertIsNone(payload["older_than_last_sync"])
|
|
184
|
+
|
|
185
|
+
def test_routing_name_collisions_reports_whether_the_plugin_is_there(self):
|
|
186
|
+
out = bundle_diagnostics(self.sync)
|
|
187
|
+
|
|
188
|
+
self.assertEqual(out["errors"], {})
|
|
189
|
+
collisions = out["routing_name_collisions"]
|
|
190
|
+
self.assertIn("installed", collisions)
|
|
191
|
+
if collisions["installed"]:
|
|
192
|
+
self.assertEqual(collisions["duplicate_name_groups"], 0)
|
|
193
|
+
|
|
194
|
+
def test_the_new_figures_export_without_names(self):
|
|
195
|
+
self._device("customer-firewall-01", tag="forward-uncovered")
|
|
196
|
+
text = json.dumps(
|
|
197
|
+
export_safe_payload(
|
|
198
|
+
{
|
|
199
|
+
"primary_ip": _primary_ip_bundle_payload(self.sync),
|
|
200
|
+
"diagnostics": bundle_diagnostics(self.sync),
|
|
201
|
+
"environment": _environment_bundle_payload(),
|
|
202
|
+
}
|
|
203
|
+
),
|
|
204
|
+
default=str,
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
self.assertNotIn("customer-firewall-01", text)
|
|
208
|
+
self.assertNotIn("Secret Street", text)
|
|
@@ -421,6 +421,32 @@ class EndpointBranchIncludeScopeTest(SimpleTestCase):
|
|
|
421
421
|
params = _default_query_parameters(filename)
|
|
422
422
|
self.assertIs(params["sync_generic_endpoints"], False, filename)
|
|
423
423
|
|
|
424
|
+
def test_vendor_overlays_name_the_manufacturer_before_the_sysdescr_token(self):
|
|
425
|
+
# An Infoblox box reports `Linux <host> <kernel>` and a Panorama reports
|
|
426
|
+
# `Palo Alto Networks ...`, so reading the first sysDescr token first
|
|
427
|
+
# made them "Linux" and "Palo". The enterprise OID and the profile name
|
|
428
|
+
# come before that token.
|
|
429
|
+
for filename in (
|
|
430
|
+
"forward_devices.nqe",
|
|
431
|
+
"forward_devices_with_netbox_aliases.nqe",
|
|
432
|
+
):
|
|
433
|
+
endpoint_branch = _read_query(filename).split("network.endpoints", 1)[1]
|
|
434
|
+
self.assertIn('matches(sysObjId, "1.3.6.1.4.1.7779.*")', endpoint_branch)
|
|
435
|
+
self.assertIn('matches(sysObjId, "1.3.6.1.4.1.25461.*")', endpoint_branch)
|
|
436
|
+
chain = endpoint_branch.split("let ep_manuf_raw", 1)[1].split(
|
|
437
|
+
"let ep_manuf =", 1
|
|
438
|
+
)[0]
|
|
439
|
+
self.assertLess(
|
|
440
|
+
chain.index('then "Infoblox"'),
|
|
441
|
+
chain.index("else if hasDescr"),
|
|
442
|
+
filename,
|
|
443
|
+
)
|
|
444
|
+
self.assertLess(
|
|
445
|
+
chain.index('then "Palo Alto Networks"'),
|
|
446
|
+
chain.index("else if hasDescr"),
|
|
447
|
+
filename,
|
|
448
|
+
)
|
|
449
|
+
|
|
424
450
|
def test_device_query_declares_toggle_default_off(self):
|
|
425
451
|
for filename in (
|
|
426
452
|
"forward_devices.nqe",
|
{forward_netbox-3.0.2 → forward_netbox-3.0.4}/forward_netbox/tests/test_merge_rule_rejection.py
RENAMED
|
@@ -398,6 +398,18 @@ class FieldScopedValidationRuleTests(SimpleTestCase):
|
|
|
398
398
|
["untagged-vlan-outside-device-site"], diagnosis["validation_rules"]
|
|
399
399
|
)
|
|
400
400
|
|
|
401
|
+
def test_an_ospf_name_collision_is_named(self):
|
|
402
|
+
# netbox-routing 0.5.0 unique (device, name): reported on a customer sync
|
|
403
|
+
# as an unrecognised rule until this slug existed.
|
|
404
|
+
diagnosis = structured_failure_diagnosis(
|
|
405
|
+
ValidationError(
|
|
406
|
+
"Name must be unique per device Only a single empty name is "
|
|
407
|
+
"permitted per device"
|
|
408
|
+
)
|
|
409
|
+
)
|
|
410
|
+
self.assertEqual(["name-not-unique-per-device"], diagnosis["validation_rules"])
|
|
411
|
+
self.assertNotIn("unrecognized_validation_rules", diagnosis)
|
|
412
|
+
|
|
401
413
|
def test_untagged_vlan_without_mode_is_named(self):
|
|
402
414
|
diagnosis = structured_failure_diagnosis(self.UNTAGGED_VLAN_MODE)
|
|
403
415
|
self.assertEqual(
|