forward-netbox 3.0.2__tar.gz → 3.0.3__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.3}/PKG-INFO +6 -4
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/README.md +4 -3
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/__init__.py +1 -1
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/forwardsync_scope_reconciliation.html +5 -1
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_bulk_merge.py +14 -3
- forward_netbox-3.0.3/forward_netbox/tests/test_bundle_triage_diagnostics.py +173 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_merge_rule_rejection.py +12 -0
- forward_netbox-3.0.3/forward_netbox/tests/test_null_vrf_identity.py +119 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_optional_plugin_versions.py +1 -1
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_ospf_drift_comparison.py +23 -1
- forward_netbox-3.0.3/forward_netbox/tests/test_ospf_instance_names.py +27 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_primary_ip.py +25 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_primary_ip_integration.py +43 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_runtime_dependency_check.py +1 -1
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_scope_reconciliation_site_aware.py +56 -4
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_site_relabel_pairs_merge.py +34 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_site_relabel_prompts.py +20 -0
- forward_netbox-3.0.3/forward_netbox/tests/test_stale_untagged_vlan_cleared.py +141 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_sync.py +12 -12
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/apply_engine_bulk.py +10 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/bundle_diagnostics.py +29 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/diagnostics.py +8 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/fast_baseline.py +1 -1
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/plugin_integrations/registry.py +22 -2
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/primary_ip.py +75 -6
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/scope_reconciliation.py +60 -19
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_contracts.py +8 -4
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_interface.py +33 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_routing_impl.py +17 -1
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/views.py +159 -1
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/pyproject.toml +8 -2
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/LICENSE +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/api/__init__.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/api/serializers.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/api/urls.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/api/views.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/change_control/__init__.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/change_control/choices.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/change_control/criteria.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/change_control/evidence.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/change_control/gates.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/change_control/policy.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/change_control/predict.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/change_control/state_machine.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/choices.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/exceptions.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/filtersets.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/forms.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/jobs.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/__init__.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/__init__.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_accept_merge_failures.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_apic_cimc_readiness_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_apply_identity_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_blocker_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_changediff_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_collection_gap_alert.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_device_name_ambiguity_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_device_scope_reconciliation_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_dlm_hardware_notice_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_fast_baseline_preflight.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_interface_vlan_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_link_vsys_parents.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_metrics.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_module_readiness.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_ownership_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_primary_ip_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_profile_merge.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_pushdown_profile.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_query_diff_coverage_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_resolve_query_ids.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_routing_dangling_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_scope_ipam_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_seed_ui_harness.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_smoke_sync.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_stuck_job_alert.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_stuck_job_recover.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_tag_delete_eligible.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_validation_org_query_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_warning_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/management/commands/forward_watch_sync.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0001_initial.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0002_add_coalesce_fields.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0003_forwardingestionissue_context_fields.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0004_forwardingestion_baseline_fields.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0005_validation_and_reporting.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0006_alter_forwardnqemap_netbox_model.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0007_forwardingestion_persisted_change_counters.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0008_alter_forwardnqemap_netbox_model.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0009_alter_forwardnqemap_netbox_model.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0010_forwardvalidationrun_override_applied_and_more.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0011_forwardingestion_change_request_id.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0012_forwardnqemap_query_reference.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0013_execution_run_step.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0014_execution_step_fetch_scope.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0015_execution_step_apply_engine.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0016_execution_step_query_metrics.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0017_execution_step_row_counters.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0018_execution_run_reconciliation_events.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0019_forwardexecutionstep_query_parameters.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0020_execution_step_operation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0021_add_fhrpgroup_nqe_map_choice.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0022_alter_forwardnqemap_netbox_model.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0023_split_ip_address_maps.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0024_forwarddeviceanalysis.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0025_device_analysis_netboxmodel.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0026_forwarddeviceanalysis_collection_result.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0027_alter_forwardexecutionrun_backend.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0028_remove_forwardexecutionstep_run_and_more.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0029_forward_parent_device_cf.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0030_forwarddeviceanalysis_cve_ids.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0031_encrypt_source_password.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0032_alter_forwardnqemap_netbox_model.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0033_alter_forwardnqemap_netbox_model.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0034_source_ownership_provenance.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0035_initialize_ownership_control_plane.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0036_protect_ownership_provenance.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0037_merge_identity_and_assignment_provenance.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0038_managed_tag_domain_guard.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0039_forwardingestion_catchup_state.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0040_remove_redundant_nqe_settings.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0041_forwardworkloadstate.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0042_device_generic_relation_guards.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0043_forwardnqemap_diff_contract.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0044_contributor_baseline_cache.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0045_forwardmergeattempt.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0046_alter_forwardnqemap_netbox_model.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0047_ownership_reconciliation_cascade.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0048_forwardingestion_skipped_change_count.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0049_drift_policy_row_shrink_floor.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0050_contributor_baseline_cascade.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0051_ownership_provenance_stamp_nullable.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0052_device_absence_quarantine.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0053_alter_forwardsource_owner.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0053_routing_policy_nqe_map_choices.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0054_aci_tenant_policy_nqe_map_choices.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0054_forwardchange_forwardchangecriterion_and_more.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0055_change_control_approvals.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0055_operator_delete_releases_ownership.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0056_aci_attachment_nqe_map_choices.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0056_routing_policy_nqe_map_choices.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0057_aci_tenant_policy_nqe_map_choices.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0057_nqe_map_last_live_drift.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0058_operator_delete_releases_ownership.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0059_aci_attachment_nqe_map_choices.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0060_merge_maint_2_9_x_history.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/0061_static_route_nqe_map_choice.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/migrations/__init__.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/models.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/navigation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/__init__.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_aci_apic_cimc_inventory.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_aci_apic_filters.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_aci_apic_nodes.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_aci_apic_pods.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_aci_app_profiles.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_aci_bridge_domains.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_aci_command_inventory.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_aci_contracts.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_aci_endpoint_groups.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_aci_fabrics.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_aci_filter_entries.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_aci_filters.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_aci_l3outs.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_aci_nodes.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_aci_pods.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_aci_source_readiness.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_aci_static_port_bindings.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_aci_subject_filters.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_aci_subjects.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_aci_tenants.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_aci_vrfs.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_bgp_address_families.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_bgp_peer_address_families.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_bgp_peers.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_cimc_endpoint_inventory.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_config_backup.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_device_analysis.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_device_feature_tags.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_device_feature_tags_with_rules.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_device_models.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_device_models_with_netbox_aliases.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_device_types.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_device_vendors.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_devices.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_devices_with_netbox_aliases.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_dlm_apic_cimc_inventory_item_software.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_dlm_cves.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_dlm_device_software.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_dlm_hardware_notices.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_dlm_hardware_notices_with_netbox_aliases.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_dlm_inventory_item_software.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_dlm_software_versions.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_dlm_vulnerabilities.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_hsrp_groups.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_inferred_interface_cables.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_interfaces.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_inventory_items.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_ip_addresses_ipv4.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_ip_addresses_ipv6.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_ip_addresses_unassignable_diagnostics.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_locations.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_mac_addresses.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_modules.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_ospf_areas.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_ospf_instances.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_ospf_interfaces.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_peering_sessions.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_platforms.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_prefixes_ipv4.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_prefixes_ipv6.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_routing_community_lists.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_routing_import_diagnostics.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_routing_prefix_lists.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_routing_route_maps.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_static_routes.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_virtual_chassis.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_vlans.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/forward_vrfs.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/queries/netbox_utilities.nqe +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/signals.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/static/forward_netbox/img/fn-logo.svg +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tables.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/template_content.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/device_cves.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/forwardchange.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/forwardchangepolicy.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/forwarddeviceanalysis.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/forwarddriftpolicy.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/forwardingestion.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/forwardingestionissue.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/forwardnqemap.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/forwardsource.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/forwardsync.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/forwardsync_audit_report.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/forwardsync_audits.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/forwardsync_delete.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/forwardsync_dependency_preview.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/forwardsync_drift_report.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/forwardsync_health.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/forwardsync_module_readiness.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/forwardsync_uncovered_devices.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/forwardvalidationrun.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/htmx/forwardsync_delete_form.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/inc/brand_bar.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/inc/count_trend.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/inc/device_analysis_panel.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/inc/device_ownership_panel.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/inc/diff.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/inc/execution_insights.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/inc/logs_pending.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/inc/merge_form.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/inc/validation_force_allow_form.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/partials/change_explainability.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/partials/ingestion_all.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/partials/ingestion_merge_button.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/partials/ingestion_progress.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/partials/ingestion_statistics.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/partials/ingestion_status.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/partials/job_logs.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/partials/object_tabs.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/partials/stage_switcher_buttons.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templates/forward_netbox/partials/validation_force_allow_button.html +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templatetags/__init__.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/templatetags/forward_netbox_helpers.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/__init__.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/fixtures/aci_command_inventory_expected.json +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/fixtures/aci_discovery_expected.json +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_a_warning_is_not_a_failure.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_absence_quarantine.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_absent_configuration_detail.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_absent_device_does_not_block_tag_domain.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_accepted_merge_failures.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_aci_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_aci_source_readiness.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_adapter_drift_scale.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_api_serializer_base.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_api_usage.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_api_views.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_apic_cimc_readiness_audit_command.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_apply_engine.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_apply_identity_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_audit_report_views.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_bgp_peer_af_query.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_bgp_peer_comment_churn.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_bgp_peer_policy_links.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_bgp_peer_round_trip_variants.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_branch_budget_split.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_branching.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_brand_bar.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_builtin_query_id_binding.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_bulk_adapter_parity.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_bulk_merge_scale.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_bundle_diagnostics_parity.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_button_jobs.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_cable_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_catalogue_models_compare.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_change_control_evidence.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_change_control_gates.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_change_control_policy.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_change_control_predict.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_change_control_state_machine.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_change_explainability_full_counts.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_changediff_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_collection_collapse_guard.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_config_backup.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_config_backup_folder.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_config_backup_job_and_health.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_config_backup_path.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_config_backup_query.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_config_backup_result_evidence.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_constraint_diagnosis.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_contract_preflight_message.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_contributor_baseline.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_converged_models_are_measured.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_copy_sql_apply_engine.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_cross_site_vlan_revalidation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_crypto.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_density_observation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_dependency_preview_summary.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_device_analysis_query.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_device_name_case_identity.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_device_scope_reconciliation_audit_command.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_device_scope_tagging.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_device_site_relabel_identity.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_diagnostics_readback.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_diff_removal_allowlist.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_dlm_catalogue_conflicts.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_dlm_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_dlm_hardware_notice_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_dlm_integration.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_dlm_inventoryitem_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_drift_coverage_is_explained.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_drift_rows_are_distinguishable.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_durable_workload_state_attribution.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_empty_comparison_is_not_a_measurement.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_empty_workload_failure.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_endpoint_absence_detail.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_endpoint_ipv4_netmask.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_endpoints_import.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_execute_by_query_id_without_commit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_execution_insights_delete_label.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_export_redaction.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_failed_run_model_evidence.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_fast_baseline.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_fast_paths_report_when_disabled.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_fast_paths_subset_runtime.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_fhrpgroup_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_field_reported_integrity_failures.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_force_allow_override.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_forms.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_forward_api.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_forward_client_errors.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_forward_client_factory.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_forward_usage_hooks.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_full_removal_reconciliation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_head_commit_from_listing.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_health.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_health_evidence.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_ingestion_delete.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_ingestion_is_deletable.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_ingestion_merge.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_interface_lookup_query_shape.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_interface_naming.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_interface_vlan_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_inventoryitem_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_ip_address_dedup_query.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_ipaddress_dup_global.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_issue_diagnosis.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_issue_rendering.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_job_liveness.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_job_queue.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_jobs.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_keyerror_names_its_key.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_license_tier.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_log_export.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_logging.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_merge_observability.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_merge_profiling.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_migration_dependencies.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_migration_lineage.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_migrations.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_mixed_model_change_diffs.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_model_view_routes.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_models.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_module_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_module_readiness.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_module_readiness_rollup.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_nqe_lint_blind_spots.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_operator_commands.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_operator_delete_releases_ownership.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_ospf_neighbour_rows_converge.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_ownership.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_ownership_command.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_ownership_completes_with_preexisting_status_tag.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_ownership_conflict_reason.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_ownership_lock_wait.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_ownership_migration.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_parameter_signature_drift.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_peering_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_plan_statistics_monotonic.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_plugin_integrations.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_post_sync.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_preview_isolation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_preview_primes_its_lookup_caches.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_preview_reports_its_cost.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_preview_runner_satisfies_the_priming_contract.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_primary_ip_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_primary_ip_duplicate_names.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_protected_delete_is_a_skip.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_protecting_reference_deletes.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_protecting_relations.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_provision_preflight.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_quarantine_cadence.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_query_binding.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_query_diff_coverage_audit_command.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_query_execution_contract.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_query_id_binding_end_to_end.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_query_registry.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_query_signature_drift_check.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_query_variants.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_raise_site_is_recorded.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_refused_deletes_are_not_staged.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_refused_deletes_are_retried.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_release_foreign_delete_blockers.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_release_readiness_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_reserved_status_tag_adoption.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_routing_apply_compare_round_trip.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_routing_catalogue_cleanup.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_routing_catalogue_drift.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_routing_catalogue_scope.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_row_collapsing.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_row_count_floor.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_run_size_anomaly.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_run_size_guard.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_scheduled_jobs.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_scope_audit_full.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_scope_ipam_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_scope_matched_tags.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_scope_module_ui.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_scope_reconciliation_view.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_scope_shrink_guard.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_scope_tag_slug_collision.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_sdk_result_contract.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_set_based_merge.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_skip_dependency_direction.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_skip_names_netbox_row.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_skip_raisers_name_dependency.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_skip_rollup_direction.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_smoke_sync_command.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_source_parameter_keys_agree.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_stability_hardening.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_static_routes_query.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_stuck_recovery.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_support_bundle_archive.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_sync_aci.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_sync_facade.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_sync_orchestration.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_sync_recurrence_pinning.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_sync_routing_policy.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_sync_routing_static.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_sync_runner_contracts.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_sync_state.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_taggeditem_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_tier3_reducers.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_tree_model_detection.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_uncovered_absence_and_trend.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_uncovered_device_cleanup.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_uncovered_device_tag.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_upgrade_reconciliation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_validated_runtime_is_declared_once.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_validation_org_query_audit_command.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_virtualchassis_drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_vsys_parent.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_workload_normalization.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_workload_state.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/urls.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/__init__.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/api_usage.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/apic_cimc_readiness.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/apply_engine.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/apply_engine_copy_sql.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/apply_engine_decision.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/apply_identity_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/audit_reports.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/branch_budget.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/branch_lifecycle.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/branching.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/bulk_delete.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/bulk_merge.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/change_explainability.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/changediff_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/config_backup.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/config_backup_path.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/constraint_diagnosis.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/contributor_baseline.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/crypto.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/delete_policy.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/density_learning.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/device_analysis.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/direct_changes.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/dlm_notice_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/drift_comparison.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/drift_report.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/execution_telemetry.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/executor_base.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/export_redaction.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/fast_baseline_models.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/forward_api.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/forward_api_impl.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/forward_client_config.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/forward_client_errors.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/forward_client_factory.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/forward_read_cache.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/forward_throttle.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/forward_usage.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/forward_usage_hooks.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/full_removal_reconciliation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/health.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/health_apply_fetch.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/health_checks.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/health_evidence.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/health_summary_blocks.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/ingestion_issues.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/ingestion_merge.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/ingestion_presentation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/interface_naming.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/interface_vlan_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/job_liveness.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/job_queue.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/json_safe.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/license_tier.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/logging.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/merge.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/merge_observability.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/merge_profiling.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/merge_set_based.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/model_contracts.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/model_validation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/module_readiness.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/ownership.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/plugin_integrations/__init__.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/post_sync.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/primary_ip_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/query_binding.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/query_binding_resolution.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/query_diagnostics.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/query_execution_contract.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/query_fetch.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/query_fetch_execution.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/query_registry.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/routing_catalogue_cleanup.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/routing_dangling_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/row_collapsing.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/run_size_anomaly.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/run_size_guard.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/runtime_guidance.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/scope_ipam_audit.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/single_branch_executor.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/snapshot_freshness.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/stuck_recovery.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/support_bundle_archive.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_aci.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_cable.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_core_models.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_device.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_dlm.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_events.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_execution.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_facade.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_inventory_module.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_ipam.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_orchestration.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_primitives.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_reporting.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_routing.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_routing_policy.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_routing_static.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_runner_adapters.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_runner_contracts.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/sync_state.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/tag_contracts.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/tier3_reducers.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/upgrade_reconciliation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/validated_runtime.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/validation.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/validation_org_query.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/version_series.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/vsys_parent.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/utilities/workload_normalization.py +0 -0
- {forward_netbox-3.0.2 → forward_netbox-3.0.3}/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.3
|
|
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,16 @@ See the
|
|
|
109
110
|
|
|
110
111
|
## Release Compatibility
|
|
111
112
|
|
|
112
|
-
The `3.0.
|
|
113
|
+
The `3.0.3` 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.3` | NetBox `4.7.x` supported, tested on `4.7.1`; needs netbox-branching `1.2.x`, tested on `1.2.0` | Release candidate; 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 |
|
|
121
|
+
| `v3.0.2` | NetBox `4.7.x` supported, tested on `4.7.1`; needs netbox-branching `1.2.x`, tested on `1.2.0` | Current release; Port of 2.9.13's PeeringSession crash + endpoint /32 fixes, plus the 3.0.1 upgrade-runtime override fix |
|
|
122
|
+
| `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
123
|
| `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
124
|
| `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
125
|
| `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,16 @@ See the
|
|
|
64
64
|
|
|
65
65
|
## Release Compatibility
|
|
66
66
|
|
|
67
|
-
The `3.0.
|
|
67
|
+
The `3.0.3` 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.3` | NetBox `4.7.x` supported, tested on `4.7.1`; needs netbox-branching `1.2.x`, tested on `1.2.0` | Release candidate; 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 |
|
|
75
|
+
| `v3.0.2` | NetBox `4.7.x` supported, tested on `4.7.1`; needs netbox-branching `1.2.x`, tested on `1.2.0` | Current release; Port of 2.9.13's PeeringSession crash + endpoint /32 fixes, plus the 3.0.1 upgrade-runtime override fix |
|
|
76
|
+
| `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
77
|
| `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
78
|
| `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
79
|
| `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.3"
|
|
9
9
|
base_url = "forward"
|
|
10
10
|
min_version = "4.7.0"
|
|
11
11
|
max_version = "4.7.99"
|
|
@@ -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 %}
|
|
@@ -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,173 @@
|
|
|
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_issues_are_tallied_by_model_exception_and_rule_over_every_row(self):
|
|
99
|
+
ingestion = ForwardIngestion.objects.create(sync=self.sync)
|
|
100
|
+
for _ in range(3):
|
|
101
|
+
ForwardIngestionIssue.objects.create(
|
|
102
|
+
ingestion=ingestion,
|
|
103
|
+
model="dcim.interface",
|
|
104
|
+
exception="ValidationError",
|
|
105
|
+
message="Merge failed",
|
|
106
|
+
raw_data={"validation_rules": ["untagged-vlan-outside-device-site"]},
|
|
107
|
+
)
|
|
108
|
+
ForwardIngestionIssue.objects.create(
|
|
109
|
+
ingestion=ingestion,
|
|
110
|
+
model="dcim.site",
|
|
111
|
+
exception="ForwardDependencySkipError",
|
|
112
|
+
message="skipped",
|
|
113
|
+
raw_data={},
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
summary = _ingestion_issue_bundle_payload(ingestion)["summary"]
|
|
117
|
+
|
|
118
|
+
self.assertEqual(summary["counted"], 4)
|
|
119
|
+
self.assertEqual(
|
|
120
|
+
summary["by_model_and_exception"][0],
|
|
121
|
+
{"model": "dcim.interface", "exception": "ValidationError", "count": 3},
|
|
122
|
+
)
|
|
123
|
+
self.assertEqual(
|
|
124
|
+
summary["by_validation_rule"],
|
|
125
|
+
[
|
|
126
|
+
{
|
|
127
|
+
"model": "dcim.interface",
|
|
128
|
+
"rule": "untagged-vlan-outside-device-site",
|
|
129
|
+
"count": 3,
|
|
130
|
+
}
|
|
131
|
+
],
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
def test_the_environment_names_the_dependency_versions(self):
|
|
135
|
+
deps = _environment_bundle_payload()["dependency_versions"]
|
|
136
|
+
|
|
137
|
+
for name in ("scrapli", "scrapli-netconf", "forward-sdk", "django"):
|
|
138
|
+
self.assertIn(name, deps)
|
|
139
|
+
# A package that is not installed reads None, never an error.
|
|
140
|
+
self.assertTrue(all(v is None or isinstance(v, str) for v in deps.values()))
|
|
141
|
+
self.assertTrue(deps["django"])
|
|
142
|
+
|
|
143
|
+
def test_a_missing_scope_report_has_no_age_rather_than_a_wrong_one(self):
|
|
144
|
+
payload = _scope_reconciliation_bundle_payload(self.sync)
|
|
145
|
+
|
|
146
|
+
self.assertIsNone(payload["generated_at"])
|
|
147
|
+
self.assertIsNone(payload["age_hours"])
|
|
148
|
+
self.assertIsNone(payload["older_than_last_sync"])
|
|
149
|
+
|
|
150
|
+
def test_routing_name_collisions_reports_whether_the_plugin_is_there(self):
|
|
151
|
+
out = bundle_diagnostics(self.sync)
|
|
152
|
+
|
|
153
|
+
self.assertEqual(out["errors"], {})
|
|
154
|
+
collisions = out["routing_name_collisions"]
|
|
155
|
+
self.assertIn("installed", collisions)
|
|
156
|
+
if collisions["installed"]:
|
|
157
|
+
self.assertEqual(collisions["duplicate_name_groups"], 0)
|
|
158
|
+
|
|
159
|
+
def test_the_new_figures_export_without_names(self):
|
|
160
|
+
self._device("customer-firewall-01", tag="forward-uncovered")
|
|
161
|
+
text = json.dumps(
|
|
162
|
+
export_safe_payload(
|
|
163
|
+
{
|
|
164
|
+
"primary_ip": _primary_ip_bundle_payload(self.sync),
|
|
165
|
+
"diagnostics": bundle_diagnostics(self.sync),
|
|
166
|
+
"environment": _environment_bundle_payload(),
|
|
167
|
+
}
|
|
168
|
+
),
|
|
169
|
+
default=str,
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
self.assertNotIn("customer-firewall-01", text)
|
|
173
|
+
self.assertNotIn("Secret Street", text)
|
{forward_netbox-3.0.2 → forward_netbox-3.0.3}/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(
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
from unittest import TestCase
|
|
2
|
+
|
|
3
|
+
from forward_netbox.exceptions import ForwardQueryError
|
|
4
|
+
from forward_netbox.utilities.sync_contracts import MODEL_SYNC_CONTRACTS
|
|
5
|
+
from forward_netbox.utilities.sync_contracts import row_coalesce_field_is_complete
|
|
6
|
+
from forward_netbox.utilities.sync_contracts import validate_row_shape_for_model
|
|
7
|
+
|
|
8
|
+
# Models whose bundled query emits a null `vrf` for the global routing table
|
|
9
|
+
# (`vrf: ... else null`) or for a route outside any VRF. Their default coalesce
|
|
10
|
+
# set names `vrf`, so a null `vrf` must still identify the row: a global route
|
|
11
|
+
# is a real, ordinary row, not an incomplete one.
|
|
12
|
+
GLOBAL_TABLE_MODELS = (
|
|
13
|
+
"netbox_routing.staticroute",
|
|
14
|
+
"netbox_routing.bgppeer",
|
|
15
|
+
"netbox_routing.bgpaddressfamily",
|
|
16
|
+
"netbox_routing.bgppeeraddressfamily",
|
|
17
|
+
"netbox_routing.ospfinstance",
|
|
18
|
+
"netbox_peering_manager.peeringsession",
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _identity_row(model_string):
|
|
23
|
+
contract = MODEL_SYNC_CONTRACTS[model_string]
|
|
24
|
+
row = {field: "x" for field in contract.required_fields}
|
|
25
|
+
for field_set in contract.default_coalesce_fields:
|
|
26
|
+
for field in field_set:
|
|
27
|
+
row[field] = "x"
|
|
28
|
+
row["vrf"] = None
|
|
29
|
+
return row
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class NullVrfIdentityTest(TestCase):
|
|
33
|
+
def test_a_global_row_satisfies_the_default_coalesce_set(self):
|
|
34
|
+
for model_string in GLOBAL_TABLE_MODELS:
|
|
35
|
+
with self.subTest(model=model_string):
|
|
36
|
+
contract = MODEL_SYNC_CONTRACTS[model_string]
|
|
37
|
+
sets = [list(s) for s in contract.default_coalesce_fields]
|
|
38
|
+
try:
|
|
39
|
+
validate_row_shape_for_model(
|
|
40
|
+
model_string, _identity_row(model_string), sets
|
|
41
|
+
)
|
|
42
|
+
except ForwardQueryError as exc:
|
|
43
|
+
self.fail(f"{model_string} rejects a global-table row: {exc}")
|
|
44
|
+
|
|
45
|
+
def test_the_static_route_row_shape_the_bundled_query_emits_is_accepted(self):
|
|
46
|
+
validate_row_shape_for_model(
|
|
47
|
+
"netbox_routing.staticroute",
|
|
48
|
+
{
|
|
49
|
+
"device": "sw-a",
|
|
50
|
+
"os": "OS.NXOS",
|
|
51
|
+
"vrf": None,
|
|
52
|
+
"family": "ip",
|
|
53
|
+
"args": "0.0.0.0/0 10.0.0.1",
|
|
54
|
+
},
|
|
55
|
+
[["device", "vrf", "family", "args"]],
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
def test_a_missing_vrf_key_is_still_rejected(self):
|
|
59
|
+
row = _identity_row("netbox_routing.staticroute")
|
|
60
|
+
del row["vrf"]
|
|
61
|
+
with self.assertRaises(ForwardQueryError):
|
|
62
|
+
validate_row_shape_for_model(
|
|
63
|
+
"netbox_routing.staticroute",
|
|
64
|
+
row,
|
|
65
|
+
[["device", "vrf", "family", "args"]],
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
def test_other_identity_fields_stay_required(self):
|
|
69
|
+
for field in ("device", "family", "args"):
|
|
70
|
+
with self.subTest(field=field):
|
|
71
|
+
row = _identity_row("netbox_routing.staticroute")
|
|
72
|
+
row[field] = None
|
|
73
|
+
with self.assertRaises(ForwardQueryError):
|
|
74
|
+
validate_row_shape_for_model(
|
|
75
|
+
"netbox_routing.staticroute",
|
|
76
|
+
row,
|
|
77
|
+
[["device", "vrf", "family", "args"]],
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
def test_a_null_vrf_is_complete_only_for_models_that_have_a_global_table(self):
|
|
81
|
+
self.assertFalse(
|
|
82
|
+
row_coalesce_field_is_complete("dcim.device", {"vrf": None}, "vrf")
|
|
83
|
+
)
|
|
84
|
+
self.assertTrue(
|
|
85
|
+
row_coalesce_field_is_complete(
|
|
86
|
+
"netbox_routing.staticroute", {"vrf": None}, "vrf"
|
|
87
|
+
)
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class RowShapeFailureIsNamedTest(TestCase):
|
|
92
|
+
def test_a_row_shape_refusal_is_named_not_unrecognized(self):
|
|
93
|
+
from forward_netbox.utilities.diagnostics import failure_reason
|
|
94
|
+
|
|
95
|
+
identity = ForwardQueryError(
|
|
96
|
+
"Row for `netbox_routing.staticroute` does not satisfy any configured "
|
|
97
|
+
"coalesce field set."
|
|
98
|
+
)
|
|
99
|
+
required = ForwardQueryError(
|
|
100
|
+
"Row for `netbox_routing.staticroute` is missing required fields: args."
|
|
101
|
+
)
|
|
102
|
+
self.assertEqual(failure_reason(identity), "row-identity-incomplete")
|
|
103
|
+
self.assertIn("shape-error", failure_reason(required))
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class RoutingAdapterReadinessTest(TestCase):
|
|
107
|
+
def test_every_routing_model_reports_its_adapters_present(self):
|
|
108
|
+
from forward_netbox.utilities.plugin_integrations.registry import (
|
|
109
|
+
integration_adapter_contract_summary,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
summary = integration_adapter_contract_summary()
|
|
113
|
+
routing = next(
|
|
114
|
+
value for key, value in summary.items() if key.startswith("routing")
|
|
115
|
+
)
|
|
116
|
+
self.assertEqual(routing["gaps"], [], routing["gaps"])
|
|
117
|
+
models = {entry["model"] for entry in routing["models"]}
|
|
118
|
+
self.assertIn("netbox_routing.staticroute", models)
|
|
119
|
+
self.assertIn("netbox_routing.routemapentry", models)
|
{forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_ospf_drift_comparison.py
RENAMED
|
@@ -77,10 +77,11 @@ class OspfPreviewTest(TestCase):
|
|
|
77
77
|
|
|
78
78
|
def _existing_instance(self, *, router_id="10.0.0.1", vrf=None):
|
|
79
79
|
from forward_netbox.utilities.sync_routing_impl import ospf_instance_comments
|
|
80
|
+
from forward_netbox.utilities.sync_routing_impl import ospf_instance_name
|
|
80
81
|
|
|
81
82
|
OSPFInstance, _, _ = _ospf_models()
|
|
82
83
|
return OSPFInstance.objects.create(
|
|
83
|
-
name=
|
|
84
|
+
name=ospf_instance_name(self.device.name, "1", vrf.name if vrf else None),
|
|
84
85
|
router_id=router_id,
|
|
85
86
|
process_id=1,
|
|
86
87
|
device=self.device,
|
|
@@ -239,6 +240,27 @@ class OspfPreviewTest(TestCase):
|
|
|
239
240
|
result = compare_model_rows(None, INSTANCE, [self._row(vrf="TENANT-B")])
|
|
240
241
|
self.assertEqual(result["unchanged"], 1)
|
|
241
242
|
|
|
243
|
+
def test_a_vrf_instance_with_the_old_unsuffixed_name_is_renamed_not_created(self):
|
|
244
|
+
# Instances written before the name carried the VRF are matched on
|
|
245
|
+
# (device, vrf, process_id), so the sync renames them in place.
|
|
246
|
+
from forward_netbox.utilities.sync_routing_impl import ospf_instance_comments
|
|
247
|
+
|
|
248
|
+
OSPFInstance, _, _ = _ospf_models()
|
|
249
|
+
vrf = VRF.objects.create(name="TENANT-C")
|
|
250
|
+
OSPFInstance.objects.create(
|
|
251
|
+
name=f"{self.device.name} OSPF 1",
|
|
252
|
+
router_id="10.0.0.1",
|
|
253
|
+
process_id=1,
|
|
254
|
+
device=self.device,
|
|
255
|
+
vrf=vrf,
|
|
256
|
+
comments=ospf_instance_comments(self._row(), "1"),
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
result = compare_model_rows(None, INSTANCE, [self._row(vrf="TENANT-C")])
|
|
260
|
+
|
|
261
|
+
self.assertEqual(result["creates"], 0)
|
|
262
|
+
self.assertEqual(result["unchanged"], 0)
|
|
263
|
+
|
|
242
264
|
# --- rows the apply refuses -------------------------------------------
|
|
243
265
|
|
|
244
266
|
def test_an_instance_without_a_router_id_is_rejected(self):
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from unittest import TestCase
|
|
2
|
+
|
|
3
|
+
from forward_netbox.utilities.sync_routing_impl import ospf_instance_name
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class OspfInstanceNameTest(TestCase):
|
|
7
|
+
def test_the_global_table_keeps_the_name_it_always_had(self):
|
|
8
|
+
self.assertEqual(
|
|
9
|
+
ospf_instance_name("sw-a", "default", None), "sw-a OSPF default"
|
|
10
|
+
)
|
|
11
|
+
self.assertEqual(ospf_instance_name("sw-a", "1", ""), "sw-a OSPF 1")
|
|
12
|
+
|
|
13
|
+
def test_the_same_process_in_two_vrfs_gets_two_names(self):
|
|
14
|
+
# netbox-routing 0.5.0 enforces unique (device, name) on OSPF instances.
|
|
15
|
+
names = {
|
|
16
|
+
ospf_instance_name("sw-a", "default", None),
|
|
17
|
+
ospf_instance_name("sw-a", "default", "BLUE"),
|
|
18
|
+
ospf_instance_name("sw-a", "default", "RED"),
|
|
19
|
+
}
|
|
20
|
+
self.assertEqual(len(names), 3)
|
|
21
|
+
|
|
22
|
+
def test_a_long_name_is_cut_in_the_base_never_in_the_vrf(self):
|
|
23
|
+
name = ospf_instance_name("d" * 120, "default", "BLUE")
|
|
24
|
+
self.assertEqual(len(name), 100)
|
|
25
|
+
self.assertTrue(name.endswith(" (BLUE)"))
|
|
26
|
+
other = ospf_instance_name("d" * 120, "default", "RED")
|
|
27
|
+
self.assertNotEqual(name, other)
|
|
@@ -152,6 +152,31 @@ class ResolveManagementIpAssignmentsTest(SimpleTestCase):
|
|
|
152
152
|
|
|
153
153
|
self.assertEqual(result, {})
|
|
154
154
|
|
|
155
|
+
def test_unresolved_devices_report_why(self):
|
|
156
|
+
reasons = {}
|
|
157
|
+
self._resolve(
|
|
158
|
+
{
|
|
159
|
+
"many": ["10.0.0.1", "10.0.0.2"],
|
|
160
|
+
"none": ["10.0.0.3"],
|
|
161
|
+
"two": ["10.0.0.4"],
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"many": {"Lo0": ["10.0.0.1/32"]},
|
|
165
|
+
"none": {"Lo0": ["10.9.9.9/32"]},
|
|
166
|
+
"two": {"Lo0": ["10.0.0.4/32"], "Vlan1": ["10.0.0.4/24"]},
|
|
167
|
+
},
|
|
168
|
+
reasons=reasons,
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
self.assertEqual(
|
|
172
|
+
reasons,
|
|
173
|
+
{
|
|
174
|
+
"many": "multiple-addresses",
|
|
175
|
+
"none": "no-interface",
|
|
176
|
+
"two": "several-interfaces",
|
|
177
|
+
},
|
|
178
|
+
)
|
|
179
|
+
|
|
155
180
|
def test_a_device_with_a_mgmt_tag_is_never_given_the_fallback(self):
|
|
156
181
|
result = self._resolve(
|
|
157
182
|
{"r1": ["10.0.0.1"]},
|
{forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_primary_ip_integration.py
RENAMED
|
@@ -214,6 +214,49 @@ class PrimaryIpFromMgmtTagIntegrationTest(TransactionTestCase):
|
|
|
214
214
|
|
|
215
215
|
executor.get_device_management_ips.assert_not_called()
|
|
216
216
|
|
|
217
|
+
def test_a_tag_that_resolves_nothing_still_gets_the_management_address(self):
|
|
218
|
+
# `Mgmt_Nope` names no interface, so the tag leaves the device bare. It
|
|
219
|
+
# used to block the fallback too, which left 590 tagged devices on one
|
|
220
|
+
# estate without a primary IP even though their management address sat
|
|
221
|
+
# on an interface.
|
|
222
|
+
self._enable(tag=True, fallback=True)
|
|
223
|
+
branch = provision_branch(user=self.user, name="Unresolved Tag Branch")
|
|
224
|
+
executor = self._fallback_executor(
|
|
225
|
+
mgmt_tags={"r1": ["Mgmt_Nope9"]},
|
|
226
|
+
management_ips={"r1": ["10.0.211.2"]},
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
updated = apply_primary_ip_from_mgmt_tags(
|
|
230
|
+
executor, branch, snapshot_id="snap-1"
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
self.assertEqual(updated, 1)
|
|
234
|
+
with activate_branch(branch):
|
|
235
|
+
self.assertEqual(
|
|
236
|
+
Device.objects.get(pk=self.device.pk).primary_ip4_id, self.ip.pk
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
def test_a_shared_management_address_is_recognised_as_shared(self):
|
|
240
|
+
from forward_netbox.utilities.primary_ip import (
|
|
241
|
+
_devices_sharing_management_address,
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
parent = Device.objects.create(
|
|
245
|
+
name="fw-parent",
|
|
246
|
+
site=self.device.site,
|
|
247
|
+
role=self.device.role,
|
|
248
|
+
device_type=self.device.device_type,
|
|
249
|
+
)
|
|
250
|
+
mgmt = Interface.objects.create(device=parent, name="mgmt", type="virtual")
|
|
251
|
+
IPAddress.objects.create(address="10.55.0.1/24", assigned_object=mgmt)
|
|
252
|
+
|
|
253
|
+
shared = _devices_sharing_management_address(
|
|
254
|
+
{"fw-vsys2": "no-interface", "r1": "no-interface"},
|
|
255
|
+
{"fw-vsys2": ["10.55.0.1"], "r1": ["10.66.0.1"]},
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
self.assertEqual(shared, {"fw-vsys2"})
|
|
259
|
+
|
|
217
260
|
def test_a_tagged_device_ignores_the_management_address(self):
|
|
218
261
|
other = Interface.objects.create(
|
|
219
262
|
device=self.device, name="Loopback9", type="virtual"
|
{forward_netbox-3.0.2 → forward_netbox-3.0.3}/forward_netbox/tests/test_runtime_dependency_check.py
RENAMED
|
@@ -23,7 +23,7 @@ class RuntimeDependencyCheckTest(SimpleTestCase):
|
|
|
23
23
|
self.assertIsNotNone(_resolved_branching_version())
|
|
24
24
|
|
|
25
25
|
def test_plugin_config_version_matches_package_release(self):
|
|
26
|
-
self.assertEqual(NetboxForwardConfig.version, "3.0.
|
|
26
|
+
self.assertEqual(NetboxForwardConfig.version, "3.0.3")
|
|
27
27
|
|
|
28
28
|
def test_exact_runtime_passes(self):
|
|
29
29
|
_check_runtime_dependencies()
|