cmdbsyncer 4.2.3__tar.gz → 4.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cmdbsyncer-4.2.3/cmdbsyncer.egg-info → cmdbsyncer-4.2.4}/PKG-INFO +1 -1
- cmdbsyncer-4.2.4/application/buildinfo.txt +1 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/changelog/v4.2.md +23 -16
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/cmk2.py +15 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/dcd.py +67 -9
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/downtimes.py +5 -1
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/inits.py +16 -3
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/models.py +6 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/syncer.py +1 -1
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/tags.py +22 -9
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/tests/test_cmk_rules.py +6 -3
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/tests/test_dcd.py +56 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/tests/test_tags.py +41 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/views.py +25 -1
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/netbox/__init__.py +40 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/netbox/devices.py +2 -20
- cmdbsyncer-4.2.4/application/plugins/netbox/interfaces.py +263 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/netbox/tests/test_import_filter.py +8 -8
- cmdbsyncer-4.2.4/application/plugins/netbox/utils.py +31 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/checkmk_rule_project_overview.html +3 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/model/inline_list_base.html +2 -2
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/themes/dracula.css +8 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/themes/gruvbox-dark.css +8 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/themes/gruvbox-light.css +9 -1
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/themes/nord.css +8 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/views/_form_sections.py +3 -2
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4/cmdbsyncer.egg-info}/PKG-INFO +1 -1
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/cmdbsyncer.egg-info/SOURCES.txt +1 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/pyproject.toml +1 -1
- cmdbsyncer-4.2.3/application/buildinfo.txt +0 -1
- cmdbsyncer-4.2.3/application/plugins/netbox/interfaces.py +0 -124
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/LICENSE +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/README.md +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/_version.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/api/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/api/inventory.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/api/objects.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/api/rules.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/api/syncer.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/api/views.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/auth/views.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/changelog/.pages +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/changelog/v3.10.md +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/changelog/v3.11.md +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/changelog/v3.12.md +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/changelog/v3.5.md +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/changelog/v3.7.md +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/changelog/v3.8.md +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/changelog/v3.9.md +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/changelog/v4.0.md +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/changelog/v4.1.md +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/cli.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/config.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/docu_links.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/enterprise.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/helpers/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/helpers/audit.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/helpers/cron.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/helpers/get_account.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/helpers/inventory.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/helpers/local_config_file.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/helpers/local_config_presets.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/helpers/mongo_keys.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/helpers/notification_channels.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/helpers/notification_dispatch.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/helpers/plugins.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/helpers/sates.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/helpers/sql.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/helpers/syncer_jinja.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/helpers/tablib_formater.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/helpers/tests/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/helpers/tests/test_sql.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/mcp_server.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/models/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/models/account.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/models/config.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/models/cron.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/models/field_approval.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/models/forms.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/models/host.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/models/host_inventory_tree.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/models/notification_channel.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/models/notification_rule.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/models/notification_state.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/models/saved_search.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/models/states.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/models/user.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/modules/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/modules/custom_attributes/models.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/modules/custom_attributes/rules.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/modules/custom_attributes/views.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/modules/debug.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/modules/email.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/modules/inventory/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/modules/log/log.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/modules/log/models.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/modules/log/views.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/modules/plugin.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/modules/rule/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/modules/rule/filter.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/modules/rule/match.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/modules/rule/models.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/modules/rule/rewrite.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/modules/rule/rule.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/modules/rule/views.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/modules/search_parser.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/modules/statefile.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/notices/strict_certificate_verification.txt +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/ansible/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/ansible/admin_views.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/ansible/inventory.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/ansible/models.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/ansible/playbook_rules.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/ansible/plugin.json +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/ansible/rules.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/ansible/runner.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/ansible/seed.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/ansible/site_syncer.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/ansible/views.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/bmc_remedy/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/bmc_remedy/bmc_remedy.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/bmc_remedy/plugin.json +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/admin_views.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/bi.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/cmk_rules.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/groups.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/helpers.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/import_v1.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/import_v2.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/inventorize.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/notification_rules.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/passwords.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/plugin.json +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/poolfolder.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/rule_passwords.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/rules.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/sites.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/tests/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/tests/test_bi.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/tests/test_cmk2.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/tests/test_downtimes.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/tests/test_groups.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/tests/test_helpers.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/tests/test_import_v1.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/tests/test_import_v2.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/tests/test_inventorize.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/tests/test_notification_rules.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/tests/test_passwords.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/tests/test_poolfolder.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/tests/test_rule_passwords.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/tests/test_rules.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/tests/test_sites.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/tests/test_syncer.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/tests/test_users.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/checkmk/users.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/cisco_dna/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/cisco_dna/plugin.json +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/cisco_dna/syncer.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/cron.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/csv/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/csv/csv.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/csv/plugin.json +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/file_requests.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/idoit/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/idoit/admin_views.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/idoit/models.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/idoit/plugin.json +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/idoit/rules.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/idoit/syncer.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/idoit/views.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/jdisc/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/jdisc/applications.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/jdisc/devices.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/jdisc/executables.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/jdisc/jdisc.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/jdisc/plugin.json +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/jira/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/jira/jira.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/jira/plugin.json +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/jira_cloud/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/jira_cloud/admin_views.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/jira_cloud/export.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/jira_cloud/jira_cloud.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/jira_cloud/models.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/jira_cloud/plugin.json +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/jira_cloud/rules.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/jira_cloud/schema_sync.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/jira_cloud/views.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/json/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/json/json.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/json/plugin.json +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/ldap/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/ldap/ldap.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/ldap/plugin.json +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/maintenance/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/maintenance/plugin.json +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/mssql/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/mssql/plugin.json +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/mysql/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/mysql/mysql.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/mysql/plugin.json +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/netbox/admin_views.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/netbox/cluster.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/netbox/contacts.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/netbox/dataflow.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/netbox/ips.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/netbox/models.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/netbox/netbox.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/netbox/networks.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/netbox/plugin.json +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/netbox/prefixes.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/netbox/rules.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/netbox/tests/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/netbox/views.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/netbox/virtualmachines.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/prtg/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/prtg/plugin.json +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/prtg/prtg.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/pyodbc/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/pyodbc/plugin.json +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/pyodbc/pyodbc.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/rest/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/rest/plugin.json +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/rest/rest.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/rules/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/rules/admin_views.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/rules/autorules.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/rules/models.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/rules/plugin.json +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/rules/rule_definitions.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/rules/rule_import_export.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/rules/views.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/syncer_shell.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/vmware/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/vmware/admin_views.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/vmware/custom_attributes.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/vmware/models.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/vmware/plugin.json +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/vmware/rules.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/vmware/views.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/vmware/vmware.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/yml/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/yml/plugin.json +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins/yml/yml.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/plugins_cli.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/static/cmdbsyncer_mark.png +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/static/css/cmdbsyncer.css +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/static/favicon.png +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/static/js/main.js +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/static/logo_white.png +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/_brand.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/_theme.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/_host_tabs.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/account_pick_type.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/ansible_playbook_run.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/ansible_project_detail.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/ansible_rule_list.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/ansible_run_details.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/bulk_label_form.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/changelog_archive.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/checkmk_rule_mngmt_list.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/checkmk_rule_project_edit.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/checkmk_rule_project_import.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/checkmk_rule_project_import_cmk.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/checkmk_rule_project_list.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/checkmk_settings_list.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/checkmk_test_folder_scope.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/copy_as_new_form.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/data_quality.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/file/list.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/file/modals/form.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/host_details.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/host_edit.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/host_inventory_tree.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/host_list.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/host_relations_graph.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/host_timeline.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/index.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/local_config_editor.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/master.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/model/clone_confirm.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/object_list.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/set_cmk_version_form.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/admin/set_template_form.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/base.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/change_password.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/debug.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/debug_host.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/email/newuser.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/email/notification.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/email/resetpassword.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/formular.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/license_info.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/login.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/logout_confirm.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/request_password.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/set_2fa.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/templates/set_theme.html +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/themes_registry.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/views/_form_fields.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/views/account.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/views/config.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/views/cron.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/views/data_quality.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/views/default.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/views/field_approval.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/views/fileadmin.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/views/host.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/views/host_filters.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/views/host_renderers.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/views/host_widgets.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/views/license.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/views/notification_channel.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/views/notification_rule.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/views/saved_search.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/application/views/user.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/cmdbsyncer.egg-info/dependency_links.txt +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/cmdbsyncer.egg-info/entry_points.txt +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/cmdbsyncer.egg-info/requires.txt +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/cmdbsyncer.egg-info/top_level.txt +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/requirements-ansible-windows.txt +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/requirements-ansible.txt +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/requirements-extras.txt +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/requirements.txt +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/setup.cfg +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/syncerapi/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/syncerapi/v1/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/syncerapi/v1/core/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/syncerapi/v1/inventory/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/syncerapi/v1/rest/__init__.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/tests/test_account_macro.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/tests/test_api.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/tests/test_api_csrf_invariant.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/tests/test_default_view.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/tests/test_mongo_keys.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/tests/test_plugin.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/tests/test_plugin_ssti.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/tests/test_plugins_cli.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/tests/test_rule.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/tests/test_rule_filename_detect.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/tests/test_rule_match.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/tests/test_search_parser.py +0 -0
- {cmdbsyncer-4.2.3 → cmdbsyncer-4.2.4}/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.2.
|
|
3
|
+
Version: 4.2.4
|
|
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-07-15T17:59:01Z
|
|
@@ -1,41 +1,48 @@
|
|
|
1
1
|
# Version 4.2
|
|
2
2
|
|
|
3
|
-
## Version 4.2.
|
|
3
|
+
## Version 4.2.4
|
|
4
4
|
|
|
5
5
|
### Checkmk
|
|
6
|
-
-
|
|
7
|
-
-
|
|
6
|
+
- FIX: Downtime export now reports the real error — a Checkmk/livestatus timeout or connection problem while reading current downtimes is surfaced (and re-raised with `--debug`) instead of ending in a generic "Checkmk: Export Downtimes" failure with no detail; reading downtimes for a host that returns no data no longer aborts the run
|
|
7
|
+
- FIX: Host export no longer logs "Created Host" when the host creation actually failed — the success line is now only printed when Checkmk accepted the host, so a failed single-host create is reported as an error instead of a false success
|
|
8
|
+
- FIX: Exporting host tags to Checkmk 2.5 no longer fails with "Unknown field" — the tag group id field (renamed from `ident` to `id` in Checkmk 2.4) is now selected per Checkmk version, so 2.3 and older keep working too
|
|
9
|
+
- FEAT: DCD rules can be flagged "static" — a host-independent DCD rule is rendered once and always created instead of being recalculated for every host, which speeds up the DCD export on large inventories (like the Setup rule static flag)
|
|
10
|
+
- FIX: Exporting DCD rules works again on Checkmk 2.4 and 2.5 — the connector settings are now sent nested under a `connector` object as the REST API requires; before, the export failed with many "Unknown field" errors. Checkmk 2.3 keeps its two extra connector fields
|
|
11
|
+
- FEAT: A DCD rule's site can be set to `{{ cmk_site }}`, which resolves to the exporting account's Checkmk site — so one rule targets the right site on a test and a prod instance with different site names; the field now shows this as a placeholder hint
|
|
12
|
+
- FEAT: DCD rules can use `{{ account.<field> }}` to insert any (non-secret) attribute of the exporting Checkmk account — including per-account custom fields — so one rule adapts its values per account (e.g. test vs prod); passwords are never exposed
|
|
13
|
+
|
|
14
|
+
### Netbox
|
|
15
|
+
- FEAT: Netbox can now import interfaces of devices and virtual machines (analogous to the device and VM import) — each host's Netbox interfaces, including their assigned IP addresses, are stored on the host's inventory; with the account option `import_as_hosts` every interface is instead imported as its own host so it can be exported again
|
|
16
|
+
|
|
17
|
+
### Interface
|
|
18
|
+
- FIX: Rule forms render fully theme-aware on the dark themes (Gruvbox, Dracula, Nord) — the nested outcome/condition field groups and their "Add …" buttons no longer show a hard-coded white/light background; nested cards, `bg-light`/`bg-white` utilities and the inline "Add" buttons now follow the active theme's surface colours everywhere
|
|
8
19
|
|
|
9
|
-
## Version 4.2.
|
|
20
|
+
## Version 4.2.3
|
|
10
21
|
|
|
11
22
|
### Ansible
|
|
12
23
|
- FIX: Playbook tasks delegated to localhost (`delegate_to: localhost`) no longer abort with "Failed to create temporary directory" under the web server — the local connection's temp dir now points at a writable per-run path instead of the web user's home
|
|
13
24
|
- FEAT: Checkmk Settings gain an "installation staging path" — the Checkmk server-management playbook stages the downloaded installer there instead of `/tmp`; leave it empty to keep using `/tmp`. Use it when the executing user can't reliably use `/tmp` (permission or private-tmp isolation)
|
|
14
25
|
- FIX: The Checkmk site-update playbook no longer fails the "set downtime" step with "401 Unauthorized" when no Checkmk API user/secret is configured — the downtime is skipped instead
|
|
26
|
+
- FIX: Running a playbook from the UI no longer aborts with "cmdbsyncer binary not found" — the local-mode inventory now resolves the `cmdbsyncer` CLI from the venv even when the web server's PATH omits it
|
|
27
|
+
|
|
28
|
+
### Setup
|
|
29
|
+
- FIX: A fresh `docker compose up` from git now starts — the bundled compose stack was told to reach MongoDB on `127.0.0.1` (the app container itself) instead of the `mongo` service, so the API aborted on boot with `Connection refused` (gh #124)
|
|
15
30
|
|
|
16
31
|
### Checkmk
|
|
32
|
+
- FIX: Importing Setup Rules from a Checkmk folder now surfaces the real Checkmk error (e.g. wrong credentials) instead of silently reporting "0 rules imported"
|
|
33
|
+
- FEAT: The Checkmk group export now honors an account's (or child account's) object filter for "Checkmk: Export Groups" — set it to include CMDB objects/shadow hosts in the group calculation; without a filter the export stays host-only as before
|
|
17
34
|
- FEAT: The Checkmk module menu is tidier — "Setup Rule Projects" now sits next to "Manage Checkmk Setup Rules", "Limit Host Export to Folders" moved under the host filters, and the separate "Export Scoping" submenu is gone
|
|
18
35
|
- FIX: "Limit Host Export to Folders" now lists rule folders in lowercase to match Checkmk's folder names, so the scope reliably matches the folders hosts are exported to
|
|
19
36
|
- FEAT: "Limit Host Export to Folders" is easier to use — clicking a rule folder or typing one adds it to a list of selected folders you can remove individually, instead of editing a comma-separated text field
|
|
20
37
|
- FEAT: Importing Setup Rules from a Checkmk folder into a project now shows a progress bar and status message while it runs, so you can see it is working
|
|
21
38
|
- FEAT: Checkmk Setup Rules can reference a syncer Checkmk Password with `{{ cmk_password("name") }}`, which resolves to that entry's Checkmk password-store ident on export — run the password export so the entry exists in the target Checkmk
|
|
22
39
|
- FEAT: Importing rules from a Checkmk folder now rewrites inline rule passwords (which Checkmk masks as `******` on read) into such password-store references, so imported rules deploy from a test to a production Checkmk without exposing or overwriting the secret — create a Checkmk Password with the reported name and export it
|
|
40
|
+
- FEAT: The Checkmk rule export now respects an account's folder scope ("Limit Host Export to Folders") — a scoped account only receives Setup rules whose target folder is in scope, just like the host export
|
|
41
|
+
- FEAT: DCD rules can be assigned to a Rule Project — they show on the project overview, follow the project's account filter on export (only exported to the accounts the project allows), and are included in the project's JSON export/import; the project list gains an "Import project from JSON" button
|
|
23
42
|
|
|
24
43
|
### Interface
|
|
25
44
|
- FIX: Card-style admin form pages (e.g. the "New Account" plugin-type picker) render with consistent padding and a theme-aware header in all four themes, instead of a header hanging off the edge of a flat card
|
|
26
45
|
|
|
27
|
-
## Version 4.2.1
|
|
28
|
-
|
|
29
|
-
### Ansible
|
|
30
|
-
- FIX: Running a playbook from the UI no longer aborts with "cmdbsyncer binary not found" — the local-mode inventory now resolves the `cmdbsyncer` CLI from the venv even when the web server's PATH omits it
|
|
31
|
-
|
|
32
|
-
### Setup
|
|
33
|
-
- FIX: A fresh `docker compose up` from git now starts — the bundled compose stack was told to reach MongoDB on `127.0.0.1` (the app container itself) instead of the `mongo` service, so the API aborted on boot with `Connection refused` (gh #124)
|
|
34
|
-
|
|
35
|
-
### Checkmk
|
|
36
|
-
- FIX: Importing Setup Rules from a Checkmk folder now surfaces the real Checkmk error (e.g. wrong credentials) instead of silently reporting "0 rules imported"
|
|
37
|
-
- FEAT: The Checkmk group export now honors an account's (or child account's) object filter for "Checkmk: Export Groups" — set it to include CMDB objects/shadow hosts in the group calculation; without a filter the export stays host-only as before
|
|
38
|
-
|
|
39
46
|
## Version 4.2.0
|
|
40
47
|
|
|
41
48
|
### Hosts
|
|
@@ -69,6 +69,21 @@ class CMK2(Plugin):
|
|
|
69
69
|
self._init_complete = True
|
|
70
70
|
|
|
71
71
|
|
|
72
|
+
def version_at_least(self, major, minor):
|
|
73
|
+
"""
|
|
74
|
+
True when the probed Checkmk version is at least ``major.minor``.
|
|
75
|
+
|
|
76
|
+
Central helper for version switches in the export code (the Checkmk REST
|
|
77
|
+
API changes field shapes between releases). ``checkmk_version`` looks
|
|
78
|
+
like ``2.4.0p19.cee`` or ``2.5.0.pro``; an unreadable value is treated
|
|
79
|
+
as the newest release so new installs get the current behaviour.
|
|
80
|
+
"""
|
|
81
|
+
try:
|
|
82
|
+
release = tuple(int(p) for p in str(self.checkmk_version).split('.')[:2])
|
|
83
|
+
except (AttributeError, ValueError, TypeError):
|
|
84
|
+
return True
|
|
85
|
+
return release >= (major, minor)
|
|
86
|
+
|
|
72
87
|
def _probe_checkmk_version(self):
|
|
73
88
|
"""
|
|
74
89
|
Ask Checkmk for its version and return the bare version string.
|
|
@@ -17,6 +17,10 @@ class CheckmkDCDRuleSync(CMK2):
|
|
|
17
17
|
"""
|
|
18
18
|
console = None
|
|
19
19
|
|
|
20
|
+
# Host-independent DCD rules, rendered once instead of per host. Injected
|
|
21
|
+
# by inits.export_dcd_rules; defaults to empty so other callers still work.
|
|
22
|
+
static_rules = []
|
|
23
|
+
|
|
20
24
|
def __init__(self, account=False):
|
|
21
25
|
super().__init__(account)
|
|
22
26
|
# Per-instance run state. Class-level defaults would accumulate
|
|
@@ -24,6 +28,33 @@ class CheckmkDCDRuleSync(CMK2):
|
|
|
24
28
|
# into later exports.
|
|
25
29
|
self.all_rules = []
|
|
26
30
|
|
|
31
|
+
# Account config keys withheld from the rule template context — secrets and
|
|
32
|
+
# internal ids that must never end up in a rendered rule.
|
|
33
|
+
_ACCOUNT_HIDDEN_KEYS = frozenset({
|
|
34
|
+
'password', 'bakery_passphrase', 'ca_cert_chain', 'ca_root_cert',
|
|
35
|
+
'_id', 'id', 'ref',
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
def _account_site(self):
|
|
39
|
+
"""
|
|
40
|
+
Checkmk site name of the exporting account — the last path segment of
|
|
41
|
+
its address (which ends in ``/<site>``). Exposed to DCD rules as
|
|
42
|
+
``{{ cmk_site }}`` so one rule can target the correct site on each
|
|
43
|
+
Checkmk (e.g. a test and a prod instance with different site names).
|
|
44
|
+
"""
|
|
45
|
+
address = (self.config.get('address') or '').rstrip('/')
|
|
46
|
+
return address.rsplit('/', 1)[-1] if '/' in address else ''
|
|
47
|
+
|
|
48
|
+
def _account_context(self):
|
|
49
|
+
"""
|
|
50
|
+
The exporting account's attributes exposed to DCD rules as
|
|
51
|
+
``{{ account.<field> }}`` — its standard fields plus any per-account
|
|
52
|
+
custom field (flattened into the account config). Lets one rule use a
|
|
53
|
+
value configured per account (test vs prod). Secrets are withheld.
|
|
54
|
+
"""
|
|
55
|
+
return {key: value for key, value in (self.config or {}).items()
|
|
56
|
+
if key not in self._ACCOUNT_HIDDEN_KEYS}
|
|
57
|
+
|
|
27
58
|
def does_rule_exist(self, rule_id):
|
|
28
59
|
"""
|
|
29
60
|
Check if Rule is existing
|
|
@@ -97,25 +128,34 @@ class CheckmkDCDRuleSync(CMK2):
|
|
|
97
128
|
exclude_time_ranges = self.build_timeranges(rule)
|
|
98
129
|
|
|
99
130
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
"site": render_jinja(rule['site'], mode='raise',**attributes),
|
|
131
|
+
# Checkmk's DCD REST API nests the connector settings under a
|
|
132
|
+
# "connector" object (all three supported versions). Checkmk 2.4
|
|
133
|
+
# dropped the "activate_changes_interval" and "exclude_time_ranges"
|
|
134
|
+
# connector fields — only 2.3 and older still accept them.
|
|
135
|
+
connector = {
|
|
106
136
|
"connector_type": render_jinja(rule['connector_type'], mode='raise',**attributes),
|
|
107
137
|
"restrict_source_hosts": restricted_hosts,
|
|
108
138
|
"interval": render_jinja(rule['interval'], mode='raise', **attributes),
|
|
109
139
|
"creation_rules": creation_rules,
|
|
110
|
-
"activate_changes_interval": render_jinja(rule['activate_changes_interval'], \
|
|
111
|
-
**attributes),
|
|
112
140
|
"discover_on_creation": rule['discover_on_creation'],
|
|
113
|
-
"exclude_time_ranges": exclude_time_ranges,
|
|
114
141
|
"no_deletion_time_after_init": render_jinja(rule['no_deletion_time_after_init'],\
|
|
115
142
|
**attributes),
|
|
116
143
|
"max_cache_age": render_jinja(rule['max_cache_age'], **attributes),
|
|
117
144
|
"validity_period": render_jinja(rule['validity_period'], **attributes),
|
|
118
145
|
}
|
|
146
|
+
if not self.version_at_least(2, 4):
|
|
147
|
+
connector["activate_changes_interval"] = \
|
|
148
|
+
render_jinja(rule['activate_changes_interval'], **attributes)
|
|
149
|
+
connector["exclude_time_ranges"] = exclude_time_ranges
|
|
150
|
+
|
|
151
|
+
payload = {
|
|
152
|
+
"dcd_id": render_jinja(rule['dcd_id'], mode='raise', **attributes),
|
|
153
|
+
"title": render_jinja(rule['title'], mode='raise', **attributes),
|
|
154
|
+
"comment": render_jinja(rule['comment'], mode='raise',**attributes),
|
|
155
|
+
"disabled": rule['disabled'],
|
|
156
|
+
"site": render_jinja(rule['site'], mode='raise',**attributes),
|
|
157
|
+
"connector": connector,
|
|
158
|
+
}
|
|
119
159
|
if rule['documentation_url']:
|
|
120
160
|
payload['documentation_url']= rule['documentation_url']
|
|
121
161
|
logger.debug(payload)
|
|
@@ -151,6 +191,11 @@ class CheckmkDCDRuleSync(CMK2):
|
|
|
151
191
|
Export DCD Rules
|
|
152
192
|
"""
|
|
153
193
|
|
|
194
|
+
# Exposed to every DCD rule: {{ cmk_site }} = the account's Checkmk site,
|
|
195
|
+
# and {{ account.<field> }} = any (non-secret) account attribute, so one
|
|
196
|
+
# rule can use values configured per account (test vs prod).
|
|
197
|
+
site = self._account_site()
|
|
198
|
+
account_ctx = self._account_context()
|
|
154
199
|
db_objects = Host.active_non_template()
|
|
155
200
|
total = db_objects.count()
|
|
156
201
|
with Progress(SpinnerColumn(),
|
|
@@ -168,12 +213,25 @@ class CheckmkDCDRuleSync(CMK2):
|
|
|
168
213
|
logger.debug(' -- Skiped no attributes')
|
|
169
214
|
progress.advance(task1)
|
|
170
215
|
continue
|
|
216
|
+
attributes['all']['cmk_site'] = site
|
|
217
|
+
attributes['all']['account'] = account_ctx
|
|
171
218
|
# pylint: disable-next=no-member
|
|
172
219
|
host_actions = self.actions.get_outcomes(db_host, attributes['all'])
|
|
173
220
|
if host_actions:
|
|
174
221
|
logger.debug(' -- Got Actions')
|
|
175
222
|
self.calculate_rules_of_host(db_host.hostname, host_actions, attributes['all'])
|
|
176
223
|
progress.advance(task1)
|
|
224
|
+
|
|
225
|
+
# Static rules carry no host data: render each once against an empty
|
|
226
|
+
# host context instead of per host (their match conditions are
|
|
227
|
+
# ignored — a static rule is always emitted).
|
|
228
|
+
for rule in self.static_rules:
|
|
229
|
+
host_actions = {'dcd': [dict(outcome.to_mongo())
|
|
230
|
+
for outcome in rule.outcomes]}
|
|
231
|
+
self.calculate_rules_of_host(
|
|
232
|
+
f"static:{rule.name}", host_actions,
|
|
233
|
+
{'cmk_site': site, 'account': account_ctx})
|
|
234
|
+
|
|
177
235
|
task2 = progress.add_task("Send Rules to Checkmk", total=len(self.all_rules))
|
|
178
236
|
count_new = 0
|
|
179
237
|
count_existing = 0
|
|
@@ -316,7 +316,11 @@ class CheckmkDowntimeSync(CMK2):
|
|
|
316
316
|
url = f"domain-types/downtime/collections/all?"\
|
|
317
317
|
f"host_name={hostname}&downtime_type=host"
|
|
318
318
|
response = self.request(url, method="GET")
|
|
319
|
-
|
|
319
|
+
# request() returns an empty ``{}`` body on error responses
|
|
320
|
+
# (404, non-200, no content). Guard the lookup so a failed
|
|
321
|
+
# downtime read yields "no current downtimes" instead of a bare
|
|
322
|
+
# KeyError that would escape as a detail-less run failure.
|
|
323
|
+
downtimes = response[0].get('value', []) if response[0] else []
|
|
320
324
|
for downtime in downtimes:
|
|
321
325
|
yield {
|
|
322
326
|
"start" : datetime.datetime.fromisoformat(
|
|
@@ -516,10 +516,16 @@ def export_downtimes(account, debug=False, debug_rules=False):
|
|
|
516
516
|
syncer.actions = actions
|
|
517
517
|
syncer.debug_rules(debug_rules, "Checkmk")
|
|
518
518
|
|
|
519
|
-
except
|
|
519
|
+
except Exception as error_obj: # pylint: disable=broad-exception-caught
|
|
520
|
+
# Catch every error, not just CmkException: the downtime export
|
|
521
|
+
# talks to Checkmk's livestatus (e.g. reading current downtimes),
|
|
522
|
+
# which can raise a plain requests timeout/connection error. With
|
|
523
|
+
# the old CmkException-only catch those escaped uncaught, so the
|
|
524
|
+
# run left only a detail-less "Checkmk: Export Downtimes" log entry
|
|
525
|
+
# and `--debug` never surfaced the real cause.
|
|
520
526
|
if debug:
|
|
521
527
|
raise
|
|
522
|
-
print(f'
|
|
528
|
+
print(f'{ColorCodes.FAIL}Error: {error_obj} {ColorCodes.ENDC}')
|
|
523
529
|
if syncer is not None:
|
|
524
530
|
syncer.record_exception(error_obj)
|
|
525
531
|
else:
|
|
@@ -545,13 +551,19 @@ def export_dcd_rules(account, debug=False, debug_rules=False):
|
|
|
545
551
|
# allows. Rules without a project stay global (exported everywhere),
|
|
546
552
|
# matching the Setup-rule export.
|
|
547
553
|
allowed_projects = [None, ''] + projects_for_account(account)
|
|
554
|
+
# Static rules carry no host data — they are rendered once (see
|
|
555
|
+
# CheckmkDCDRuleSync.export_rules) instead of per host, so they are kept
|
|
556
|
+
# out of the per-host engine here.
|
|
548
557
|
actions.rules = CheckmkDCDRule.objects(
|
|
549
|
-
enabled=True, project__in=allowed_projects)
|
|
558
|
+
enabled=True, static_rule__ne=True, project__in=allowed_projects)
|
|
559
|
+
static_rules = CheckmkDCDRule.objects(
|
|
560
|
+
enabled=True, static_rule=True, project__in=allowed_projects)
|
|
550
561
|
|
|
551
562
|
if not debug_rules:
|
|
552
563
|
syncer = CheckmkDCDRuleSync(account)
|
|
553
564
|
syncer.debug = debug
|
|
554
565
|
syncer.actions = actions
|
|
566
|
+
syncer.static_rules = static_rules
|
|
555
567
|
syncer.rewrite = rules['rewrite']
|
|
556
568
|
syncer.filter = rules['filter']
|
|
557
569
|
syncer.name = 'Checkmk: Export DCD Rules'
|
|
@@ -560,6 +572,7 @@ def export_dcd_rules(account, debug=False, debug_rules=False):
|
|
|
560
572
|
else:
|
|
561
573
|
syncer = CheckmkDCDRuleSync(False)
|
|
562
574
|
syncer.actions = actions
|
|
575
|
+
syncer.static_rules = static_rules
|
|
563
576
|
syncer.rewrite = rules['rewrite']
|
|
564
577
|
syncer.filter = rules['filter']
|
|
565
578
|
syncer.debug_rules(debug_rules, "Checkmk")
|
|
@@ -690,6 +690,12 @@ class CheckmkDCDRule(db.Document):
|
|
|
690
690
|
render_cmk_dcd_rule = db.StringField()
|
|
691
691
|
last_match = db.BooleanField(default=False)
|
|
692
692
|
|
|
693
|
+
# Host-independent DCD rule: a DCD connection rarely depends on host data, so
|
|
694
|
+
# a static rule is rendered once (against an empty host context, ignoring the
|
|
695
|
+
# match conditions) instead of once per host and de-duplicated — the same
|
|
696
|
+
# optimisation CheckmkRuleMngmt.static_rule provides for Setup rules.
|
|
697
|
+
static_rule = db.BooleanField(default=False)
|
|
698
|
+
|
|
693
699
|
# Name of the CheckmkRuleProject this DCD rule belongs to (or empty).
|
|
694
700
|
# Referenced by name to match CheckmkRuleMngmt.project. A DCD rule assigned
|
|
695
701
|
# to a project follows that project's account filter (limit_by_accounts) on
|
|
@@ -1022,10 +1022,10 @@ class SyncCMK2(CMK2):
|
|
|
1022
1022
|
try:
|
|
1023
1023
|
self.request(url, method="POST", data=body)
|
|
1024
1024
|
self.num_created += 1
|
|
1025
|
+
self.console(f" * Created Host {hostname}")
|
|
1025
1026
|
except CmkException as error:
|
|
1026
1027
|
self.log_details.append(('error', f"Host Create Error: {error}"))
|
|
1027
1028
|
self.console(f" * CMK API ERROR {error}")
|
|
1028
|
-
self.console(f" * Created Host {hostname}")
|
|
1029
1029
|
|
|
1030
1030
|
|
|
1031
1031
|
|
|
@@ -310,6 +310,7 @@ class CheckmkTagSync(CMK2):
|
|
|
310
310
|
config_tags.sort(key=lambda tup: tup[1])
|
|
311
311
|
if len(config_tags) > 1:
|
|
312
312
|
config_tags.insert(0, (None, "Not set"))
|
|
313
|
+
id_field = self._tag_id_field()
|
|
313
314
|
found_ids = []
|
|
314
315
|
tags = []
|
|
315
316
|
for x, y in config_tags:
|
|
@@ -319,7 +320,7 @@ class CheckmkTagSync(CMK2):
|
|
|
319
320
|
if not y:
|
|
320
321
|
continue
|
|
321
322
|
if x not in found_ids:
|
|
322
|
-
tags.append({
|
|
323
|
+
tags.append({id_field: x, 'title': y})
|
|
323
324
|
found_ids.append(x)
|
|
324
325
|
|
|
325
326
|
if not tags or len(tags) == 0:
|
|
@@ -327,6 +328,14 @@ class CheckmkTagSync(CMK2):
|
|
|
327
328
|
return False
|
|
328
329
|
return tags
|
|
329
330
|
|
|
331
|
+
def _tag_id_field(self):
|
|
332
|
+
"""
|
|
333
|
+
Field name for a host tag group id and its tag choices. Checkmk renamed
|
|
334
|
+
it from ``ident`` to ``id`` in 2.4, so 2.4+ use ``id`` and 2.3 and older
|
|
335
|
+
use ``ident`` (verified against 2.3.0p48, 2.4.0p19 and 2.5.0p8).
|
|
336
|
+
"""
|
|
337
|
+
return 'id' if self.version_at_least(2, 4) else 'ident'
|
|
338
|
+
|
|
330
339
|
def sync_to_checkmk(self, groups, tag_group_list):
|
|
331
340
|
"""
|
|
332
341
|
Use generated configuration to Sync
|
|
@@ -341,12 +350,17 @@ class CheckmkTagSync(CMK2):
|
|
|
341
350
|
*Progress.get_default_columns(),
|
|
342
351
|
TimeElapsedColumn()) as progress:
|
|
343
352
|
task1 = progress.add_task("Sending to Checkmk", total=len(groups))
|
|
353
|
+
# Checkmk renamed the tag group id field 'ident' -> 'id' in 2.4.
|
|
354
|
+
id_field = self._tag_id_field()
|
|
344
355
|
for syncer_group_id, syncer_group_data in groups.items():
|
|
345
356
|
payload = syncer_group_data.copy()
|
|
346
357
|
for what in ['object_filter', 'rw_id', 'is_template',
|
|
347
358
|
'rw_title', 'multiply_list']:
|
|
348
359
|
if what in payload:
|
|
349
360
|
del payload[what]
|
|
361
|
+
# The group is built with an 'ident' key internally; send it
|
|
362
|
+
# under the field name this Checkmk version expects.
|
|
363
|
+
payload[id_field] = payload.pop('ident')
|
|
350
364
|
|
|
351
365
|
tag_list = [(x[1], x[2]) for x in tag_group_list if x[0] == syncer_group_id]
|
|
352
366
|
if tags := self.prepare_tags_for_checkmk(tag_list):
|
|
@@ -362,7 +376,7 @@ class CheckmkTagSync(CMK2):
|
|
|
362
376
|
# Check if we need to update it
|
|
363
377
|
checkmk_tags = checkmk_ids[syncer_group_id]
|
|
364
378
|
checkmk_tags_flat = \
|
|
365
|
-
[{
|
|
379
|
+
[{id_field: x['id'], 'title': x['title']} \
|
|
366
380
|
for x in checkmk_tags if x['title'].strip()]
|
|
367
381
|
|
|
368
382
|
if app.config['CMK_DONT_DELETE_TAGS']:
|
|
@@ -370,10 +384,10 @@ class CheckmkTagSync(CMK2):
|
|
|
370
384
|
found = set()
|
|
371
385
|
new_tags = []
|
|
372
386
|
for tag in payload['tags'] + checkmk_tags_flat:
|
|
373
|
-
if tag[
|
|
374
|
-
found.add(tag[
|
|
387
|
+
if tag[id_field] not in found:
|
|
388
|
+
found.add(tag[id_field])
|
|
375
389
|
new_tags.append(tag)
|
|
376
|
-
payload['tags'] = sorted(new_tags, key=lambda x: str(x[
|
|
390
|
+
payload['tags'] = sorted(new_tags, key=lambda x: str(x[id_field]))
|
|
377
391
|
checkmk_tags_frozen = {frozenset(d.items()) for d in checkmk_tags_flat}
|
|
378
392
|
syncer_tags_frozen = {frozenset(d.items()) for d in payload['tags']}
|
|
379
393
|
if checkmk_tags_frozen == syncer_tags_frozen:
|
|
@@ -386,12 +400,11 @@ class CheckmkTagSync(CMK2):
|
|
|
386
400
|
update_headers = {
|
|
387
401
|
'if-match': etag
|
|
388
402
|
}
|
|
389
|
-
del payload[
|
|
403
|
+
del payload[id_field]
|
|
390
404
|
payload['repair'] = False
|
|
391
405
|
try:
|
|
392
|
-
self.request(
|
|
393
|
-
method="PUT",
|
|
394
|
-
data=payload,
|
|
406
|
+
self.request(
|
|
407
|
+
url, method="PUT", data=payload,
|
|
395
408
|
additional_header=update_headers)
|
|
396
409
|
except Exception as error:
|
|
397
410
|
progress.console.print(f" ! Group {syncer_group_id} can't be updated.")
|
|
@@ -975,9 +975,12 @@ class TestExportDcdRulesProjectFilter(unittest.TestCase):
|
|
|
975
975
|
patch.object(inits, 'CheckmkDCDRule') as mock_dcd:
|
|
976
976
|
mock_dcd.objects.return_value = ['rule']
|
|
977
977
|
inits.export_dcd_rules('acc_a')
|
|
978
|
-
# Global (no project) rules plus the projects this account is allowed
|
|
979
|
-
|
|
980
|
-
|
|
978
|
+
# Global (no project) rules plus the projects this account is allowed,
|
|
979
|
+
# split into the per-host (non-static) and static-rule querysets.
|
|
980
|
+
mock_dcd.objects.assert_any_call(
|
|
981
|
+
enabled=True, static_rule__ne=True, project__in=[None, '', 'proj_a'])
|
|
982
|
+
mock_dcd.objects.assert_any_call(
|
|
983
|
+
enabled=True, static_rule=True, project__in=[None, '', 'proj_a'])
|
|
981
984
|
|
|
982
985
|
|
|
983
986
|
if __name__ == '__main__':
|
|
@@ -171,6 +171,62 @@ class TestCheckmkDCDRuleSync(unittest.TestCase):
|
|
|
171
171
|
result = self.sync.build_rule_payload(rule, {})
|
|
172
172
|
self.assertEqual(result, {})
|
|
173
173
|
|
|
174
|
+
def _payload_rule(self):
|
|
175
|
+
return {
|
|
176
|
+
'dcd_id': 'dcd1', 'title': 'T', 'comment': '', 'disabled': False,
|
|
177
|
+
'site': 'site1', 'connector_type': 'piggyback',
|
|
178
|
+
'restricted_source_hosts': [], 'interval': '60',
|
|
179
|
+
'creation_rules': [], 'activate_changes_interval': '300',
|
|
180
|
+
'discover_on_creation': True, 'exclude_time_ranges': [],
|
|
181
|
+
'no_deletion_time_after_init': '120', 'max_cache_age': '3600',
|
|
182
|
+
'validity_period': '60', 'documentation_url': '',
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
@patch('application.plugins.checkmk.dcd.render_jinja')
|
|
186
|
+
def test_payload_nests_connector_on_24plus(self, mock_render):
|
|
187
|
+
# Checkmk 2.4+ wants the connector settings nested under "connector"
|
|
188
|
+
# and no longer accepts the two 2.3-only fields.
|
|
189
|
+
mock_render.side_effect = lambda tpl, **kw: tpl
|
|
190
|
+
self.sync.checkmk_version = '2.4.0p19.cee'
|
|
191
|
+
result = self.sync.build_rule_payload(self._payload_rule(), {})
|
|
192
|
+
self.assertIn('connector', result)
|
|
193
|
+
self.assertNotIn('connector_type', result) # not at top level
|
|
194
|
+
conn = result['connector']
|
|
195
|
+
self.assertEqual(conn['connector_type'], 'piggyback')
|
|
196
|
+
self.assertIn('interval', conn)
|
|
197
|
+
self.assertNotIn('activate_changes_interval', conn)
|
|
198
|
+
self.assertNotIn('exclude_time_ranges', conn)
|
|
199
|
+
|
|
200
|
+
@patch('application.plugins.checkmk.dcd.render_jinja')
|
|
201
|
+
def test_payload_connector_keeps_23_fields(self, mock_render):
|
|
202
|
+
mock_render.side_effect = lambda tpl, **kw: tpl
|
|
203
|
+
self.sync.checkmk_version = '2.3.0p48.cce'
|
|
204
|
+
conn = self.sync.build_rule_payload(self._payload_rule(), {})['connector']
|
|
205
|
+
self.assertIn('activate_changes_interval', conn)
|
|
206
|
+
self.assertIn('exclude_time_ranges', conn)
|
|
207
|
+
|
|
208
|
+
def test_account_site(self):
|
|
209
|
+
self.sync.config = {'address': 'http://host:8080/cmk/'}
|
|
210
|
+
self.assertEqual(self.sync._account_site(), 'cmk')
|
|
211
|
+
self.sync.config = {'address': 'https://mon.example.com/prod'}
|
|
212
|
+
self.assertEqual(self.sync._account_site(), 'prod')
|
|
213
|
+
self.sync.config = {'address': ''}
|
|
214
|
+
self.assertEqual(self.sync._account_site(), '')
|
|
215
|
+
|
|
216
|
+
def test_account_context_exposes_fields_without_secrets(self):
|
|
217
|
+
self.sync.config = {
|
|
218
|
+
'name': 'prod', 'address': 'http://h/cmk', 'username': 'auto',
|
|
219
|
+
'my_field': 'x', 'password': 'secret',
|
|
220
|
+
'bakery_passphrase': 'p', '_id': 1,
|
|
221
|
+
}
|
|
222
|
+
ctx = self.sync._account_context()
|
|
223
|
+
# custom + standard fields are exposed
|
|
224
|
+
self.assertEqual(ctx['name'], 'prod')
|
|
225
|
+
self.assertEqual(ctx['my_field'], 'x')
|
|
226
|
+
# secrets / internal ids are withheld
|
|
227
|
+
for hidden in ('password', 'bakery_passphrase', '_id'):
|
|
228
|
+
self.assertNotIn(hidden, ctx)
|
|
229
|
+
|
|
174
230
|
def test_create_rule_in_cmk(self):
|
|
175
231
|
with patch.object(self.sync, 'request') as mock_req:
|
|
176
232
|
mock_req.return_value = (None, {})
|
|
@@ -236,5 +236,46 @@ class TestCheckmkTagSync(unittest.TestCase):
|
|
|
236
236
|
self.assertEqual(result['grp1'], ('pre_id', 'Pre Title'))
|
|
237
237
|
|
|
238
238
|
|
|
239
|
+
class TestTagIdFieldSwitch(unittest.TestCase):
|
|
240
|
+
"""The host tag group id field switch (ident vs id) by Checkmk version."""
|
|
241
|
+
|
|
242
|
+
def setUp(self):
|
|
243
|
+
def mock_init(self_param, account=False):
|
|
244
|
+
base_mock_init(self_param, groups={})
|
|
245
|
+
|
|
246
|
+
self.init_patcher = patch(
|
|
247
|
+
'application.plugins.checkmk.tags.CMK2.__init__', mock_init)
|
|
248
|
+
self.init_patcher.start()
|
|
249
|
+
self.sync = CheckmkTagSync()
|
|
250
|
+
|
|
251
|
+
def tearDown(self):
|
|
252
|
+
self.init_patcher.stop()
|
|
253
|
+
|
|
254
|
+
def test_tag_id_field_by_version(self):
|
|
255
|
+
cases = {
|
|
256
|
+
'2.2.0p1': 'ident',
|
|
257
|
+
'2.3.0p48.cre': 'ident',
|
|
258
|
+
'2.4.0p19.cee': 'id',
|
|
259
|
+
'2.5.0p8.pro': 'id',
|
|
260
|
+
'3.0.0': 'id',
|
|
261
|
+
'': 'id', # unknown -> assume modern
|
|
262
|
+
'garbage': 'id',
|
|
263
|
+
}
|
|
264
|
+
for version, expected in cases.items():
|
|
265
|
+
self.sync.checkmk_version = version
|
|
266
|
+
self.assertEqual(self.sync._tag_id_field(), expected,
|
|
267
|
+
f"version {version!r}")
|
|
268
|
+
|
|
269
|
+
def test_prepare_tags_uses_ident_on_23(self):
|
|
270
|
+
self.sync.checkmk_version = '2.3.0p48.cre'
|
|
271
|
+
tags = self.sync.prepare_tags_for_checkmk([('v1', 'Val1')])
|
|
272
|
+
self.assertEqual(tags, [{'ident': 'v1', 'title': 'Val1'}])
|
|
273
|
+
|
|
274
|
+
def test_prepare_tags_uses_id_on_24plus(self):
|
|
275
|
+
self.sync.checkmk_version = '2.4.0p19.cee'
|
|
276
|
+
tags = self.sync.prepare_tags_for_checkmk([('v1', 'Val1')])
|
|
277
|
+
self.assertEqual(tags, [{'id': 'v1', 'title': 'Val1'}])
|
|
278
|
+
|
|
279
|
+
|
|
239
280
|
if __name__ == '__main__':
|
|
240
281
|
unittest.main(verbosity=2)
|
|
@@ -1854,7 +1854,7 @@ class CheckmkDCDView(RuleModelView):
|
|
|
1854
1854
|
rules.Field('documentation'),
|
|
1855
1855
|
rules.Field('project'),
|
|
1856
1856
|
div_open,
|
|
1857
|
-
rules.NestedRule(('enabled', 'last_match')),
|
|
1857
|
+
rules.NestedRule(('enabled', 'last_match', 'static_rule')),
|
|
1858
1858
|
div_close,
|
|
1859
1859
|
rules.Field('sort_field'),
|
|
1860
1860
|
],
|
|
@@ -1888,6 +1888,30 @@ class CheckmkDCDView(RuleModelView):
|
|
|
1888
1888
|
"rule is exported only to the accounts the project allows (a "
|
|
1889
1889
|
"project without an account filter still exports everywhere)."
|
|
1890
1890
|
)
|
|
1891
|
+
self.form_descriptions['static_rule'] = (
|
|
1892
|
+
"Host-independent rule: render it once and always create it, "
|
|
1893
|
+
"ignoring the match conditions. A DCD connection rarely depends on "
|
|
1894
|
+
"host data, so this skips the per-host calculation and is much "
|
|
1895
|
+
"faster on large inventories. Use only when the outcome templates "
|
|
1896
|
+
"reference no host attributes."
|
|
1897
|
+
)
|
|
1898
|
+
|
|
1899
|
+
# Hint the {{ cmk_site }} macro in the outcome's Site field so users see
|
|
1900
|
+
# they can target the exporting account's own Checkmk site (test/prod).
|
|
1901
|
+
base_subdocs = dict(getattr(self, 'form_subdocuments', None) or {})
|
|
1902
|
+
base_subdocs['outcomes'] = {
|
|
1903
|
+
'form_subdocuments': {
|
|
1904
|
+
'': {
|
|
1905
|
+
'form_widget_args': {
|
|
1906
|
+
'site': {
|
|
1907
|
+
'placeholder':
|
|
1908
|
+
'{{ cmk_site }} — the exporting account\'s site',
|
|
1909
|
+
},
|
|
1910
|
+
},
|
|
1911
|
+
},
|
|
1912
|
+
},
|
|
1913
|
+
}
|
|
1914
|
+
self.form_subdocuments = base_subdocs
|
|
1891
1915
|
|
|
1892
1916
|
super().__init__(model, **kwargs)
|
|
1893
1917
|
|
|
@@ -277,6 +277,46 @@ def cli_netbox_vm_import(account, debug=False):
|
|
|
277
277
|
netbox_vm_import(account, debug)
|
|
278
278
|
register_cronjob("Netbox: Import VMs", netbox_vm_import)
|
|
279
279
|
#.
|
|
280
|
+
# .-- Command: Import DCIM Interfaces
|
|
281
|
+
def netbox_interface_import(account, debug=False):
|
|
282
|
+
"""Import DCIM Interfaces from Netbox"""
|
|
283
|
+
try:
|
|
284
|
+
syncer = SyncInterfaces(account)
|
|
285
|
+
syncer.debug = debug
|
|
286
|
+
syncer.import_interfaces()
|
|
287
|
+
except Exception as error_obj: # pylint: disable=broad-exception-caught
|
|
288
|
+
if debug:
|
|
289
|
+
raise
|
|
290
|
+
print(f'{cc.FAIL}Connection Error: {error_obj} {cc.ENDC}')
|
|
291
|
+
|
|
292
|
+
@cli_netbox.command('import_dcim_interfaces')
|
|
293
|
+
@click.argument("account")
|
|
294
|
+
@click.option("--debug", is_flag=True)
|
|
295
|
+
def cli_netbox_interface_import(account, debug=False):
|
|
296
|
+
"""Import Interfaces of Devices from Netbox"""
|
|
297
|
+
netbox_interface_import(account, debug)
|
|
298
|
+
register_cronjob("Netbox: Import DCIM Interfaces", netbox_interface_import)
|
|
299
|
+
#.
|
|
300
|
+
# .-- Command: Import Virtualization Interfaces
|
|
301
|
+
def netbox_virt_interface_import(account, debug=False):
|
|
302
|
+
"""Import Virtualization Interfaces from Netbox"""
|
|
303
|
+
try:
|
|
304
|
+
syncer = SyncVirtInterfaces(account)
|
|
305
|
+
syncer.debug = debug
|
|
306
|
+
syncer.import_interfaces(mode='virtualization')
|
|
307
|
+
except Exception as error_obj: # pylint: disable=broad-exception-caught
|
|
308
|
+
if debug:
|
|
309
|
+
raise
|
|
310
|
+
print(f'{cc.FAIL}Connection Error: {error_obj} {cc.ENDC}')
|
|
311
|
+
|
|
312
|
+
@cli_netbox.command('import_virt_interfaces')
|
|
313
|
+
@click.argument("account")
|
|
314
|
+
@click.option("--debug", is_flag=True)
|
|
315
|
+
def cli_netbox_virt_interface_import(account, debug=False):
|
|
316
|
+
"""Import Interfaces of Virtual Machines from Netbox"""
|
|
317
|
+
netbox_virt_interface_import(account, debug)
|
|
318
|
+
register_cronjob("Netbox: Import Virtualization Interfaces", netbox_virt_interface_import)
|
|
319
|
+
#.
|
|
280
320
|
# .-- Command: Export IPs
|
|
281
321
|
def netbox_ip_sync(account, debug=False, debug_rules=False):
|
|
282
322
|
"""Import Devices from Netbox"""
|