cmdbsyncer 4.2.0__tar.gz → 4.2.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.2.0/cmdbsyncer.egg-info → cmdbsyncer-4.2.2}/PKG-INFO +1 -1
- cmdbsyncer-4.2.2/application/buildinfo.txt +1 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/v4.2.md +30 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/syncer_jinja.py +12 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/runner.py +24 -3
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/site_syncer.py +1 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/__init__.py +4 -1
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/admin_views.py +18 -26
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/cmk_rules.py +23 -4
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/groups.py +11 -1
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/inits.py +38 -6
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/models.py +1 -0
- cmdbsyncer-4.2.2/application/plugins/checkmk/rule_passwords.py +126 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_cmk_rules.py +15 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_groups.py +28 -0
- cmdbsyncer-4.2.2/application/plugins/checkmk/tests/test_rule_passwords.py +160 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/views.py +54 -21
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/static/css/cmdbsyncer.css +28 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/checkmk_rule_project_import_cmk.html +38 -2
- cmdbsyncer-4.2.2/application/templates/admin/checkmk_test_folder_scope.html +219 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2/cmdbsyncer.egg-info}/PKG-INFO +1 -1
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/cmdbsyncer.egg-info/SOURCES.txt +2 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/pyproject.toml +1 -1
- cmdbsyncer-4.2.0/application/buildinfo.txt +0 -1
- cmdbsyncer-4.2.0/application/templates/admin/checkmk_test_folder_scope.html +0 -101
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/LICENSE +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/README.md +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/_version.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/api/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/api/inventory.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/api/objects.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/api/rules.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/api/syncer.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/api/views.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/auth/views.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/.pages +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/v3.10.md +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/v3.11.md +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/v3.12.md +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/v3.5.md +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/v3.7.md +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/v3.8.md +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/v3.9.md +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/v4.0.md +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/v4.1.md +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/cli.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/config.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/docu_links.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/enterprise.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/audit.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/cron.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/get_account.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/inventory.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/local_config_file.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/local_config_presets.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/mongo_keys.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/notification_channels.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/notification_dispatch.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/plugins.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/sates.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/sql.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/tablib_formater.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/tests/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/tests/test_sql.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/mcp_server.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/account.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/config.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/cron.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/field_approval.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/forms.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/host.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/host_inventory_tree.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/notification_channel.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/notification_rule.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/notification_state.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/saved_search.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/states.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/user.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/custom_attributes/models.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/custom_attributes/rules.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/custom_attributes/views.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/debug.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/email.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/inventory/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/log/log.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/log/models.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/log/views.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/plugin.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/rule/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/rule/filter.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/rule/match.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/rule/models.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/rule/rewrite.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/rule/rule.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/rule/views.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/search_parser.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/statefile.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/notices/strict_certificate_verification.txt +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/admin_views.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/inventory.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/models.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/playbook_rules.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/plugin.json +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/rules.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/seed.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/views.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/bmc_remedy/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/bmc_remedy/bmc_remedy.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/bmc_remedy/plugin.json +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/bi.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/cmk2.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/dcd.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/downtimes.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/helpers.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/import_v1.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/import_v2.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/inventorize.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/notification_rules.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/passwords.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/plugin.json +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/poolfolder.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/rules.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/sites.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/syncer.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tags.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_bi.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_cmk2.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_dcd.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_downtimes.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_helpers.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_import_v1.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_import_v2.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_inventorize.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_notification_rules.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_passwords.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_poolfolder.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_rules.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_sites.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_syncer.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_tags.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_users.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/users.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/cisco_dna/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/cisco_dna/plugin.json +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/cisco_dna/syncer.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/cron.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/csv/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/csv/csv.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/csv/plugin.json +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/file_requests.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/idoit/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/idoit/admin_views.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/idoit/models.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/idoit/plugin.json +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/idoit/rules.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/idoit/syncer.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/idoit/views.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jdisc/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jdisc/applications.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jdisc/devices.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jdisc/executables.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jdisc/jdisc.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jdisc/plugin.json +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira/jira.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira/plugin.json +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira_cloud/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira_cloud/admin_views.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira_cloud/export.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira_cloud/jira_cloud.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira_cloud/models.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira_cloud/plugin.json +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira_cloud/rules.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira_cloud/schema_sync.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira_cloud/views.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/json/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/json/json.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/json/plugin.json +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ldap/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ldap/ldap.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ldap/plugin.json +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/maintenance/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/maintenance/plugin.json +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/mssql/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/mssql/plugin.json +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/mysql/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/mysql/mysql.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/mysql/plugin.json +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/admin_views.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/cluster.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/contacts.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/dataflow.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/devices.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/interfaces.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/ips.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/models.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/netbox.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/networks.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/plugin.json +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/prefixes.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/rules.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/tests/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/tests/test_import_filter.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/views.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/virtualmachines.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/prtg/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/prtg/plugin.json +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/prtg/prtg.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/pyodbc/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/pyodbc/plugin.json +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/pyodbc/pyodbc.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rest/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rest/plugin.json +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rest/rest.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rules/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rules/admin_views.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rules/autorules.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rules/models.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rules/plugin.json +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rules/rule_definitions.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rules/rule_import_export.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rules/views.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/syncer_shell.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/vmware/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/vmware/admin_views.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/vmware/custom_attributes.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/vmware/models.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/vmware/plugin.json +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/vmware/rules.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/vmware/views.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/vmware/vmware.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/yml/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/yml/plugin.json +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/yml/yml.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins_cli.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/static/cmdbsyncer_mark.png +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/static/favicon.png +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/static/js/main.js +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/static/logo_white.png +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/_brand.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/_theme.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/_host_tabs.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/account_pick_type.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/ansible_playbook_run.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/ansible_project_detail.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/ansible_rule_list.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/ansible_run_details.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/bulk_label_form.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/changelog_archive.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/checkmk_rule_mngmt_list.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/checkmk_rule_project_edit.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/checkmk_rule_project_import.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/checkmk_rule_project_overview.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/checkmk_settings_list.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/copy_as_new_form.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/data_quality.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/file/list.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/file/modals/form.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/host_details.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/host_edit.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/host_inventory_tree.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/host_list.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/host_relations_graph.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/host_timeline.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/index.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/local_config_editor.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/master.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/model/clone_confirm.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/model/inline_list_base.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/object_list.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/set_cmk_version_form.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/set_template_form.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/base.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/change_password.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/debug.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/debug_host.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/email/newuser.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/email/notification.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/email/resetpassword.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/formular.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/license_info.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/login.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/logout_confirm.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/request_password.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/set_2fa.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/set_theme.html +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/themes/dracula.css +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/themes/gruvbox-dark.css +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/themes/gruvbox-light.css +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/themes/nord.css +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/themes_registry.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/_form_fields.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/_form_sections.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/account.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/config.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/cron.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/data_quality.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/default.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/field_approval.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/fileadmin.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/host.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/host_filters.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/host_renderers.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/host_widgets.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/license.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/notification_channel.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/notification_rule.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/saved_search.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/user.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/cmdbsyncer.egg-info/dependency_links.txt +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/cmdbsyncer.egg-info/entry_points.txt +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/cmdbsyncer.egg-info/requires.txt +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/cmdbsyncer.egg-info/top_level.txt +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/requirements-ansible-windows.txt +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/requirements-ansible.txt +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/requirements-extras.txt +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/requirements.txt +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/setup.cfg +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/syncerapi/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/syncerapi/v1/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/syncerapi/v1/core/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/syncerapi/v1/inventory/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/syncerapi/v1/rest/__init__.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_account_macro.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_api.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_api_csrf_invariant.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_default_view.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_mongo_keys.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_plugin.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_plugin_ssti.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_plugins_cli.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_rule.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_rule_filename_detect.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_rule_match.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_search_parser.py +0 -0
- {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.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.2.
|
|
3
|
+
Version: 4.2.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-07-14T11:01:00Z
|
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Version 4.2
|
|
2
2
|
|
|
3
|
+
## Version 4.2.2
|
|
4
|
+
|
|
5
|
+
### Ansible
|
|
6
|
+
- 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
|
|
7
|
+
- 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)
|
|
8
|
+
- 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
|
|
9
|
+
|
|
10
|
+
### Checkmk
|
|
11
|
+
- 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
|
|
12
|
+
- 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
|
|
13
|
+
- 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
|
|
14
|
+
- 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
|
|
15
|
+
- 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
|
|
16
|
+
- 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
|
|
17
|
+
|
|
18
|
+
### Interface
|
|
19
|
+
- 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
|
|
20
|
+
|
|
21
|
+
## Version 4.2.1
|
|
22
|
+
|
|
23
|
+
### Ansible
|
|
24
|
+
- 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
|
|
25
|
+
|
|
26
|
+
### Setup
|
|
27
|
+
- 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)
|
|
28
|
+
|
|
29
|
+
### Checkmk
|
|
30
|
+
- 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"
|
|
31
|
+
- 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
|
|
32
|
+
|
|
3
33
|
## Version 4.2.0
|
|
4
34
|
|
|
5
35
|
### Hosts
|
|
@@ -48,6 +48,17 @@ def _cmk_cleanup_hostname(value):
|
|
|
48
48
|
return _cleanup(value)
|
|
49
49
|
|
|
50
50
|
|
|
51
|
+
def _cmk_password(name):
|
|
52
|
+
"""
|
|
53
|
+
Resolve a syncer Checkmk Password name to its password-store ident
|
|
54
|
+
(``cmdbsyncer_<id>``) so rules can reference a stored secret instead of an
|
|
55
|
+
inlined one. Lazily imported to avoid circular imports.
|
|
56
|
+
"""
|
|
57
|
+
from application.plugins.checkmk.rule_passwords import password_ident
|
|
58
|
+
|
|
59
|
+
return password_ident(name)
|
|
60
|
+
|
|
61
|
+
|
|
51
62
|
def syncer_eval(string, default=None):
|
|
52
63
|
"""
|
|
53
64
|
Evals given object
|
|
@@ -139,6 +150,7 @@ _GLOBALS = {
|
|
|
139
150
|
'merge_list_of_dicts': merge_list_of_dicts,
|
|
140
151
|
'cmk_cleanup_tag_id': _cmk_cleanup_tag_id,
|
|
141
152
|
'cmk_cleanup_hostname': _cmk_cleanup_hostname,
|
|
153
|
+
'cmk_password': _cmk_password,
|
|
142
154
|
'get_ip_network': get_ip_network,
|
|
143
155
|
'get_ip4_interface': get_ip_interface,
|
|
144
156
|
'get_ip_interface': get_ip_interface,
|
|
@@ -92,13 +92,23 @@ def _cmdbsyncer_bin() -> str:
|
|
|
92
92
|
|
|
93
93
|
The plugin defaults to a bare `cmdbsyncer` and only looks on $PATH,
|
|
94
94
|
which fails when the app runs from a source checkout / container where
|
|
95
|
-
no `cmdbsyncer` console script is on PATH.
|
|
96
|
-
env override, then
|
|
97
|
-
|
|
95
|
+
no `cmdbsyncer` console script is on PATH. Resolution order: explicit
|
|
96
|
+
config / env override, then the console script inside the running
|
|
97
|
+
interpreter's venv, then PATH, then the repo-root wrapper that sits next
|
|
98
|
+
to the `application` package (mirrors the legacy `ansible/inventory` shim).
|
|
98
99
|
"""
|
|
99
100
|
override = app.config.get('CMDBSYNCER_BIN') or os.environ.get('CMDBSYNCER_BIN')
|
|
100
101
|
if override:
|
|
101
102
|
return override
|
|
103
|
+
# Console script installed alongside the running interpreter (e.g.
|
|
104
|
+
# `/opt/cmdbsyncer/venv/bin/cmdbsyncer`). Checked before $PATH because a
|
|
105
|
+
# mod_wsgi / gunicorn worker typically runs with a PATH that omits the
|
|
106
|
+
# venv's bin dir, so shutil.which() finds nothing and we would fall
|
|
107
|
+
# through to the bare name — which the inventory plugin then fails to
|
|
108
|
+
# spawn with "cmdbsyncer binary not found ('cmdbsyncer')".
|
|
109
|
+
venv_bin = Path(sys.prefix) / 'bin' / 'cmdbsyncer'
|
|
110
|
+
if venv_bin.is_file():
|
|
111
|
+
return str(venv_bin)
|
|
102
112
|
on_path = shutil.which('cmdbsyncer')
|
|
103
113
|
if on_path:
|
|
104
114
|
return on_path
|
|
@@ -340,6 +350,17 @@ def _execute(stats_id, run_params: dict, cwd: Path, provider: str):
|
|
|
340
350
|
run_tmp = tempfile.mkdtemp(prefix='cmdbsyncer-ansible-')
|
|
341
351
|
env['ANSIBLE_LOCAL_TEMP'] = run_tmp
|
|
342
352
|
env['HOME'] = run_tmp
|
|
353
|
+
# ANSIBLE_LOCAL_TEMP / $HOME only cover the controller-side scratch
|
|
354
|
+
# dir. A task delegated to localhost (delegate_to: localhost) runs
|
|
355
|
+
# over the *local* connection, whose remote_tmp still defaults to
|
|
356
|
+
# ``~/.ansible/tmp`` — and that ``~`` is expanded via the passwd
|
|
357
|
+
# database (the web user's non-writable home, e.g.
|
|
358
|
+
# ``/usr/share/httpd``), ignoring $HOME. That makes such tasks abort
|
|
359
|
+
# "Failed to create temporary directory". Pin remote_tmp to the
|
|
360
|
+
# writable per-run dir (a literal /tmp path, no ``~`` to expand) so
|
|
361
|
+
# local-delegated tasks work; real SSH hosts just create this path
|
|
362
|
+
# under their own /tmp.
|
|
363
|
+
env['ANSIBLE_REMOTE_TEMP'] = run_tmp
|
|
343
364
|
inventory_path = _write_run_inventory_spec(
|
|
344
365
|
run_tmp, provider, env['CMDBSYNCER_INVENTORY_MODE'],
|
|
345
366
|
cmdbsyncer_bin=_cmdbsyncer_bin(),
|
|
@@ -47,6 +47,7 @@ class SyncSites(Plugin):
|
|
|
47
47
|
'cmk_edition': site.settings_master.cmk_edition,
|
|
48
48
|
'cmk_version': site.settings_master.cmk_version,
|
|
49
49
|
'cmk_version_filename': filename,
|
|
50
|
+
'installation_staging_path': site.settings_master.installation_staging_path or '',
|
|
50
51
|
'subscription_username': site.settings_master.subscription_username,
|
|
51
52
|
'subscription_password': site.settings_master.subscription_password,
|
|
52
53
|
'cmk_user': cmk_user,
|
|
@@ -442,7 +442,10 @@ def cli_import_project_rules(project, account, folder, recursive, debug):
|
|
|
442
442
|
account (string): Checkmk account to read the rules from
|
|
443
443
|
folder (string): Checkmk folder to import rules from
|
|
444
444
|
"""
|
|
445
|
-
|
|
445
|
+
try:
|
|
446
|
+
import_project_rules_from_folder(project, account, folder, recursive, debug)
|
|
447
|
+
except CmkException as error_obj:
|
|
448
|
+
print(f'{ColorCodes.FAIL}Checkmk Error: {error_obj}{ColorCodes.ENDC}')
|
|
446
449
|
|
|
447
450
|
#.
|
|
448
451
|
# .-- Command: Export Group
|
|
@@ -72,6 +72,15 @@ def register_admin_views(admin):
|
|
|
72
72
|
menu_icon_value='fa-filter',
|
|
73
73
|
)
|
|
74
74
|
)
|
|
75
|
+
admin.add_view(
|
|
76
|
+
CheckmkTestFolderScopeView(
|
|
77
|
+
name="Limit Host Export to Folders",
|
|
78
|
+
category="Checkmk",
|
|
79
|
+
endpoint="checkmk_test_folder_scope",
|
|
80
|
+
menu_icon_type='fa',
|
|
81
|
+
menu_icon_value='fa-folder-open',
|
|
82
|
+
)
|
|
83
|
+
)
|
|
75
84
|
admin.add_view(
|
|
76
85
|
CheckmkRuleView(
|
|
77
86
|
CheckmkRule,
|
|
@@ -99,6 +108,15 @@ def register_admin_views(admin):
|
|
|
99
108
|
menu_icon_value='fa-cogs',
|
|
100
109
|
)
|
|
101
110
|
)
|
|
111
|
+
admin.add_view(
|
|
112
|
+
CheckmkRuleProjectView(
|
|
113
|
+
CheckmkRuleProject,
|
|
114
|
+
name="Setup Rule Projects",
|
|
115
|
+
category="Checkmk",
|
|
116
|
+
menu_icon_type='fa',
|
|
117
|
+
menu_icon_value='fa-cubes',
|
|
118
|
+
)
|
|
119
|
+
)
|
|
102
120
|
admin.add_view(
|
|
103
121
|
CheckmkTagMngmtView(
|
|
104
122
|
CheckmkTagMngmt,
|
|
@@ -183,32 +201,6 @@ def register_admin_views(admin):
|
|
|
183
201
|
menu_icon_value='fa-folder-open',
|
|
184
202
|
)
|
|
185
203
|
)
|
|
186
|
-
admin.add_sub_category(name="Export Scoping", parent_name="Checkmk")
|
|
187
|
-
# add_sub_category does not apply category_icon_classes to sub-categories,
|
|
188
|
-
# so set the menu icon directly on the created SubMenuCategory.
|
|
189
|
-
_ttp_category = admin.get_category_menu_item("Export Scoping")
|
|
190
|
-
if _ttp_category is not None:
|
|
191
|
-
_ttp_category.icon_type = 'fa'
|
|
192
|
-
_ttp_category.icon_value = 'fa-filter'
|
|
193
|
-
admin.add_view(
|
|
194
|
-
CheckmkRuleProjectView(
|
|
195
|
-
CheckmkRuleProject,
|
|
196
|
-
name="Setup Rule Projects",
|
|
197
|
-
category="Export Scoping",
|
|
198
|
-
menu_icon_type='fa',
|
|
199
|
-
menu_icon_value='fa-cubes',
|
|
200
|
-
)
|
|
201
|
-
)
|
|
202
|
-
admin.add_view(
|
|
203
|
-
CheckmkTestFolderScopeView(
|
|
204
|
-
name="Limit Host Export to Folders",
|
|
205
|
-
category="Export Scoping",
|
|
206
|
-
endpoint="checkmk_test_folder_scope",
|
|
207
|
-
menu_icon_type='fa',
|
|
208
|
-
menu_icon_value='fa-folder-open',
|
|
209
|
-
)
|
|
210
|
-
)
|
|
211
|
-
|
|
212
204
|
admin.add_view(
|
|
213
205
|
CheckmkInventorizeAttributesView(
|
|
214
206
|
CheckmkInventorizeAttributes,
|
|
@@ -11,7 +11,7 @@ from pprint import pformat
|
|
|
11
11
|
|
|
12
12
|
from rich.progress import Progress, SpinnerColumn, TimeElapsedColumn, MofNCompleteColumn
|
|
13
13
|
|
|
14
|
-
from application import logger
|
|
14
|
+
from application import app, logger
|
|
15
15
|
from application.models.host import Host
|
|
16
16
|
from application.plugins.checkmk.cmk2 import CmkException, CMK2
|
|
17
17
|
from application.helpers.syncer_jinja import render_jinja, get_list
|
|
@@ -44,6 +44,25 @@ def normalize_cmk_folder(folder):
|
|
|
44
44
|
return normalize_folder(folder)
|
|
45
45
|
|
|
46
46
|
|
|
47
|
+
def scope_folder(folder):
|
|
48
|
+
"""
|
|
49
|
+
Normalise a folder for a folder-scope selection.
|
|
50
|
+
|
|
51
|
+
Like :func:`normalize_cmk_folder`, but also prefixes a leading ``/`` and
|
|
52
|
+
lowercases the path when ``CMK_LOWERCASE_FOLDERNAMES`` is on. Checkmk's API
|
|
53
|
+
folder names are always lowercase, and the export side (``rules.py``) writes
|
|
54
|
+
them that way, so a picked or typed folder compares equal to the folder a
|
|
55
|
+
host actually lands in.
|
|
56
|
+
"""
|
|
57
|
+
folder = (folder or '').strip()
|
|
58
|
+
if folder and not folder.startswith('/'):
|
|
59
|
+
folder = '/' + folder
|
|
60
|
+
folder = normalize_cmk_folder(folder)
|
|
61
|
+
if app.config['CMK_LOWERCASE_FOLDERNAMES']:
|
|
62
|
+
folder = folder.lower()
|
|
63
|
+
return folder
|
|
64
|
+
|
|
65
|
+
|
|
47
66
|
def folder_in_scope(rule_folder, target_folder, recursive=False):
|
|
48
67
|
"""
|
|
49
68
|
True when ``rule_folder`` should be imported for ``target_folder``.
|
|
@@ -90,7 +109,7 @@ def iter_rule_folders():
|
|
|
90
109
|
for rule in CheckmkRuleMngmt.objects():
|
|
91
110
|
for outcome in rule.outcomes:
|
|
92
111
|
if outcome.folder and '{{' not in outcome.folder:
|
|
93
|
-
folders.add(
|
|
112
|
+
folders.add(scope_folder(outcome.folder))
|
|
94
113
|
|
|
95
114
|
for rule in CheckmkRule.objects(enabled=True):
|
|
96
115
|
for outcome in rule.outcomes:
|
|
@@ -99,11 +118,11 @@ def iter_rule_folders():
|
|
|
99
118
|
param = (outcome.action_param or '').strip()
|
|
100
119
|
if not param or '{{' in param:
|
|
101
120
|
continue
|
|
102
|
-
folders.add(
|
|
121
|
+
folders.add(scope_folder(param))
|
|
103
122
|
|
|
104
123
|
for pool in CheckmkFolderPool.objects():
|
|
105
124
|
if pool.folder_name:
|
|
106
|
-
folders.add(
|
|
125
|
+
folders.add(scope_folder(pool.folder_name))
|
|
107
126
|
|
|
108
127
|
return sorted(folders)
|
|
109
128
|
|
|
@@ -39,7 +39,17 @@ class CheckmkGroupSync(CMK2):
|
|
|
39
39
|
"""
|
|
40
40
|
collection_keys = {}
|
|
41
41
|
collection_values = {}
|
|
42
|
-
|
|
42
|
+
# Default stays host-only (is_object=True documents, e.g. shadow
|
|
43
|
+
# hosts, are excluded). If the account — or a child account — defines
|
|
44
|
+
# an object filter for this export, honor it so the configured
|
|
45
|
+
# object types (shadow hosts, CMDB objects, …) feed the groups too,
|
|
46
|
+
# consistent with the rules/tags export.
|
|
47
|
+
object_filter = self.config['settings'].get(self.name, {}).get('filter')
|
|
48
|
+
if object_filter:
|
|
49
|
+
db_hosts = Host.objects_by_filter(object_filter)
|
|
50
|
+
else:
|
|
51
|
+
db_hosts = Host.get_export_hosts()
|
|
52
|
+
for db_host in db_hosts:
|
|
43
53
|
if attributes := self.get_attributes(db_host, 'cmk_conf'):
|
|
44
54
|
for key, value in attributes['all'].items():
|
|
45
55
|
key, value = str(key), str(value)
|
|
@@ -14,6 +14,11 @@ from application.plugins.checkmk.rules import CheckmkRulesetRule, DefaultRule
|
|
|
14
14
|
from application.plugins.checkmk.inventorize import InventorizeHosts
|
|
15
15
|
from application.plugins.checkmk.dcd import CheckmkDCDRuleSync
|
|
16
16
|
from application.plugins.checkmk.passwords import CheckmkPasswordSync
|
|
17
|
+
from application.plugins.checkmk.rule_passwords import (
|
|
18
|
+
rewrite_explicit_passwords,
|
|
19
|
+
preserve_password_macros,
|
|
20
|
+
referenced_password_names,
|
|
21
|
+
)
|
|
17
22
|
from application.plugins.checkmk.groups import CheckmkGroupSync
|
|
18
23
|
from application.plugins.checkmk.users import CheckmkUserSync
|
|
19
24
|
from application.plugins.checkmk.bi import BI
|
|
@@ -384,6 +389,7 @@ def import_project_rules_from_folder(project_name, account, folder, # pylint: d
|
|
|
384
389
|
found = syncer.fetch_rules_in_folder(folder, recursive=recursive)
|
|
385
390
|
|
|
386
391
|
imported = 0
|
|
392
|
+
password_hints = set()
|
|
387
393
|
for entry in found:
|
|
388
394
|
cmk_id = entry.get('cmk_id')
|
|
389
395
|
if not cmk_id:
|
|
@@ -402,21 +408,47 @@ def import_project_rules_from_folder(project_name, account, folder, # pylint: d
|
|
|
402
408
|
f"Imported from Checkmk account '{account}', "
|
|
403
409
|
f"folder '{folder}' (rule {cmk_id})")
|
|
404
410
|
outcome = entry['outcome']
|
|
411
|
+
# Checkmk masks explicit passwords as '******' on read, so a rule
|
|
412
|
+
# imported here can't carry a usable secret. Rewrite each into a
|
|
413
|
+
# syncer password-store reference (a cmk_password macro); on a
|
|
414
|
+
# re-import keep the macro already on the rule so a renamed one is
|
|
415
|
+
# not reverted to its default hint.
|
|
416
|
+
new_value, hints = rewrite_explicit_passwords(
|
|
417
|
+
outcome.get('value_template', ''))
|
|
418
|
+
if hints:
|
|
419
|
+
old_outcome = rule.outcomes[0] if rule.outcomes else None
|
|
420
|
+
if old_outcome is not None:
|
|
421
|
+
new_value = preserve_password_macros(
|
|
422
|
+
old_outcome.value_template, new_value)
|
|
423
|
+
outcome['value_template'] = new_value
|
|
424
|
+
password_hints.update(referenced_password_names(new_value))
|
|
405
425
|
rule.outcomes = [RuleMngmtOutcome(**outcome)]
|
|
406
426
|
rule.primary_ruleset = outcome.get('ruleset', '')
|
|
407
427
|
rule.save()
|
|
408
428
|
imported += 1
|
|
409
429
|
|
|
430
|
+
if password_hints:
|
|
431
|
+
hint_list = ', '.join(sorted(password_hints))
|
|
432
|
+
print(f"{ColorCodes.WARNING} * Rules reference password store "
|
|
433
|
+
f"entries: {hint_list}. Create matching Checkmk Passwords in "
|
|
434
|
+
f"the syncer and run 'checkmk export_passwords <account>' so "
|
|
435
|
+
f"the reference resolves in the target Checkmk.{ColorCodes.ENDC}")
|
|
436
|
+
|
|
410
437
|
message = (f"Imported {imported} rule(s) from Checkmk folder "
|
|
411
438
|
f"'{folder}' into project '{project_name}'")
|
|
412
439
|
print(f'{ColorCodes.OKGREEN}{message}{ColorCodes.ENDC}')
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
440
|
+
details = [('account', account), ('folder', folder),
|
|
441
|
+
('recursive', str(recursive)),
|
|
442
|
+
('imported', str(imported))]
|
|
443
|
+
if password_hints:
|
|
444
|
+
details.append(('password_store_entries',
|
|
445
|
+
', '.join(sorted(password_hints))))
|
|
446
|
+
log.log(message, source="cmk_project_rule_import", details=details)
|
|
417
447
|
return imported
|
|
418
448
|
except CmkException as error_obj:
|
|
419
|
-
|
|
449
|
+
# Record the failure, then re-raise so callers can surface it.
|
|
450
|
+
# Swallowing it into "return 0" made a wrong-credentials error
|
|
451
|
+
# (401) look identical to an empty folder in the web UI.
|
|
420
452
|
if syncer is not None:
|
|
421
453
|
syncer.record_exception(error_obj)
|
|
422
454
|
else:
|
|
@@ -424,7 +456,7 @@ def import_project_rules_from_folder(project_name, account, folder, # pylint: d
|
|
|
424
456
|
f"{account} not started",
|
|
425
457
|
source="cmk_project_rule_import",
|
|
426
458
|
details=[('error', str(error_obj))])
|
|
427
|
-
|
|
459
|
+
raise
|
|
428
460
|
#.
|
|
429
461
|
# .-- Export Notification Rules
|
|
430
462
|
def export_notifications(account, debug=False):
|
|
@@ -505,6 +505,7 @@ class CheckmkSettings(db.Document):
|
|
|
505
505
|
cmk_version = db.StringField()
|
|
506
506
|
cmk_edition = db.StringField(choices=editions)
|
|
507
507
|
cmk_version_filename = db.StringField()
|
|
508
|
+
installation_staging_path = db.StringField()
|
|
508
509
|
inital_password = db.StringField()
|
|
509
510
|
|
|
510
511
|
subscription_username = db.StringField()
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Bridge Checkmk rule secrets to the syncer's own Checkmk password store.
|
|
3
|
+
|
|
4
|
+
Checkmk masks an ``explicit_password`` in a rule value as ``******`` on every
|
|
5
|
+
read, so a rule imported from one Checkmk instance carries no usable secret and
|
|
6
|
+
would overwrite the target's password with ``******`` on deploy. Instead we
|
|
7
|
+
rewrite every ``explicit_password`` into a ``stored_password`` reference backed
|
|
8
|
+
by a syncer :class:`CheckmkPassword`. The reference is a Jinja macro
|
|
9
|
+
``{{ cmk_password("name") }}`` that resolves to the entry's stable ident
|
|
10
|
+
``cmdbsyncer_<id>`` at export time — the same ident the password export writes
|
|
11
|
+
into every Checkmk instance, so a rule deployed to test and prod resolves each
|
|
12
|
+
instance's own stored secret.
|
|
13
|
+
"""
|
|
14
|
+
import ast
|
|
15
|
+
import re
|
|
16
|
+
|
|
17
|
+
from application import logger
|
|
18
|
+
|
|
19
|
+
# Checkmk 2.3+ tags password values in a rule's ``value_raw`` as
|
|
20
|
+
# ``('cmk_postprocessed', <kind>, (<ident>, <value>))``. ``explicit_password``
|
|
21
|
+
# inlines the (masked) secret; ``stored_password`` only references a password
|
|
22
|
+
# store ident and carries no secret.
|
|
23
|
+
POSTPROCESSED = 'cmk_postprocessed'
|
|
24
|
+
EXPLICIT_PASSWORD = 'explicit_password'
|
|
25
|
+
STORED_PASSWORD = 'stored_password'
|
|
26
|
+
|
|
27
|
+
# ``{{ cmk_password("name") }}`` — tolerant of surrounding whitespace and either
|
|
28
|
+
# quote style, matching how the macro may be hand-edited on the rule.
|
|
29
|
+
_MACRO_RE = re.compile(r'\{\{\s*cmk_password\([^)]*\)\s*\}\}')
|
|
30
|
+
_MACRO_NAME_RE = re.compile(r'cmk_password\(\s*["\']([^"\']+)["\']\s*\)')
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def password_ident(name):
|
|
34
|
+
"""
|
|
35
|
+
Resolve a syncer password name to its Checkmk password-store ident.
|
|
36
|
+
|
|
37
|
+
Returns ``cmdbsyncer_<id>`` for the :class:`CheckmkPassword` named ``name``.
|
|
38
|
+
A missing name is logged and resolved to a clearly-invalid ident so only the
|
|
39
|
+
one affected rule fails to deploy (Checkmk rejects the unknown reference)
|
|
40
|
+
instead of aborting the whole export.
|
|
41
|
+
"""
|
|
42
|
+
from .models import CheckmkPassword # pylint: disable=import-outside-toplevel
|
|
43
|
+
entry = CheckmkPassword.objects(name=name).first()
|
|
44
|
+
if not entry:
|
|
45
|
+
logger.error(
|
|
46
|
+
"cmk_password(%r): no Checkmk Password with that name in the syncer",
|
|
47
|
+
name)
|
|
48
|
+
return f"cmdbsyncer_missing_{name}"
|
|
49
|
+
return f"cmdbsyncer_{entry.id}"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _macro_for(hint):
|
|
53
|
+
"""Build the ``{{ cmk_password(...) }}`` macro for a default name hint."""
|
|
54
|
+
return '{{ cmk_password("%s") }}' % (hint or 'password')
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def rewrite_explicit_passwords(value_raw):
|
|
58
|
+
"""
|
|
59
|
+
Rewrite every ``explicit_password`` in a rule ``value_raw`` string into a
|
|
60
|
+
``stored_password`` password-store reference.
|
|
61
|
+
|
|
62
|
+
Each ``('cmk_postprocessed', 'explicit_password', (<uuid>, '******'))``
|
|
63
|
+
becomes ``('cmk_postprocessed', 'stored_password', ('{{ cmk_password("<hint>") }}', ''))``
|
|
64
|
+
where ``<hint>`` defaults to the value's field name (e.g. ``secret``). The
|
|
65
|
+
hint is only a starting name — rename the macro on the rule and create a
|
|
66
|
+
matching syncer Checkmk Password.
|
|
67
|
+
|
|
68
|
+
Returns ``(new_value_raw, hints)`` where ``hints`` is the list of default
|
|
69
|
+
names inserted (empty, and ``value_raw`` returned unchanged, when the value
|
|
70
|
+
holds no explicit password or cannot be parsed).
|
|
71
|
+
"""
|
|
72
|
+
if not isinstance(value_raw, str) or EXPLICIT_PASSWORD not in value_raw:
|
|
73
|
+
return value_raw, []
|
|
74
|
+
try:
|
|
75
|
+
parsed = ast.literal_eval(value_raw)
|
|
76
|
+
except (ValueError, SyntaxError):
|
|
77
|
+
return value_raw, []
|
|
78
|
+
|
|
79
|
+
hints = []
|
|
80
|
+
|
|
81
|
+
def convert(obj, key=None):
|
|
82
|
+
if isinstance(obj, tuple):
|
|
83
|
+
if len(obj) == 3 and obj[0] == POSTPROCESSED \
|
|
84
|
+
and obj[1] == EXPLICIT_PASSWORD:
|
|
85
|
+
hint = key if isinstance(key, str) and key else 'password'
|
|
86
|
+
hints.append(hint)
|
|
87
|
+
return (POSTPROCESSED, STORED_PASSWORD, (_macro_for(hint), ''))
|
|
88
|
+
return tuple(convert(item, key) for item in obj)
|
|
89
|
+
if isinstance(obj, list):
|
|
90
|
+
return [convert(item, key) for item in obj]
|
|
91
|
+
if isinstance(obj, dict):
|
|
92
|
+
return {k: convert(v, k) for k, v in obj.items()}
|
|
93
|
+
return obj
|
|
94
|
+
|
|
95
|
+
new = convert(parsed)
|
|
96
|
+
if not hints:
|
|
97
|
+
return value_raw, []
|
|
98
|
+
return repr(new), hints
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def preserve_password_macros(old_value, new_value):
|
|
102
|
+
"""
|
|
103
|
+
Carry a rule's existing ``cmk_password`` macros over into a freshly
|
|
104
|
+
re-imported value, so a re-run of the folder import does not revert a
|
|
105
|
+
renamed macro back to its default hint.
|
|
106
|
+
|
|
107
|
+
Positional: when ``old_value`` and ``new_value`` hold the same number of
|
|
108
|
+
macros (the usual case — the rule's password fields did not change), the
|
|
109
|
+
i-th new macro is replaced by the i-th old one. On any mismatch the new
|
|
110
|
+
value is kept unchanged.
|
|
111
|
+
"""
|
|
112
|
+
if not old_value:
|
|
113
|
+
return new_value
|
|
114
|
+
old_macros = _MACRO_RE.findall(old_value)
|
|
115
|
+
new_macros = _MACRO_RE.findall(new_value)
|
|
116
|
+
if not old_macros or len(old_macros) != len(new_macros):
|
|
117
|
+
return new_value
|
|
118
|
+
carried = iter(old_macros)
|
|
119
|
+
return _MACRO_RE.sub(lambda _match: next(carried), new_value)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def referenced_password_names(text):
|
|
123
|
+
"""Return the set of syncer password names a value references via macro."""
|
|
124
|
+
if not text:
|
|
125
|
+
return set()
|
|
126
|
+
return set(_MACRO_NAME_RE.findall(text))
|
|
@@ -863,6 +863,21 @@ class TestImportProjectRules(unittest.TestCase):
|
|
|
863
863
|
instance.fetch_rules_in_folder.assert_called_once_with(
|
|
864
864
|
'/folder', recursive=True)
|
|
865
865
|
|
|
866
|
+
def test_cmk_error_propagates_and_is_recorded(self):
|
|
867
|
+
"""A Checkmk error (e.g. wrong credentials -> 401) must NOT be
|
|
868
|
+
swallowed into a "0 imported" result — it has to reach the caller so
|
|
869
|
+
the CLI/web UI can surface it instead of showing an empty import."""
|
|
870
|
+
from application.plugins.checkmk.cmk2 import CmkException # noqa: E402 pylint: disable=import-outside-toplevel
|
|
871
|
+
with patch.object(inits, 'CheckmkRuleProject') as proj, \
|
|
872
|
+
patch.object(inits, 'CheckmkRuleSync') as sync:
|
|
873
|
+
proj.objects.return_value.first.return_value = SimpleNamespace(name='P')
|
|
874
|
+
instance = sync.return_value
|
|
875
|
+
instance.fetch_rules_in_folder.side_effect = \
|
|
876
|
+
CmkException('Unauthorized Wrong credentials (Bearer header)')
|
|
877
|
+
with self.assertRaises(CmkException):
|
|
878
|
+
inits.import_project_rules_from_folder('P', 'acc', '/folder')
|
|
879
|
+
instance.record_exception.assert_called_once()
|
|
880
|
+
|
|
866
881
|
|
|
867
882
|
class TestProjectsForAccount(unittest.TestCase):
|
|
868
883
|
"""inits.projects_for_account account-filter selection."""
|
|
@@ -154,6 +154,34 @@ class TestCheckmkGroupSync(unittest.TestCase):
|
|
|
154
154
|
self.assertEqual(keys, {})
|
|
155
155
|
self.assertEqual(values, {})
|
|
156
156
|
|
|
157
|
+
@patch('application.plugins.checkmk.groups.Host')
|
|
158
|
+
def test_parse_attributes_default_is_host_only(self, mock_host):
|
|
159
|
+
"""Without an account object filter the default stays host-only."""
|
|
160
|
+
self.sync.name = 'Checkmk: Export Groups'
|
|
161
|
+
self.sync.config['settings'] = {}
|
|
162
|
+
mock_host.get_export_hosts.return_value = []
|
|
163
|
+
|
|
164
|
+
self.sync.parse_attributes()
|
|
165
|
+
|
|
166
|
+
mock_host.get_export_hosts.assert_called_once()
|
|
167
|
+
mock_host.objects_by_filter.assert_not_called()
|
|
168
|
+
|
|
169
|
+
@patch('application.plugins.checkmk.groups.Host')
|
|
170
|
+
def test_parse_attributes_uses_account_object_filter(self, mock_host):
|
|
171
|
+
"""An account (or child account) object filter opts objects/shadow
|
|
172
|
+
hosts into the group calculation instead of the host-only default."""
|
|
173
|
+
self.sync.name = 'Checkmk: Export Groups'
|
|
174
|
+
self.sync.config['settings'] = {
|
|
175
|
+
'Checkmk: Export Groups': {'filter': ['host', 'shadow_host']},
|
|
176
|
+
}
|
|
177
|
+
mock_host.objects_by_filter.return_value = []
|
|
178
|
+
|
|
179
|
+
self.sync.parse_attributes()
|
|
180
|
+
|
|
181
|
+
mock_host.objects_by_filter.assert_called_once_with(
|
|
182
|
+
['host', 'shadow_host'])
|
|
183
|
+
mock_host.get_export_hosts.assert_not_called()
|
|
184
|
+
|
|
157
185
|
|
|
158
186
|
if __name__ == '__main__':
|
|
159
187
|
unittest.main(verbosity=2)
|