cmdbsyncer 4.4.1__tar.gz → 4.4.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/PKG-INFO +1 -1
- cmdbsyncer-4.4.2/application/buildinfo.txt +1 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/changelog/v4.4.md +10 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/get_account.py +13 -8
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/models/account.py +16 -9
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/ansible/runner.py +14 -4
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/ansible/tests/test_runner_ssh_env.py +37 -1
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/cmk_rules.py +24 -15
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/dcd.py +5 -1
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/syncer.py +3 -1
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_cmk_rules.py +56 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_dcd.py +8 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_syncer.py +4 -3
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/cron.py +33 -3
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/netbox/dataflow.py +2 -1
- cmdbsyncer-4.4.2/application/plugins/netbox/tests/test_same_host_url.py +29 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/netbox/utils.py +13 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/cmdbsyncer.egg-info/PKG-INFO +1 -1
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/cmdbsyncer.egg-info/SOURCES.txt +3 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/pyproject.toml +1 -1
- cmdbsyncer-4.4.2/tests/test_account_master_cache_smoke.py +50 -0
- cmdbsyncer-4.4.2/tests/test_cron_stale_lock_smoke.py +57 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_security_fixes.py +23 -0
- cmdbsyncer-4.4.1/application/buildinfo.txt +0 -1
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/LICENSE +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/README.md +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/_version.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/api/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/api/inventory.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/api/objects.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/api/rules.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/api/syncer.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/api/views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/auth/views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/changelog/.pages +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/changelog/v3.10.md +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/changelog/v3.11.md +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/changelog/v3.12.md +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/changelog/v3.5.md +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/changelog/v3.7.md +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/changelog/v3.8.md +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/changelog/v3.9.md +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/changelog/v4.0.md +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/changelog/v4.1.md +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/changelog/v4.2.md +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/changelog/v4.3.md +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/cli.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/config.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/docu_links.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/enterprise.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/audit.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/cron.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/db_analysis.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/host_maintenance.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/import_hostnames.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/inventory.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/label_hash.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/label_history.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/local_config_file.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/local_config_presets.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/mongo_keys.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/notification_channels.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/notification_dispatch.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/plugins.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/retention.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/sates.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/sql.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/stale_indexes.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/syncer_jinja.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/tablib_formater.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/tests/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/tests/test_sql.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/helpers/timezone.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/mcp_server.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/models/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/models/config.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/models/cron.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/models/field_approval.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/models/forms.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/models/host.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/models/host_cleanup.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/models/host_create_time.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/models/host_inventory_tree.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/models/host_label_event.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/models/host_labels.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/models/host_templates.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/models/notification_channel.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/models/notification_rule.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/models/notification_state.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/models/project.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/models/saved_search.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/models/states.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/models/user.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/module_registry.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/custom_attributes/models.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/custom_attributes/rules.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/custom_attributes/views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/debug.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/email.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/inventory/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/log/command_output.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/log/log.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/log/models.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/log/views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/plugin.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/rule/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/rule/filter.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/rule/list_source.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/rule/list_source_views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/rule/match.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/rule/models.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/rule/rewrite.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/rule/rule.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/rule/views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/search_parser.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/modules/statefile.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/notices/strict_certificate_verification.txt +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/ansible/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/ansible/admin_views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/ansible/inventory.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/ansible/models.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/ansible/playbook_rules.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/ansible/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/ansible/rules.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/ansible/seed.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/ansible/site_syncer.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/ansible/tests/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/ansible/views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/bmc_remedy/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/bmc_remedy/bmc_remedy.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/bmc_remedy/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/admin_views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/bi.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/cmk2.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/data/ruleset_examples.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/data/rulesets_2.4.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/data/rulesets_2.5.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/data_quality.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/downtimes.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/folder_attributes.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/groups.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/helpers.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/import_v1.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/import_v2.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/inits.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/inventorize.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/list_source.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/models.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/notification_rules.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/passwords.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/poolfolder.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/rule_analysis_runner.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/rule_passwords.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/rules.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/rulesets_catalog.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/sitepool.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/sites.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tags.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_assign_template.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_bi.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_cmk2.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_cmk_conditions.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_data_quality.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_downtimes.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_groups.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_helpers.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_import_v1.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_import_v2.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_inventorize.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_list_source.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_notification_rules.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_passwords.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_poolfolder.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_rule_analysis_runner.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_rule_passwords.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_rules.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_sitepool.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_sites.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_tags.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_user_generation.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/tests/test_users.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/user_generation.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/user_models.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/users.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/checkmk/views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/cisco_dna/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/cisco_dna/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/cisco_dna/syncer.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/csv/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/csv/csv.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/csv/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/eda/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/eda/admin_views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/eda/models.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/eda/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/eda/repeats.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/eda/rules.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/eda/sender.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/eda/tests/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/eda/tests/test_eda.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/eda/tests/test_repeats.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/eda/views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/file_requests.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/idoit/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/idoit/admin_views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/idoit/models.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/idoit/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/idoit/rules.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/idoit/syncer.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/idoit/views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/jdisc/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/jdisc/applications.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/jdisc/devices.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/jdisc/executables.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/jdisc/jdisc.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/jdisc/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/jira/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/jira/jira.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/jira/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/jira_cloud/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/jira_cloud/admin_views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/jira_cloud/export.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/jira_cloud/jira_cloud.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/jira_cloud/models.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/jira_cloud/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/jira_cloud/rules.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/jira_cloud/schema_sync.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/jira_cloud/tests/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/jira_cloud/tests/test_attribute_value.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/jira_cloud/views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/json/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/json/json.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/json/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/ldap/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/ldap/admin_views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/ldap/ldap.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/ldap/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/ldap/views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/maintenance/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/maintenance/db_commands.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/maintenance/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/maintenance/tests/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/maintenance/tests/test_delete_all_hosts.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/maintenance/tests/test_delete_inventory.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/mssql/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/mssql/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/mysql/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/mysql/mysql.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/mysql/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/netbox/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/netbox/admin_views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/netbox/cluster.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/netbox/contacts.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/netbox/devices.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/netbox/interfaces.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/netbox/ips.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/netbox/models.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/netbox/netbox.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/netbox/networks.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/netbox/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/netbox/prefixes.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/netbox/rules.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/netbox/tests/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/netbox/tests/test_import_filter.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/netbox/views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/netbox/virtualmachines.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/prtg/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/prtg/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/prtg/prtg.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/pyodbc/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/pyodbc/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/pyodbc/pyodbc.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/rest/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/rest/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/rest/rest.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/rules/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/rules/admin_views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/rules/autorules.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/rules/models.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/rules/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/rules/rule_definitions.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/rules/rule_import_export.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/rules/views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/servicenow/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/servicenow/admin_views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/servicenow/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/servicenow/syncer.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/servicenow/tests/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/servicenow/tests/test_table_request.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/servicenow/views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/syncer_shell.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/vmware/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/vmware/admin_views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/vmware/custom_attributes.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/vmware/models.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/vmware/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/vmware/rules.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/vmware/views.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/vmware/vmware.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/yml/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/yml/plugin.json +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/yml/yml.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins_cli.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/static/cmdbsyncer_mark.png +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/static/css/cmdbsyncer.css +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/static/favicon.png +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/static/js/Sortable.min.js +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/static/js/main.js +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/static/logo_white.png +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/static/vendor/README.md +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/static/vendor/ansible.svg +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/static/vendor/checkmk.svg +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/static/vendor/idoit.svg +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/static/vendor/jira.svg +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/static/vendor/netbox.svg +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/static/vendor/vmware.svg +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/_brand.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/_theme.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/_timezone.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/_host_tabs.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/account_create.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/account_edit.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/account_field_help.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/account_pick_type.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/ansible_playbook_run.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/ansible_project_detail.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/ansible_rule_list.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/ansible_run_details.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/assign_project_form.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/bulk_label_form.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/changelog_archive.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/checkmk_data_quality.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/checkmk_list_rule_debug.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/checkmk_rule_mngmt_list.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/checkmk_rule_optimization.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/checkmk_settings_list.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/checkmk_test_folder_scope.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/checkmk_user_generation_preview.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/checkmk_user_generation_rule_list.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/copy_as_new_form.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/data_quality.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/data_quality_lowercase_preview.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/file/list.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/file/modals/form.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/first_steps.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/host_csv_import_preview.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/host_details.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/host_edit.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/host_inventory_tree.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/host_list.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/host_relations_graph.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/host_timeline.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/index.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/ldap_search.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/local_config_editor.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/master.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/model/_action_picker.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/model/_folder_builder.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/model/_list_source_preview.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/model/_notification_plugin_picker.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/model/_ruleset_autocomplete.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/model/checkmk_notification_rule_create.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/model/checkmk_notification_rule_edit.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/model/checkmk_rule_create.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/model/checkmk_rule_edit.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/model/checkmk_rule_mngmt_create.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/model/checkmk_rule_mngmt_edit.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/model/clone_confirm.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/model/inline_list_base.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/model/list_source_create.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/model/list_source_edit.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/module_overview.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/object_list.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/project_edit.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/project_import.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/project_import_cmk.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/project_list.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/project_overview.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/servicenow_query.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/set_account_form.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/set_cmk_version_form.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/admin/set_template_form.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/api_tokens.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/base.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/change_password.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/csrf_error.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/debug.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/debug_host.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/email/newuser.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/email/notification.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/email/resetpassword.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/formular.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/license_info.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/login.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/logout_confirm.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/request_password.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/set_2fa.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/templates/set_theme.html +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/themes/dracula.css +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/themes/gruvbox-dark.css +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/themes/gruvbox-light.css +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/themes/nord.css +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/themes_registry.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/_form_fields.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/_form_sections.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/account.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/account_select.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/config.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/cron.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/data_quality.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/default.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/field_approval.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/fileadmin.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/first_steps.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/host.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/host_filters.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/host_inventory_grid.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/host_renderers.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/host_widgets.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/license.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/menu_links.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/module_overview.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/notification_channel.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/notification_rule.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/project.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/saved_search.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/template_select.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/views/user.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/cmdbsyncer.egg-info/dependency_links.txt +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/cmdbsyncer.egg-info/entry_points.txt +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/cmdbsyncer.egg-info/requires.txt +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/cmdbsyncer.egg-info/top_level.txt +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/requirements-ansible-windows.txt +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/requirements-ansible.txt +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/requirements-extras.txt +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/requirements.txt +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/setup.cfg +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/syncerapi/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/syncerapi/v1/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/syncerapi/v1/core/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/syncerapi/v1/inventory/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/syncerapi/v1/rest/__init__.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_account_macro.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_active_templates.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_ansible_cmk_roles.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_ansible_inventory.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_api.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_api_csrf_invariant.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_config_dir.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_cron_missing_account.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_csrf_config.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_data_quality_duplicates.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_default_view.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_disabled_row_style.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_eda_web_smoke.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_enterprise_quiet.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_folder_builder_js.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_global_account_presets.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_host_cleanup.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_host_create_time.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_host_label_edit.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_host_roundtrip_smoke.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_host_template_filter.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_host_template_resync.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_import_hostnames.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_jinja_get_list.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_jinja_hash.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_label_history.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_ldap_search_filter.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_local_config_presets.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_logging_config.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_model_indexes.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_mongo_keys.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_plugin.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_plugin_ssti.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_plugins_cli.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_regex_condition_limits.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_rule.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_rule_export_templates.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_rule_filename_detect.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_rule_import_override.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_rule_list_rows.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_rule_list_source.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_rule_match.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_rule_registry_complete.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_search_parser.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_stale_indexes.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_template_merge_fields.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_timezone.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_user_scope_smoke.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_view_permission_flags.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_web_account_password_chars.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_web_account_password_deferred_save.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_web_ansible_account_inventory.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_web_boot_smoke.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_web_debug_pages.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_web_list_source.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_web_requests_smoke.py +0 -0
- {cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/tests/test_webhook_token_hash.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cmdbsyncer
|
|
3
|
-
Version: 4.4.
|
|
3
|
+
Version: 4.4.2
|
|
4
4
|
Summary: Rule-based modular synchronizer for Checkmk, Netbox, Ansible, I-DOIT, Jira CMDB and 15+ other CMDB/monitoring systems
|
|
5
5
|
Author-email: Kuhn & Ruess GmbH <info@kuhn-ruess.de>
|
|
6
6
|
Maintainer-email: Bastian Kuhn <mail@bastian-kuhn.de>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
BUILD_DATE=2026-11-10T09:35:59Z
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Version 4.4
|
|
2
2
|
|
|
3
|
+
## Version 4.4.2
|
|
4
|
+
- SEC: Netbox Dataflow: the API token only goes to the address of the account; a page link of the answer pointing to another host no longer gets it
|
|
5
|
+
- FIX: Cron Groups: after a restart of the container a group no longer stays marked as running, when another process got the number of its old run
|
|
6
|
+
- FIX: Accounts: a change, like the master flag, reaches every process of the web interface and REST API within a minute; before, some kept the old account until a restart
|
|
7
|
+
- FIX: Checkmk: a host export with --limit creates a host that a rule turns into a cluster right away; before, the host was deleted and only came back as cluster with the next full run
|
|
8
|
+
- FIX: Checkmk DCD Rules: Restrict Source Hosts renders Jinja like the other fields, e.g. {{ HOSTNAME }}; a line that renders empty is left out
|
|
9
|
+
- FIX: Checkmk: rule export: a rule with a stored password, for example Kubernetes on Checkmk 2.5, is no longer updated on every run
|
|
10
|
+
- FIX: Ansible: playbooks started from the web interface find ansible-playbook in the Syncer's venv, also when the web server runs under systemd without the venv on its PATH
|
|
11
|
+
- FIX: Checkmk: Manage OMD Server creates a missing site again, including the initial cmkadmin password, instead of failing on the update step
|
|
12
|
+
|
|
3
13
|
## Version 4.4.1
|
|
4
14
|
- FIX: REST import: entries without the hostname field are skipped instead of aborting the whole import
|
|
5
15
|
- FIX: Checkmk users: an empty row under Roles or Contact Groups is no longer sent to Checkmk, which rejected the user because of it
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Helper to get Account
|
|
3
3
|
"""
|
|
4
4
|
import copy
|
|
5
|
+
import time
|
|
5
6
|
from contextlib import contextmanager
|
|
6
7
|
from contextvars import ContextVar
|
|
7
8
|
|
|
@@ -67,11 +68,13 @@ _CHILD_OWNED_FIELDS = ('typ', 'username', 'password', 'address', 'object_type')
|
|
|
67
68
|
# Internal serialisation artefacts that never leave this layer.
|
|
68
69
|
_INTERNAL_FIELDS = ('custom_fields', 'password_crypted', 'plugin_settings')
|
|
69
70
|
|
|
70
|
-
# In-process cache: ``{(lookup_key, is_id): account_dict}``.
|
|
71
|
-
# the same handful of accounts for every host/rule, so
|
|
72
|
-
# and the secrets-manager hook off the hot path.
|
|
73
|
-
# save/delete
|
|
74
|
-
#
|
|
71
|
+
# In-process cache: ``{(lookup_key, is_id): (loaded_at, account_dict)}``.
|
|
72
|
+
# Sync runs read the same handful of accounts for every host/rule, so
|
|
73
|
+
# caching keeps Mongo and the secrets-manager hook off the hot path.
|
|
74
|
+
# Account save/delete clears it through mongoengine signals, but only in
|
|
75
|
+
# the process that saved; the other web workers read the account again
|
|
76
|
+
# after ACCOUNT_CACHE_SECONDS.
|
|
77
|
+
ACCOUNT_CACHE_SECONDS = 60
|
|
75
78
|
_account_cache = {}
|
|
76
79
|
|
|
77
80
|
|
|
@@ -177,10 +180,12 @@ def get_account_by_name(name, is_id=False):
|
|
|
177
180
|
Get Account by Name or Return False
|
|
178
181
|
"""
|
|
179
182
|
cache_key = (str(name), is_id)
|
|
180
|
-
|
|
181
|
-
if
|
|
183
|
+
entry = _account_cache.get(cache_key)
|
|
184
|
+
if entry and time.monotonic() - entry[0] < ACCOUNT_CACHE_SECONDS:
|
|
185
|
+
cached = entry[1]
|
|
186
|
+
else:
|
|
182
187
|
cached = _build_account_dict(name, is_id)
|
|
183
|
-
_account_cache[cache_key] = cached
|
|
188
|
+
_account_cache[cache_key] = (time.monotonic(), cached)
|
|
184
189
|
# Defensive copy — callers must not mutate the cached entry.
|
|
185
190
|
return copy.deepcopy(cached)
|
|
186
191
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Account
|
|
3
3
|
"""
|
|
4
|
+
import time
|
|
5
|
+
|
|
4
6
|
from bson.errors import InvalidId
|
|
5
7
|
from mongoengine import DENY
|
|
6
8
|
from mongoengine.errors import ValidationError
|
|
@@ -230,6 +232,7 @@ class Account(db.Document):
|
|
|
230
232
|
return f"{self.name} ({self.typ})"
|
|
231
233
|
|
|
232
234
|
|
|
235
|
+
IS_MASTER_CACHE_SECONDS = 60
|
|
233
236
|
_IS_MASTER_CACHE = {}
|
|
234
237
|
|
|
235
238
|
# Hosts an import had to leave alone because a master account owns them.
|
|
@@ -273,13 +276,17 @@ def account_is_master(account_id):
|
|
|
273
276
|
Whether the account with *account_id* is flagged as master.
|
|
274
277
|
|
|
275
278
|
An import asks this once per host it does not own, so the answer is
|
|
276
|
-
cached for
|
|
277
|
-
(
|
|
279
|
+
cached for IS_MASTER_CACHE_SECONDS; a change of the flag reaches a
|
|
280
|
+
running process (web workers) within that time. Unknown or malformed
|
|
281
|
+
ids (legacy data) count as "not master".
|
|
278
282
|
"""
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
283
|
+
entry = _IS_MASTER_CACHE.get(account_id)
|
|
284
|
+
if entry and time.monotonic() - entry[0] < IS_MASTER_CACHE_SECONDS:
|
|
285
|
+
return entry[1]
|
|
286
|
+
try:
|
|
287
|
+
account = Account.objects(id=account_id).only('is_master').first()
|
|
288
|
+
except (ValidationError, InvalidId):
|
|
289
|
+
account = None
|
|
290
|
+
is_master = bool(account and account.is_master)
|
|
291
|
+
_IS_MASTER_CACHE[account_id] = (time.monotonic(), is_master)
|
|
292
|
+
return is_master
|
|
@@ -57,10 +57,20 @@ def _ansible_dir() -> Path:
|
|
|
57
57
|
|
|
58
58
|
|
|
59
59
|
def _ansible_binary() -> str:
|
|
60
|
-
"""
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
"""
|
|
61
|
+
Path to `ansible-playbook`: explicit config / env override, then the one
|
|
62
|
+
in the running interpreter's venv, then $PATH. The venv comes first for
|
|
63
|
+
the same reason as in `_cmdbsyncer_bin` — a gunicorn worker under
|
|
64
|
+
systemd runs with a PATH that omits the venv's bin dir.
|
|
65
|
+
"""
|
|
66
|
+
override = app.config.get('ANSIBLE_PLAYBOOK_BIN') \
|
|
67
|
+
or os.environ.get('CMDBSYNCER_ANSIBLE_PLAYBOOK_BIN')
|
|
68
|
+
if override:
|
|
69
|
+
return override
|
|
70
|
+
venv_bin = Path(sys.prefix) / 'bin' / 'ansible-playbook'
|
|
71
|
+
if venv_bin.is_file():
|
|
72
|
+
return str(venv_bin)
|
|
73
|
+
return 'ansible-playbook'
|
|
64
74
|
|
|
65
75
|
|
|
66
76
|
def _inventory_plugin_dir() -> str | None:
|
{cmdbsyncer-4.4.1 → cmdbsyncer-4.4.2}/application/plugins/ansible/tests/test_runner_ssh_env.py
RENAMED
|
@@ -3,10 +3,12 @@ The playbook runner has to work under a web user without a writable home.
|
|
|
3
3
|
"""
|
|
4
4
|
# pylint: disable=missing-function-docstring,missing-class-docstring,protected-access
|
|
5
5
|
import os
|
|
6
|
+
import shutil
|
|
6
7
|
import sys
|
|
8
|
+
import tempfile
|
|
7
9
|
import unittest
|
|
8
10
|
from types import ModuleType
|
|
9
|
-
from unittest.mock import MagicMock
|
|
11
|
+
from unittest.mock import MagicMock, patch
|
|
10
12
|
|
|
11
13
|
from tests import _load_real_module
|
|
12
14
|
|
|
@@ -56,6 +58,40 @@ class SshEnvTest(unittest.TestCase):
|
|
|
56
58
|
args.index('/tmp/run-2/known_hosts'))
|
|
57
59
|
|
|
58
60
|
|
|
61
|
+
class AnsibleBinaryTest(unittest.TestCase):
|
|
62
|
+
"""
|
|
63
|
+
Under systemd the venv's bin dir is not on PATH, so the runner has to
|
|
64
|
+
find ansible-playbook next to the running interpreter.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
@classmethod
|
|
68
|
+
def setUpClass(cls):
|
|
69
|
+
cls.runner = _load_runner()
|
|
70
|
+
|
|
71
|
+
def setUp(self):
|
|
72
|
+
self.prefix = tempfile.mkdtemp()
|
|
73
|
+
self.addCleanup(shutil.rmtree, self.prefix)
|
|
74
|
+
patcher = patch.object(self.runner.sys, 'prefix', self.prefix)
|
|
75
|
+
patcher.start()
|
|
76
|
+
self.addCleanup(patcher.stop)
|
|
77
|
+
self.runner.app.config.pop('ANSIBLE_PLAYBOOK_BIN', None)
|
|
78
|
+
|
|
79
|
+
def test_the_venv_binary_is_used(self):
|
|
80
|
+
os.mkdir(os.path.join(self.prefix, 'bin'))
|
|
81
|
+
binary = os.path.join(self.prefix, 'bin', 'ansible-playbook')
|
|
82
|
+
with open(binary, 'w', encoding='utf-8'):
|
|
83
|
+
pass
|
|
84
|
+
self.assertEqual(self.runner._ansible_binary(), binary)
|
|
85
|
+
|
|
86
|
+
def test_without_venv_binary_path_decides(self):
|
|
87
|
+
self.assertEqual(self.runner._ansible_binary(), 'ansible-playbook')
|
|
88
|
+
|
|
89
|
+
def test_the_config_wins(self):
|
|
90
|
+
self.runner.app.config['ANSIBLE_PLAYBOOK_BIN'] = '/usr/bin/ansible-playbook'
|
|
91
|
+
self.addCleanup(self.runner.app.config.pop, 'ANSIBLE_PLAYBOOK_BIN', None)
|
|
92
|
+
self.assertEqual(self.runner._ansible_binary(), '/usr/bin/ansible-playbook')
|
|
93
|
+
|
|
94
|
+
|
|
59
95
|
class ConnectionHintTest(unittest.TestCase):
|
|
60
96
|
"""
|
|
61
97
|
sshpass calls a non-writable home a wrong password. The log must not
|
|
@@ -36,6 +36,9 @@ KEEP_VALUE_HINT = "Value managed manually in Checkmk - Syncer will not overwrite
|
|
|
36
36
|
KEEP_VALUE_MARK = "(Value editable)"
|
|
37
37
|
# Checkmk returns every explicit password of a rule value masked like this.
|
|
38
38
|
MASKED_PASSWORD = "'******'"
|
|
39
|
+
# Checkmk 2.5 masks the second part of a stored password reference too. It
|
|
40
|
+
# holds no secret: the rule works with it left empty.
|
|
41
|
+
MASKED_STORED_PASSWORD = re.compile(r"('stored_password', \('[^']*', )'\*{6}'")
|
|
39
42
|
|
|
40
43
|
# Longest Setup Rule name written into the Checkmk rule description. Long
|
|
41
44
|
# enough for real rule names, short enough to keep the rule list readable.
|
|
@@ -843,7 +846,7 @@ def preview_list_rule(rule):
|
|
|
843
846
|
|
|
844
847
|
def clean_postproccessed(data):
|
|
845
848
|
"""
|
|
846
|
-
Normalize Checkmk's
|
|
849
|
+
Normalize Checkmk's password tuples, at any depth, before rule comparison.
|
|
847
850
|
"""
|
|
848
851
|
# Intentional: Checkmk re-encrypts the stored explicit_password tuple
|
|
849
852
|
# (id, password) on every GET, so the ciphertext differs across reads
|
|
@@ -852,16 +855,20 @@ def clean_postproccessed(data):
|
|
|
852
855
|
# on every sync. The trade-off — that a real password change is not
|
|
853
856
|
# detected here — is accepted; password rotation is managed by the
|
|
854
857
|
# Checkmk password store, not by rule diffs.
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
858
|
+
# A stored_password only references the store: Checkmk 2.5 returns its
|
|
859
|
+
# second part masked, so only the ident is compared.
|
|
860
|
+
if isinstance(data, dict):
|
|
861
|
+
return {key: clean_postproccessed(value) for key, value in data.items()}
|
|
862
|
+
if isinstance(data, list):
|
|
863
|
+
return [clean_postproccessed(value) for value in data]
|
|
864
|
+
if not isinstance(data, tuple):
|
|
865
|
+
return data
|
|
866
|
+
if len(data) == 3 and data[0] == 'cmk_postprocessed':
|
|
867
|
+
if data[1] == 'explicit_password':
|
|
868
|
+
return (data[0], data[1], (None, None))
|
|
869
|
+
if data[1] == 'stored_password':
|
|
870
|
+
return (data[0], data[1], (data[2][0], ''))
|
|
871
|
+
return tuple(clean_postproccessed(value) for value in data)
|
|
865
872
|
|
|
866
873
|
def deep_compare(ours, stored, strict=False):
|
|
867
874
|
"""
|
|
@@ -883,9 +890,9 @@ def deep_compare(ours, stored, strict=False):
|
|
|
883
890
|
Nested dicts inside lists are still compared structurally via each
|
|
884
891
|
element's ``==``.
|
|
885
892
|
"""
|
|
893
|
+
ours = clean_postproccessed(ours)
|
|
894
|
+
stored = clean_postproccessed(stored)
|
|
886
895
|
if isinstance(ours, dict) and isinstance(stored, dict):
|
|
887
|
-
ours = clean_postproccessed(ours)
|
|
888
|
-
stored = clean_postproccessed(stored)
|
|
889
896
|
if strict:
|
|
890
897
|
if set(ours.keys()) != set(stored.keys()):
|
|
891
898
|
return False
|
|
@@ -2694,7 +2701,9 @@ class CheckmkRuleSync(CMK2): # pylint: disable=too-many-instance-attributes
|
|
|
2694
2701
|
current = properties.get('description', '')
|
|
2695
2702
|
if current == wanted:
|
|
2696
2703
|
return
|
|
2697
|
-
|
|
2704
|
+
value_raw = MASKED_STORED_PASSWORD.sub(
|
|
2705
|
+
r"\1''", cmk_rule['extensions']['value_raw'])
|
|
2706
|
+
if MASKED_PASSWORD in value_raw:
|
|
2698
2707
|
# The value as read holds the password masked. Sending it back
|
|
2699
2708
|
# would replace the real password with the mask, so the
|
|
2700
2709
|
# description stays as it is.
|
|
@@ -2704,7 +2713,7 @@ class CheckmkRuleSync(CMK2): # pylint: disable=too-many-instance-attributes
|
|
|
2704
2713
|
payload = {
|
|
2705
2714
|
"properties": properties,
|
|
2706
2715
|
"conditions": cmk_rule['extensions']['conditions'],
|
|
2707
|
-
"value_raw":
|
|
2716
|
+
"value_raw": value_raw,
|
|
2708
2717
|
}
|
|
2709
2718
|
if self.dry_run:
|
|
2710
2719
|
self._plan('UPDATE', f"{ruleset_name} {rule_id}",
|
|
@@ -128,7 +128,11 @@ class CheckmkDCDRuleSync(CMK2):
|
|
|
128
128
|
Return Payload as Dict
|
|
129
129
|
"""
|
|
130
130
|
try:
|
|
131
|
-
|
|
131
|
+
# A line rendering empty (an attribute the host lacks) is left out.
|
|
132
|
+
restricted_hosts = [
|
|
133
|
+
host for host in (render_jinja(entry, mode='raise', **attributes).strip()
|
|
134
|
+
for entry in rule['restricted_source_hosts'])
|
|
135
|
+
if host]
|
|
132
136
|
creation_rules = self.build_creation_rules(rule, attributes)
|
|
133
137
|
exclude_time_ranges = self.build_timeranges(rule)
|
|
134
138
|
|
|
@@ -1201,6 +1201,9 @@ class SyncCMK2(CMK2):
|
|
|
1201
1201
|
# skipping it left every already-existing folder unchanged whenever a
|
|
1202
1202
|
# run was limited to single hosts (the usual way to test folder rules).
|
|
1203
1203
|
self.handle_folders()
|
|
1204
|
+
# Clusters only hold hosts of this run. A host that turned into a
|
|
1205
|
+
# cluster was already deleted above and has to come back now.
|
|
1206
|
+
self.handle_clusters()
|
|
1204
1207
|
|
|
1205
1208
|
if self.limit:
|
|
1206
1209
|
log.log(f"Finished Sync to Checkmk Account: {self.account_name} because LIMIT",
|
|
@@ -1208,7 +1211,6 @@ class SyncCMK2(CMK2):
|
|
|
1208
1211
|
print(f"\n{CC.OKCYAN} -- {CC.ENDC}Stop processing in limit mode")
|
|
1209
1212
|
return
|
|
1210
1213
|
|
|
1211
|
-
self.handle_clusters()
|
|
1212
1214
|
self.cleanup_hosts()
|
|
1213
1215
|
|
|
1214
1216
|
|
|
@@ -75,6 +75,11 @@ class TestCleanPostprocessed(unittest.TestCase):
|
|
|
75
75
|
}
|
|
76
76
|
self.assertEqual(result, expected)
|
|
77
77
|
|
|
78
|
+
def test_stored_password_keeps_ident_only(self):
|
|
79
|
+
data = {'token': ('cmk_postprocessed', 'stored_password', ('id', '******'))}
|
|
80
|
+
expected = {'token': ('cmk_postprocessed', 'stored_password', ('id', ''))}
|
|
81
|
+
self.assertEqual(clean_postproccessed(data), expected)
|
|
82
|
+
|
|
78
83
|
def test_non_password_tuple_unchanged(self):
|
|
79
84
|
data = {'other': ('something', 'else', 'data')}
|
|
80
85
|
result = clean_postproccessed(data)
|
|
@@ -152,6 +157,31 @@ class TestDeepCompare(unittest.TestCase):
|
|
|
152
157
|
b = {'password': ('cmk_postprocessed', 'explicit_password', ('id2', 'pw2'))}
|
|
153
158
|
self.assertTrue(deep_compare(a, b))
|
|
154
159
|
|
|
160
|
+
def test_masked_stored_password_is_no_drift(self):
|
|
161
|
+
# Sent with an empty second part, Checkmk 2.5 returns it masked.
|
|
162
|
+
ours = {'token': ('cmk_postprocessed', 'stored_password', ('pw1', ''))}
|
|
163
|
+
stored = {'token': ('cmk_postprocessed', 'stored_password', ('pw1', '******'))}
|
|
164
|
+
self.assertTrue(deep_compare(ours, stored))
|
|
165
|
+
self.assertTrue(deep_compare(ours, stored, strict=True))
|
|
166
|
+
|
|
167
|
+
def test_other_stored_password_is_drift(self):
|
|
168
|
+
ours = {'token': ('cmk_postprocessed', 'stored_password', ('pw1', ''))}
|
|
169
|
+
stored = {'token': ('cmk_postprocessed', 'stored_password', ('pw2', '******'))}
|
|
170
|
+
self.assertFalse(deep_compare(ours, stored))
|
|
171
|
+
|
|
172
|
+
def test_nested_stored_password_is_no_drift(self):
|
|
173
|
+
def value(secret):
|
|
174
|
+
password = ('cmk_postprocessed', 'stored_password', ('pw1', secret))
|
|
175
|
+
return {'auth': ('user_auth', {'password': password}),
|
|
176
|
+
'endpoints': [{'password': password}]}
|
|
177
|
+
self.assertTrue(deep_compare(value(''), value('******')))
|
|
178
|
+
|
|
179
|
+
def test_nested_explicit_password_is_no_drift(self):
|
|
180
|
+
def value(ident):
|
|
181
|
+
password = ('cmk_postprocessed', 'explicit_password', (ident, '******'))
|
|
182
|
+
return {'auth': ('user_auth', {'password': password})}
|
|
183
|
+
self.assertTrue(deep_compare(value('a'), value('b')))
|
|
184
|
+
|
|
155
185
|
|
|
156
186
|
class TestAnalyzeValueDifferences(unittest.TestCase):
|
|
157
187
|
"""Tests for analyze_value_differences"""
|
|
@@ -3296,6 +3326,32 @@ class TestSyncDescription(unittest.TestCase):
|
|
|
3296
3326
|
self.assertEqual(data['value_raw'], "{'levels': (99, 99)}")
|
|
3297
3327
|
self.assertEqual(data['properties']['comment'], 'c')
|
|
3298
3328
|
|
|
3329
|
+
def test_stale_description_with_stored_password_is_rewritten(self):
|
|
3330
|
+
puts = self._wire()
|
|
3331
|
+
cmk_rule = self._cmk_rule('cmdbsyncer_test_account')
|
|
3332
|
+
cmk_rule['extensions']['value_raw'] = (
|
|
3333
|
+
"{'token': ('cmk_postprocessed', 'stored_password', ('pw1', '******'))}")
|
|
3334
|
+
local = {'description': 'cmdbsyncer_test_account - Kube'}
|
|
3335
|
+
|
|
3336
|
+
self.sync._sync_description(cmk_rule, local, 'a_ruleset')
|
|
3337
|
+
|
|
3338
|
+
self.assertEqual(len(puts), 1)
|
|
3339
|
+
self.assertEqual(
|
|
3340
|
+
puts[0][2]['value_raw'],
|
|
3341
|
+
"{'token': ('cmk_postprocessed', 'stored_password', ('pw1', ''))}")
|
|
3342
|
+
|
|
3343
|
+
def test_stale_description_with_explicit_password_writes_nothing(self):
|
|
3344
|
+
puts = self._wire()
|
|
3345
|
+
cmk_rule = self._cmk_rule('cmdbsyncer_test_account')
|
|
3346
|
+
cmk_rule['extensions']['value_raw'] = (
|
|
3347
|
+
"{'stored': ('cmk_postprocessed', 'stored_password', ('pw1', '******')), "
|
|
3348
|
+
"'token': ('cmk_postprocessed', 'explicit_password', ('id', '******'))}")
|
|
3349
|
+
local = {'description': 'cmdbsyncer_test_account - Kube'}
|
|
3350
|
+
|
|
3351
|
+
self.sync._sync_description(cmk_rule, local, 'a_ruleset')
|
|
3352
|
+
|
|
3353
|
+
self.assertEqual(puts, [])
|
|
3354
|
+
|
|
3299
3355
|
def test_matching_description_writes_nothing(self):
|
|
3300
3356
|
puts = self._wire()
|
|
3301
3357
|
cmk_rule = self._cmk_rule('cmdbsyncer_test_account - Disk Levels')
|
|
@@ -380,6 +380,14 @@ class TestDCDListRule(unittest.TestCase):
|
|
|
380
380
|
self.assertTrue(any('dc1 not created' in str(detail)
|
|
381
381
|
for detail in self.sync.log_details))
|
|
382
382
|
|
|
383
|
+
def test_restrict_source_hosts_are_rendered(self, _render):
|
|
384
|
+
self.sync.static_rules = [_dcd_rule(
|
|
385
|
+
"id;host\ndc1;srv01\n",
|
|
386
|
+
restricted_source_hosts=['{{ host }}', '{{ missing | default("") }}'])]
|
|
387
|
+
self.sync.calculate_static_rules({'cmk_site': 'site_a', 'account': {}})
|
|
388
|
+
self.assertEqual(
|
|
389
|
+
self.sync.all_rules[0]['connector']['restrict_source_hosts'], ['srv01'])
|
|
390
|
+
|
|
383
391
|
|
|
384
392
|
if __name__ == '__main__':
|
|
385
393
|
unittest.main(verbosity=2)
|
|
@@ -963,10 +963,11 @@ class TestSyncCMK2(unittest.TestCase):
|
|
|
963
963
|
|
|
964
964
|
self.syncer.run()
|
|
965
965
|
|
|
966
|
-
# Folders applied for the processed hosts
|
|
966
|
+
# Folders and clusters applied for the processed hosts, a host
|
|
967
|
+
# turned cluster was deleted and has to come back ...
|
|
967
968
|
mock_folders.assert_called_once()
|
|
968
|
-
|
|
969
|
-
|
|
969
|
+
mock_clusters.assert_called_once()
|
|
970
|
+
# ... but the cleanup is skipped in limit mode.
|
|
970
971
|
mock_cleanup.assert_not_called()
|
|
971
972
|
|
|
972
973
|
|
|
@@ -35,20 +35,50 @@ def _pid_alive(pid):
|
|
|
35
35
|
return True
|
|
36
36
|
|
|
37
37
|
|
|
38
|
+
def _process_start(pid):
|
|
39
|
+
"""
|
|
40
|
+
Local start time of the process ``pid``, from /proc. None where /proc
|
|
41
|
+
is missing (not Linux) or the process is gone.
|
|
42
|
+
"""
|
|
43
|
+
try:
|
|
44
|
+
with open(f"/proc/{int(pid)}/stat", encoding="ascii") as handle:
|
|
45
|
+
# The name in brackets may hold spaces, the fields after it don't
|
|
46
|
+
ticks = int(handle.read().rsplit(")", 1)[1].split()[19])
|
|
47
|
+
with open("/proc/stat", encoding="ascii") as handle:
|
|
48
|
+
boot = next(int(line.split()[1]) for line in handle
|
|
49
|
+
if line.startswith("btime "))
|
|
50
|
+
return datetime.fromtimestamp(boot + ticks / os.sysconf("SC_CLK_TCK"))
|
|
51
|
+
except (OSError, ValueError, IndexError, StopIteration):
|
|
52
|
+
return None
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _pid_reused(stats):
|
|
56
|
+
"""
|
|
57
|
+
Whether the PID of the lock now belongs to a process that started after
|
|
58
|
+
the run, as after a container restart, where PIDs count up from 1 again.
|
|
59
|
+
The runner itself starts before it writes last_start.
|
|
60
|
+
"""
|
|
61
|
+
if not stats.last_start:
|
|
62
|
+
return False
|
|
63
|
+
started = _process_start(stats.pid)
|
|
64
|
+
return started is not None and started > stats.last_start + timedelta(seconds=2)
|
|
65
|
+
|
|
66
|
+
|
|
38
67
|
def _reset_stale_lock(stats):
|
|
39
68
|
"""
|
|
40
69
|
A previous run crashed (OOM, kill -9, container restart) before it could
|
|
41
70
|
release `is_running`. Reset the lock when the recorded PID no longer
|
|
42
|
-
exists on this host (the runner is always local)
|
|
71
|
+
exists on this host (the runner is always local), or belongs to a
|
|
72
|
+
process started after the run.
|
|
43
73
|
"""
|
|
44
74
|
if not stats.is_running:
|
|
45
75
|
return
|
|
46
|
-
if _pid_alive(stats.pid):
|
|
76
|
+
if _pid_alive(stats.pid) and not _pid_reused(stats):
|
|
47
77
|
return
|
|
48
78
|
stats.is_running = False
|
|
49
79
|
stats.failure = True
|
|
50
80
|
message = (f"{datetime.now()}: Stale lock cleared "
|
|
51
|
-
f"(pid {stats.pid} no longer running)")
|
|
81
|
+
f"(pid {stats.pid} no longer running the group)")
|
|
52
82
|
stats.last_message = message
|
|
53
83
|
stats.all_messages = f"{stats.all_messages or ''}{message}\n"
|
|
54
84
|
stats.last_ended = datetime.now()
|
|
@@ -9,6 +9,7 @@ from application.models.host import Host
|
|
|
9
9
|
|
|
10
10
|
from .netbox import SyncNetbox
|
|
11
11
|
from .models import NetboxDataflowModels
|
|
12
|
+
from .utils import same_host_url
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class DictObj: # pylint: disable=too-few-public-methods
|
|
@@ -160,7 +161,7 @@ class SyncDataFlow(SyncNetbox):
|
|
|
160
161
|
resp_data = resp.json()
|
|
161
162
|
result_collection += resp_data['results']
|
|
162
163
|
while resp_data.get('next'):
|
|
163
|
-
next_url = resp_data['next']
|
|
164
|
+
next_url = same_host_url(resp_data['next'], self.config['address'])
|
|
164
165
|
resp = self.inner_request("GET", next_url, headers=self.headers)
|
|
165
166
|
resp_data = resp.json()
|
|
166
167
|
result_collection += resp_data['results']
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The page link of a Netbox answer carries the token on the next request,
|
|
3
|
+
so it is pinned to the host of the account.
|
|
4
|
+
"""
|
|
5
|
+
# pylint: disable=missing-function-docstring
|
|
6
|
+
import unittest
|
|
7
|
+
|
|
8
|
+
from application.plugins.netbox.utils import same_host_url
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TestSameHostUrl(unittest.TestCase):
|
|
12
|
+
"""Page links of the Dataflow sync."""
|
|
13
|
+
|
|
14
|
+
def test_link_to_another_host_stays_on_the_account(self):
|
|
15
|
+
self.assertEqual(
|
|
16
|
+
same_host_url('https://evil.example/api/plugins/data-flows/x/?limit=50&offset=50',
|
|
17
|
+
'https://netbox.example.com'),
|
|
18
|
+
'https://netbox.example.com/api/plugins/data-flows/x/?limit=50&offset=50')
|
|
19
|
+
|
|
20
|
+
def test_link_of_the_own_host_is_kept(self):
|
|
21
|
+
url = 'https://netbox.example.com:8443/api/plugins/data-flows/x/?offset=50'
|
|
22
|
+
self.assertEqual(same_host_url(url, 'https://netbox.example.com:8443'), url)
|
|
23
|
+
|
|
24
|
+
def test_scheme_follows_the_account(self):
|
|
25
|
+
# Behind a TLS proxy Netbox may answer with http links
|
|
26
|
+
self.assertEqual(
|
|
27
|
+
same_host_url('http://netbox.example.com/api/x/?offset=50',
|
|
28
|
+
'https://netbox.example.com'),
|
|
29
|
+
'https://netbox.example.com/api/x/?offset=50')
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Shared helpers for the Netbox plugin.
|
|
3
3
|
"""
|
|
4
4
|
from collections import defaultdict
|
|
5
|
+
from urllib.parse import urlsplit, urlunsplit
|
|
6
|
+
|
|
5
7
|
from rich.progress import Progress, SpinnerColumn, TimeElapsedColumn, MofNCompleteColumn
|
|
6
8
|
|
|
7
9
|
|
|
@@ -29,3 +31,14 @@ def parse_import_filter(import_filter):
|
|
|
29
31
|
parsed_filter[key].append(value)
|
|
30
32
|
return {key: values if len(values) > 1 else values[0]
|
|
31
33
|
for key, values in parsed_filter.items()}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def same_host_url(url, address):
|
|
37
|
+
"""
|
|
38
|
+
The page link of an answer, with scheme and host of the account.
|
|
39
|
+
The link comes from the server and carries the token on the next
|
|
40
|
+
request, so it must not lead to another host.
|
|
41
|
+
"""
|
|
42
|
+
page = urlsplit(url)
|
|
43
|
+
base = urlsplit(address)
|
|
44
|
+
return urlunsplit((base.scheme, base.netloc, page.path, page.query, ''))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cmdbsyncer
|
|
3
|
-
Version: 4.4.
|
|
3
|
+
Version: 4.4.2
|
|
4
4
|
Summary: Rule-based modular synchronizer for Checkmk, Netbox, Ansible, I-DOIT, Jira CMDB and 15+ other CMDB/monitoring systems
|
|
5
5
|
Author-email: Kuhn & Ruess GmbH <info@kuhn-ruess.de>
|
|
6
6
|
Maintainer-email: Bastian Kuhn <mail@bastian-kuhn.de>
|
|
@@ -270,6 +270,7 @@ application/plugins/netbox/views.py
|
|
|
270
270
|
application/plugins/netbox/virtualmachines.py
|
|
271
271
|
application/plugins/netbox/tests/__init__.py
|
|
272
272
|
application/plugins/netbox/tests/test_import_filter.py
|
|
273
|
+
application/plugins/netbox/tests/test_same_host_url.py
|
|
273
274
|
application/plugins/prtg/__init__.py
|
|
274
275
|
application/plugins/prtg/plugin.json
|
|
275
276
|
application/plugins/prtg/prtg.py
|
|
@@ -441,6 +442,7 @@ syncerapi/v1/core/__init__.py
|
|
|
441
442
|
syncerapi/v1/inventory/__init__.py
|
|
442
443
|
syncerapi/v1/rest/__init__.py
|
|
443
444
|
tests/test_account_macro.py
|
|
445
|
+
tests/test_account_master_cache_smoke.py
|
|
444
446
|
tests/test_active_templates.py
|
|
445
447
|
tests/test_ansible_cmk_roles.py
|
|
446
448
|
tests/test_ansible_inventory.py
|
|
@@ -448,6 +450,7 @@ tests/test_api.py
|
|
|
448
450
|
tests/test_api_csrf_invariant.py
|
|
449
451
|
tests/test_config_dir.py
|
|
450
452
|
tests/test_cron_missing_account.py
|
|
453
|
+
tests/test_cron_stale_lock_smoke.py
|
|
451
454
|
tests/test_csrf_config.py
|
|
452
455
|
tests/test_data_quality_duplicates.py
|
|
453
456
|
tests/test_default_view.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "cmdbsyncer"
|
|
7
|
-
version = "4.4.
|
|
7
|
+
version = "4.4.2"
|
|
8
8
|
description = "Rule-based modular synchronizer for Checkmk, Netbox, Ansible, I-DOIT, Jira CMDB and 15+ other CMDB/monitoring systems"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""
|
|
2
|
+
A change of the master flag reaches a running process within the cache time.
|
|
3
|
+
|
|
4
|
+
The save signal only clears the caches of the process that saved, the
|
|
5
|
+
other web workers learn about it when their entry runs out. Saving in
|
|
6
|
+
another process is simulated by a direct database update, which sends no
|
|
7
|
+
signal. See ``tests/web_smoke_helpers.py`` for why this needs a subprocess.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import unittest
|
|
11
|
+
|
|
12
|
+
from tests.web_smoke_helpers import HAVE_MONGOMOCK, SKIP_REASON, run_against_app
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
SNIPPET = '''
|
|
16
|
+
from unittest.mock import patch
|
|
17
|
+
|
|
18
|
+
from application.models import account as account_module
|
|
19
|
+
from application.models.account import Account, account_is_master
|
|
20
|
+
|
|
21
|
+
now = [1000.0]
|
|
22
|
+
clock = patch.object(account_module.time, 'monotonic', side_effect=lambda: now[0])
|
|
23
|
+
clock.start()
|
|
24
|
+
|
|
25
|
+
account = Account(name='src', type='csv', address='', enabled=True)
|
|
26
|
+
account.save()
|
|
27
|
+
eq(account_is_master(str(account.id)), False, 'before the change')
|
|
28
|
+
|
|
29
|
+
Account.objects(id=account.id).update(set__is_master=True)
|
|
30
|
+
now[0] += account_module.IS_MASTER_CACHE_SECONDS - 1
|
|
31
|
+
eq(account_is_master(str(account.id)), False, 'within the cache time')
|
|
32
|
+
|
|
33
|
+
now[0] += 2
|
|
34
|
+
eq(account_is_master(str(account.id)), True, 'after the cache time')
|
|
35
|
+
|
|
36
|
+
clock.stop()
|
|
37
|
+
print('MASTER_CACHE_OK')
|
|
38
|
+
'''
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@unittest.skipUnless(HAVE_MONGOMOCK, SKIP_REASON)
|
|
42
|
+
class AccountMasterCacheTests(unittest.TestCase):
|
|
43
|
+
"""Runs the snippet against the booted app."""
|
|
44
|
+
|
|
45
|
+
def test_master_flag_reaches_a_running_process(self):
|
|
46
|
+
"""Cached within the cache time, read again after it."""
|
|
47
|
+
result = run_against_app(SNIPPET, False)
|
|
48
|
+
self.assertEqual(result.returncode, 0,
|
|
49
|
+
f"{result.stdout[-1500:]}\n{result.stderr[-1500:]}")
|
|
50
|
+
self.assertIn('MASTER_CACHE_OK', result.stdout)
|