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.
Files changed (344) hide show
  1. {cmdbsyncer-4.2.0/cmdbsyncer.egg-info → cmdbsyncer-4.2.2}/PKG-INFO +1 -1
  2. cmdbsyncer-4.2.2/application/buildinfo.txt +1 -0
  3. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/v4.2.md +30 -0
  4. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/syncer_jinja.py +12 -0
  5. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/runner.py +24 -3
  6. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/site_syncer.py +1 -0
  7. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/__init__.py +4 -1
  8. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/admin_views.py +18 -26
  9. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/cmk_rules.py +23 -4
  10. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/groups.py +11 -1
  11. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/inits.py +38 -6
  12. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/models.py +1 -0
  13. cmdbsyncer-4.2.2/application/plugins/checkmk/rule_passwords.py +126 -0
  14. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_cmk_rules.py +15 -0
  15. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_groups.py +28 -0
  16. cmdbsyncer-4.2.2/application/plugins/checkmk/tests/test_rule_passwords.py +160 -0
  17. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/views.py +54 -21
  18. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/static/css/cmdbsyncer.css +28 -0
  19. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/checkmk_rule_project_import_cmk.html +38 -2
  20. cmdbsyncer-4.2.2/application/templates/admin/checkmk_test_folder_scope.html +219 -0
  21. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2/cmdbsyncer.egg-info}/PKG-INFO +1 -1
  22. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/cmdbsyncer.egg-info/SOURCES.txt +2 -0
  23. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/pyproject.toml +1 -1
  24. cmdbsyncer-4.2.0/application/buildinfo.txt +0 -1
  25. cmdbsyncer-4.2.0/application/templates/admin/checkmk_test_folder_scope.html +0 -101
  26. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/LICENSE +0 -0
  27. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/README.md +0 -0
  28. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/__init__.py +0 -0
  29. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/_version.py +0 -0
  30. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/api/__init__.py +0 -0
  31. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/api/inventory.py +0 -0
  32. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/api/objects.py +0 -0
  33. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/api/rules.py +0 -0
  34. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/api/syncer.py +0 -0
  35. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/api/views.py +0 -0
  36. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/auth/views.py +0 -0
  37. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/.pages +0 -0
  38. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/v3.10.md +0 -0
  39. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/v3.11.md +0 -0
  40. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/v3.12.md +0 -0
  41. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/v3.5.md +0 -0
  42. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/v3.7.md +0 -0
  43. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/v3.8.md +0 -0
  44. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/v3.9.md +0 -0
  45. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/v4.0.md +0 -0
  46. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/changelog/v4.1.md +0 -0
  47. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/cli.py +0 -0
  48. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/config.py +0 -0
  49. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/docu_links.py +0 -0
  50. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/enterprise.py +0 -0
  51. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/__init__.py +0 -0
  52. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/audit.py +0 -0
  53. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/cron.py +0 -0
  54. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/get_account.py +0 -0
  55. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/inventory.py +0 -0
  56. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/local_config_file.py +0 -0
  57. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/local_config_presets.py +0 -0
  58. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/mongo_keys.py +0 -0
  59. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/notification_channels.py +0 -0
  60. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/notification_dispatch.py +0 -0
  61. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/plugins.py +0 -0
  62. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/sates.py +0 -0
  63. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/sql.py +0 -0
  64. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/tablib_formater.py +0 -0
  65. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/tests/__init__.py +0 -0
  66. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/helpers/tests/test_sql.py +0 -0
  67. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/mcp_server.py +0 -0
  68. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/__init__.py +0 -0
  69. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/account.py +0 -0
  70. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/config.py +0 -0
  71. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/cron.py +0 -0
  72. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/field_approval.py +0 -0
  73. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/forms.py +0 -0
  74. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/host.py +0 -0
  75. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/host_inventory_tree.py +0 -0
  76. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/notification_channel.py +0 -0
  77. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/notification_rule.py +0 -0
  78. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/notification_state.py +0 -0
  79. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/saved_search.py +0 -0
  80. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/states.py +0 -0
  81. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/models/user.py +0 -0
  82. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/__init__.py +0 -0
  83. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/custom_attributes/models.py +0 -0
  84. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/custom_attributes/rules.py +0 -0
  85. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/custom_attributes/views.py +0 -0
  86. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/debug.py +0 -0
  87. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/email.py +0 -0
  88. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/inventory/__init__.py +0 -0
  89. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/log/log.py +0 -0
  90. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/log/models.py +0 -0
  91. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/log/views.py +0 -0
  92. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/plugin.py +0 -0
  93. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/rule/__init__.py +0 -0
  94. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/rule/filter.py +0 -0
  95. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/rule/match.py +0 -0
  96. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/rule/models.py +0 -0
  97. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/rule/rewrite.py +0 -0
  98. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/rule/rule.py +0 -0
  99. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/rule/views.py +0 -0
  100. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/search_parser.py +0 -0
  101. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/modules/statefile.py +0 -0
  102. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/notices/strict_certificate_verification.txt +0 -0
  103. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/__init__.py +0 -0
  104. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/__init__.py +0 -0
  105. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/admin_views.py +0 -0
  106. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/inventory.py +0 -0
  107. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/models.py +0 -0
  108. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/playbook_rules.py +0 -0
  109. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/plugin.json +0 -0
  110. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/rules.py +0 -0
  111. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/seed.py +0 -0
  112. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ansible/views.py +0 -0
  113. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/bmc_remedy/__init__.py +0 -0
  114. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/bmc_remedy/bmc_remedy.py +0 -0
  115. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/bmc_remedy/plugin.json +0 -0
  116. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/bi.py +0 -0
  117. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/cmk2.py +0 -0
  118. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/dcd.py +0 -0
  119. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/downtimes.py +0 -0
  120. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/helpers.py +0 -0
  121. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/import_v1.py +0 -0
  122. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/import_v2.py +0 -0
  123. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/inventorize.py +0 -0
  124. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/notification_rules.py +0 -0
  125. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/passwords.py +0 -0
  126. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/plugin.json +0 -0
  127. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/poolfolder.py +0 -0
  128. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/rules.py +0 -0
  129. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/sites.py +0 -0
  130. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/syncer.py +0 -0
  131. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tags.py +0 -0
  132. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/__init__.py +0 -0
  133. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_bi.py +0 -0
  134. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_cmk2.py +0 -0
  135. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_dcd.py +0 -0
  136. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_downtimes.py +0 -0
  137. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_helpers.py +0 -0
  138. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_import_v1.py +0 -0
  139. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_import_v2.py +0 -0
  140. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_inventorize.py +0 -0
  141. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_notification_rules.py +0 -0
  142. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_passwords.py +0 -0
  143. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_poolfolder.py +0 -0
  144. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_rules.py +0 -0
  145. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_sites.py +0 -0
  146. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_syncer.py +0 -0
  147. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_tags.py +0 -0
  148. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/tests/test_users.py +0 -0
  149. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/checkmk/users.py +0 -0
  150. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/cisco_dna/__init__.py +0 -0
  151. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/cisco_dna/plugin.json +0 -0
  152. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/cisco_dna/syncer.py +0 -0
  153. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/cron.py +0 -0
  154. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/csv/__init__.py +0 -0
  155. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/csv/csv.py +0 -0
  156. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/csv/plugin.json +0 -0
  157. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/file_requests.py +0 -0
  158. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/idoit/__init__.py +0 -0
  159. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/idoit/admin_views.py +0 -0
  160. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/idoit/models.py +0 -0
  161. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/idoit/plugin.json +0 -0
  162. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/idoit/rules.py +0 -0
  163. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/idoit/syncer.py +0 -0
  164. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/idoit/views.py +0 -0
  165. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jdisc/__init__.py +0 -0
  166. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jdisc/applications.py +0 -0
  167. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jdisc/devices.py +0 -0
  168. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jdisc/executables.py +0 -0
  169. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jdisc/jdisc.py +0 -0
  170. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jdisc/plugin.json +0 -0
  171. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira/__init__.py +0 -0
  172. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira/jira.py +0 -0
  173. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira/plugin.json +0 -0
  174. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira_cloud/__init__.py +0 -0
  175. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira_cloud/admin_views.py +0 -0
  176. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira_cloud/export.py +0 -0
  177. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira_cloud/jira_cloud.py +0 -0
  178. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira_cloud/models.py +0 -0
  179. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira_cloud/plugin.json +0 -0
  180. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira_cloud/rules.py +0 -0
  181. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira_cloud/schema_sync.py +0 -0
  182. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/jira_cloud/views.py +0 -0
  183. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/json/__init__.py +0 -0
  184. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/json/json.py +0 -0
  185. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/json/plugin.json +0 -0
  186. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ldap/__init__.py +0 -0
  187. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ldap/ldap.py +0 -0
  188. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/ldap/plugin.json +0 -0
  189. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/maintenance/__init__.py +0 -0
  190. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/maintenance/plugin.json +0 -0
  191. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/mssql/__init__.py +0 -0
  192. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/mssql/plugin.json +0 -0
  193. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/mysql/__init__.py +0 -0
  194. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/mysql/mysql.py +0 -0
  195. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/mysql/plugin.json +0 -0
  196. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/__init__.py +0 -0
  197. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/admin_views.py +0 -0
  198. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/cluster.py +0 -0
  199. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/contacts.py +0 -0
  200. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/dataflow.py +0 -0
  201. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/devices.py +0 -0
  202. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/interfaces.py +0 -0
  203. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/ips.py +0 -0
  204. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/models.py +0 -0
  205. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/netbox.py +0 -0
  206. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/networks.py +0 -0
  207. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/plugin.json +0 -0
  208. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/prefixes.py +0 -0
  209. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/rules.py +0 -0
  210. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/tests/__init__.py +0 -0
  211. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/tests/test_import_filter.py +0 -0
  212. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/views.py +0 -0
  213. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/netbox/virtualmachines.py +0 -0
  214. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/prtg/__init__.py +0 -0
  215. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/prtg/plugin.json +0 -0
  216. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/prtg/prtg.py +0 -0
  217. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/pyodbc/__init__.py +0 -0
  218. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/pyodbc/plugin.json +0 -0
  219. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/pyodbc/pyodbc.py +0 -0
  220. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rest/__init__.py +0 -0
  221. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rest/plugin.json +0 -0
  222. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rest/rest.py +0 -0
  223. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rules/__init__.py +0 -0
  224. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rules/admin_views.py +0 -0
  225. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rules/autorules.py +0 -0
  226. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rules/models.py +0 -0
  227. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rules/plugin.json +0 -0
  228. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rules/rule_definitions.py +0 -0
  229. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rules/rule_import_export.py +0 -0
  230. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/rules/views.py +0 -0
  231. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/syncer_shell.py +0 -0
  232. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/vmware/__init__.py +0 -0
  233. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/vmware/admin_views.py +0 -0
  234. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/vmware/custom_attributes.py +0 -0
  235. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/vmware/models.py +0 -0
  236. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/vmware/plugin.json +0 -0
  237. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/vmware/rules.py +0 -0
  238. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/vmware/views.py +0 -0
  239. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/vmware/vmware.py +0 -0
  240. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/yml/__init__.py +0 -0
  241. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/yml/plugin.json +0 -0
  242. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins/yml/yml.py +0 -0
  243. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/plugins_cli.py +0 -0
  244. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/static/cmdbsyncer_mark.png +0 -0
  245. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/static/favicon.png +0 -0
  246. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/static/js/main.js +0 -0
  247. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/static/logo_white.png +0 -0
  248. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/_brand.html +0 -0
  249. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/_theme.html +0 -0
  250. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/_host_tabs.html +0 -0
  251. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/account_pick_type.html +0 -0
  252. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/ansible_playbook_run.html +0 -0
  253. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/ansible_project_detail.html +0 -0
  254. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/ansible_rule_list.html +0 -0
  255. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/ansible_run_details.html +0 -0
  256. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/bulk_label_form.html +0 -0
  257. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/changelog_archive.html +0 -0
  258. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/checkmk_rule_mngmt_list.html +0 -0
  259. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/checkmk_rule_project_edit.html +0 -0
  260. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/checkmk_rule_project_import.html +0 -0
  261. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/checkmk_rule_project_overview.html +0 -0
  262. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/checkmk_settings_list.html +0 -0
  263. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/copy_as_new_form.html +0 -0
  264. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/data_quality.html +0 -0
  265. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/file/list.html +0 -0
  266. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/file/modals/form.html +0 -0
  267. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/host_details.html +0 -0
  268. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/host_edit.html +0 -0
  269. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/host_inventory_tree.html +0 -0
  270. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/host_list.html +0 -0
  271. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/host_relations_graph.html +0 -0
  272. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/host_timeline.html +0 -0
  273. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/index.html +0 -0
  274. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/local_config_editor.html +0 -0
  275. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/master.html +0 -0
  276. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/model/clone_confirm.html +0 -0
  277. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/model/inline_list_base.html +0 -0
  278. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/object_list.html +0 -0
  279. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/set_cmk_version_form.html +0 -0
  280. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/admin/set_template_form.html +0 -0
  281. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/base.html +0 -0
  282. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/change_password.html +0 -0
  283. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/debug.html +0 -0
  284. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/debug_host.html +0 -0
  285. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/email/newuser.html +0 -0
  286. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/email/notification.html +0 -0
  287. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/email/resetpassword.html +0 -0
  288. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/formular.html +0 -0
  289. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/license_info.html +0 -0
  290. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/login.html +0 -0
  291. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/logout_confirm.html +0 -0
  292. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/request_password.html +0 -0
  293. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/set_2fa.html +0 -0
  294. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/templates/set_theme.html +0 -0
  295. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/themes/dracula.css +0 -0
  296. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/themes/gruvbox-dark.css +0 -0
  297. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/themes/gruvbox-light.css +0 -0
  298. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/themes/nord.css +0 -0
  299. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/themes_registry.py +0 -0
  300. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/_form_fields.py +0 -0
  301. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/_form_sections.py +0 -0
  302. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/account.py +0 -0
  303. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/config.py +0 -0
  304. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/cron.py +0 -0
  305. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/data_quality.py +0 -0
  306. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/default.py +0 -0
  307. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/field_approval.py +0 -0
  308. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/fileadmin.py +0 -0
  309. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/host.py +0 -0
  310. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/host_filters.py +0 -0
  311. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/host_renderers.py +0 -0
  312. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/host_widgets.py +0 -0
  313. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/license.py +0 -0
  314. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/notification_channel.py +0 -0
  315. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/notification_rule.py +0 -0
  316. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/saved_search.py +0 -0
  317. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/application/views/user.py +0 -0
  318. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/cmdbsyncer.egg-info/dependency_links.txt +0 -0
  319. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/cmdbsyncer.egg-info/entry_points.txt +0 -0
  320. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/cmdbsyncer.egg-info/requires.txt +0 -0
  321. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/cmdbsyncer.egg-info/top_level.txt +0 -0
  322. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/requirements-ansible-windows.txt +0 -0
  323. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/requirements-ansible.txt +0 -0
  324. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/requirements-extras.txt +0 -0
  325. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/requirements.txt +0 -0
  326. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/setup.cfg +0 -0
  327. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/syncerapi/__init__.py +0 -0
  328. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/syncerapi/v1/__init__.py +0 -0
  329. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/syncerapi/v1/core/__init__.py +0 -0
  330. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/syncerapi/v1/inventory/__init__.py +0 -0
  331. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/syncerapi/v1/rest/__init__.py +0 -0
  332. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_account_macro.py +0 -0
  333. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_api.py +0 -0
  334. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_api_csrf_invariant.py +0 -0
  335. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_default_view.py +0 -0
  336. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_mongo_keys.py +0 -0
  337. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_plugin.py +0 -0
  338. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_plugin_ssti.py +0 -0
  339. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_plugins_cli.py +0 -0
  340. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_rule.py +0 -0
  341. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_rule_filename_detect.py +0 -0
  342. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_rule_match.py +0 -0
  343. {cmdbsyncer-4.2.0 → cmdbsyncer-4.2.2}/tests/test_search_parser.py +0 -0
  344. {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.0
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. Prefer an explicit config /
96
- env override, then PATH, then the repo-root wrapper that sits next to
97
- the `application` package (mirrors the legacy `ansible/inventory` shim).
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
- import_project_rules_from_folder(project, account, folder, recursive, debug)
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(normalize_cmk_folder(outcome.folder))
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(normalize_cmk_folder(param))
121
+ folders.add(scope_folder(param))
103
122
 
104
123
  for pool in CheckmkFolderPool.objects():
105
124
  if pool.folder_name:
106
- folders.add(normalize_cmk_folder(pool.folder_name))
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
- for db_host in Host.get_export_hosts():
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
- log.log(message, source="cmk_project_rule_import",
414
- details=[('account', account), ('folder', folder),
415
- ('recursive', str(recursive)),
416
- ('imported', str(imported))])
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
- print(f'C{ColorCodes.FAIL}MK Connection Error: {error_obj} {ColorCodes.ENDC}')
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
- return 0
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)