cmdbsyncer 4.2.2__tar.gz → 4.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (344) hide show
  1. {cmdbsyncer-4.2.2/cmdbsyncer.egg-info → cmdbsyncer-4.2.3}/PKG-INFO +1 -1
  2. cmdbsyncer-4.2.3/application/buildinfo.txt +1 -0
  3. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/changelog/v4.2.md +6 -0
  4. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/cmk_rules.py +31 -0
  5. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/inits.py +7 -1
  6. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/models.py +8 -1
  7. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/syncer.py +2 -19
  8. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/tests/test_cmk_rules.py +82 -0
  9. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/tests/test_rule_passwords.py +48 -0
  10. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/views.py +88 -20
  11. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/checkmk_rule_project_import.html +4 -3
  12. cmdbsyncer-4.2.3/application/templates/admin/checkmk_rule_project_list.html +25 -0
  13. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/checkmk_rule_project_overview.html +69 -0
  14. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3/cmdbsyncer.egg-info}/PKG-INFO +1 -1
  15. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/cmdbsyncer.egg-info/SOURCES.txt +1 -0
  16. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/pyproject.toml +1 -1
  17. cmdbsyncer-4.2.2/application/buildinfo.txt +0 -1
  18. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/LICENSE +0 -0
  19. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/README.md +0 -0
  20. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/__init__.py +0 -0
  21. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/_version.py +0 -0
  22. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/api/__init__.py +0 -0
  23. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/api/inventory.py +0 -0
  24. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/api/objects.py +0 -0
  25. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/api/rules.py +0 -0
  26. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/api/syncer.py +0 -0
  27. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/api/views.py +0 -0
  28. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/auth/views.py +0 -0
  29. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/changelog/.pages +0 -0
  30. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/changelog/v3.10.md +0 -0
  31. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/changelog/v3.11.md +0 -0
  32. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/changelog/v3.12.md +0 -0
  33. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/changelog/v3.5.md +0 -0
  34. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/changelog/v3.7.md +0 -0
  35. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/changelog/v3.8.md +0 -0
  36. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/changelog/v3.9.md +0 -0
  37. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/changelog/v4.0.md +0 -0
  38. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/changelog/v4.1.md +0 -0
  39. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/cli.py +0 -0
  40. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/config.py +0 -0
  41. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/docu_links.py +0 -0
  42. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/enterprise.py +0 -0
  43. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/helpers/__init__.py +0 -0
  44. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/helpers/audit.py +0 -0
  45. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/helpers/cron.py +0 -0
  46. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/helpers/get_account.py +0 -0
  47. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/helpers/inventory.py +0 -0
  48. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/helpers/local_config_file.py +0 -0
  49. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/helpers/local_config_presets.py +0 -0
  50. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/helpers/mongo_keys.py +0 -0
  51. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/helpers/notification_channels.py +0 -0
  52. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/helpers/notification_dispatch.py +0 -0
  53. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/helpers/plugins.py +0 -0
  54. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/helpers/sates.py +0 -0
  55. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/helpers/sql.py +0 -0
  56. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/helpers/syncer_jinja.py +0 -0
  57. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/helpers/tablib_formater.py +0 -0
  58. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/helpers/tests/__init__.py +0 -0
  59. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/helpers/tests/test_sql.py +0 -0
  60. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/mcp_server.py +0 -0
  61. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/models/__init__.py +0 -0
  62. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/models/account.py +0 -0
  63. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/models/config.py +0 -0
  64. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/models/cron.py +0 -0
  65. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/models/field_approval.py +0 -0
  66. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/models/forms.py +0 -0
  67. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/models/host.py +0 -0
  68. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/models/host_inventory_tree.py +0 -0
  69. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/models/notification_channel.py +0 -0
  70. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/models/notification_rule.py +0 -0
  71. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/models/notification_state.py +0 -0
  72. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/models/saved_search.py +0 -0
  73. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/models/states.py +0 -0
  74. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/models/user.py +0 -0
  75. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/modules/__init__.py +0 -0
  76. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/modules/custom_attributes/models.py +0 -0
  77. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/modules/custom_attributes/rules.py +0 -0
  78. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/modules/custom_attributes/views.py +0 -0
  79. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/modules/debug.py +0 -0
  80. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/modules/email.py +0 -0
  81. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/modules/inventory/__init__.py +0 -0
  82. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/modules/log/log.py +0 -0
  83. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/modules/log/models.py +0 -0
  84. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/modules/log/views.py +0 -0
  85. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/modules/plugin.py +0 -0
  86. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/modules/rule/__init__.py +0 -0
  87. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/modules/rule/filter.py +0 -0
  88. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/modules/rule/match.py +0 -0
  89. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/modules/rule/models.py +0 -0
  90. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/modules/rule/rewrite.py +0 -0
  91. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/modules/rule/rule.py +0 -0
  92. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/modules/rule/views.py +0 -0
  93. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/modules/search_parser.py +0 -0
  94. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/modules/statefile.py +0 -0
  95. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/notices/strict_certificate_verification.txt +0 -0
  96. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/__init__.py +0 -0
  97. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/ansible/__init__.py +0 -0
  98. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/ansible/admin_views.py +0 -0
  99. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/ansible/inventory.py +0 -0
  100. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/ansible/models.py +0 -0
  101. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/ansible/playbook_rules.py +0 -0
  102. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/ansible/plugin.json +0 -0
  103. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/ansible/rules.py +0 -0
  104. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/ansible/runner.py +0 -0
  105. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/ansible/seed.py +0 -0
  106. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/ansible/site_syncer.py +0 -0
  107. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/ansible/views.py +0 -0
  108. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/bmc_remedy/__init__.py +0 -0
  109. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/bmc_remedy/bmc_remedy.py +0 -0
  110. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/bmc_remedy/plugin.json +0 -0
  111. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/__init__.py +0 -0
  112. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/admin_views.py +0 -0
  113. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/bi.py +0 -0
  114. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/cmk2.py +0 -0
  115. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/dcd.py +0 -0
  116. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/downtimes.py +0 -0
  117. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/groups.py +0 -0
  118. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/helpers.py +0 -0
  119. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/import_v1.py +0 -0
  120. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/import_v2.py +0 -0
  121. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/inventorize.py +0 -0
  122. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/notification_rules.py +0 -0
  123. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/passwords.py +0 -0
  124. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/plugin.json +0 -0
  125. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/poolfolder.py +0 -0
  126. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/rule_passwords.py +0 -0
  127. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/rules.py +0 -0
  128. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/sites.py +0 -0
  129. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/tags.py +0 -0
  130. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/tests/__init__.py +0 -0
  131. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/tests/test_bi.py +0 -0
  132. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/tests/test_cmk2.py +0 -0
  133. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/tests/test_dcd.py +0 -0
  134. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/tests/test_downtimes.py +0 -0
  135. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/tests/test_groups.py +0 -0
  136. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/tests/test_helpers.py +0 -0
  137. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/tests/test_import_v1.py +0 -0
  138. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/tests/test_import_v2.py +0 -0
  139. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/tests/test_inventorize.py +0 -0
  140. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/tests/test_notification_rules.py +0 -0
  141. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/tests/test_passwords.py +0 -0
  142. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/tests/test_poolfolder.py +0 -0
  143. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/tests/test_rules.py +0 -0
  144. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/tests/test_sites.py +0 -0
  145. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/tests/test_syncer.py +0 -0
  146. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/tests/test_tags.py +0 -0
  147. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/tests/test_users.py +0 -0
  148. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/checkmk/users.py +0 -0
  149. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/cisco_dna/__init__.py +0 -0
  150. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/cisco_dna/plugin.json +0 -0
  151. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/cisco_dna/syncer.py +0 -0
  152. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/cron.py +0 -0
  153. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/csv/__init__.py +0 -0
  154. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/csv/csv.py +0 -0
  155. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/csv/plugin.json +0 -0
  156. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/file_requests.py +0 -0
  157. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/idoit/__init__.py +0 -0
  158. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/idoit/admin_views.py +0 -0
  159. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/idoit/models.py +0 -0
  160. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/idoit/plugin.json +0 -0
  161. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/idoit/rules.py +0 -0
  162. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/idoit/syncer.py +0 -0
  163. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/idoit/views.py +0 -0
  164. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/jdisc/__init__.py +0 -0
  165. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/jdisc/applications.py +0 -0
  166. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/jdisc/devices.py +0 -0
  167. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/jdisc/executables.py +0 -0
  168. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/jdisc/jdisc.py +0 -0
  169. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/jdisc/plugin.json +0 -0
  170. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/jira/__init__.py +0 -0
  171. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/jira/jira.py +0 -0
  172. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/jira/plugin.json +0 -0
  173. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/jira_cloud/__init__.py +0 -0
  174. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/jira_cloud/admin_views.py +0 -0
  175. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/jira_cloud/export.py +0 -0
  176. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/jira_cloud/jira_cloud.py +0 -0
  177. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/jira_cloud/models.py +0 -0
  178. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/jira_cloud/plugin.json +0 -0
  179. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/jira_cloud/rules.py +0 -0
  180. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/jira_cloud/schema_sync.py +0 -0
  181. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/jira_cloud/views.py +0 -0
  182. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/json/__init__.py +0 -0
  183. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/json/json.py +0 -0
  184. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/json/plugin.json +0 -0
  185. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/ldap/__init__.py +0 -0
  186. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/ldap/ldap.py +0 -0
  187. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/ldap/plugin.json +0 -0
  188. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/maintenance/__init__.py +0 -0
  189. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/maintenance/plugin.json +0 -0
  190. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/mssql/__init__.py +0 -0
  191. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/mssql/plugin.json +0 -0
  192. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/mysql/__init__.py +0 -0
  193. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/mysql/mysql.py +0 -0
  194. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/mysql/plugin.json +0 -0
  195. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/netbox/__init__.py +0 -0
  196. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/netbox/admin_views.py +0 -0
  197. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/netbox/cluster.py +0 -0
  198. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/netbox/contacts.py +0 -0
  199. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/netbox/dataflow.py +0 -0
  200. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/netbox/devices.py +0 -0
  201. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/netbox/interfaces.py +0 -0
  202. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/netbox/ips.py +0 -0
  203. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/netbox/models.py +0 -0
  204. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/netbox/netbox.py +0 -0
  205. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/netbox/networks.py +0 -0
  206. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/netbox/plugin.json +0 -0
  207. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/netbox/prefixes.py +0 -0
  208. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/netbox/rules.py +0 -0
  209. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/netbox/tests/__init__.py +0 -0
  210. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/netbox/tests/test_import_filter.py +0 -0
  211. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/netbox/views.py +0 -0
  212. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/netbox/virtualmachines.py +0 -0
  213. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/prtg/__init__.py +0 -0
  214. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/prtg/plugin.json +0 -0
  215. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/prtg/prtg.py +0 -0
  216. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/pyodbc/__init__.py +0 -0
  217. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/pyodbc/plugin.json +0 -0
  218. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/pyodbc/pyodbc.py +0 -0
  219. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/rest/__init__.py +0 -0
  220. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/rest/plugin.json +0 -0
  221. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/rest/rest.py +0 -0
  222. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/rules/__init__.py +0 -0
  223. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/rules/admin_views.py +0 -0
  224. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/rules/autorules.py +0 -0
  225. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/rules/models.py +0 -0
  226. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/rules/plugin.json +0 -0
  227. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/rules/rule_definitions.py +0 -0
  228. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/rules/rule_import_export.py +0 -0
  229. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/rules/views.py +0 -0
  230. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/syncer_shell.py +0 -0
  231. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/vmware/__init__.py +0 -0
  232. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/vmware/admin_views.py +0 -0
  233. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/vmware/custom_attributes.py +0 -0
  234. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/vmware/models.py +0 -0
  235. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/vmware/plugin.json +0 -0
  236. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/vmware/rules.py +0 -0
  237. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/vmware/views.py +0 -0
  238. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/vmware/vmware.py +0 -0
  239. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/yml/__init__.py +0 -0
  240. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/yml/plugin.json +0 -0
  241. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins/yml/yml.py +0 -0
  242. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/plugins_cli.py +0 -0
  243. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/static/cmdbsyncer_mark.png +0 -0
  244. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/static/css/cmdbsyncer.css +0 -0
  245. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/static/favicon.png +0 -0
  246. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/static/js/main.js +0 -0
  247. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/static/logo_white.png +0 -0
  248. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/_brand.html +0 -0
  249. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/_theme.html +0 -0
  250. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/_host_tabs.html +0 -0
  251. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/account_pick_type.html +0 -0
  252. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/ansible_playbook_run.html +0 -0
  253. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/ansible_project_detail.html +0 -0
  254. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/ansible_rule_list.html +0 -0
  255. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/ansible_run_details.html +0 -0
  256. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/bulk_label_form.html +0 -0
  257. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/changelog_archive.html +0 -0
  258. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/checkmk_rule_mngmt_list.html +0 -0
  259. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/checkmk_rule_project_edit.html +0 -0
  260. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/checkmk_rule_project_import_cmk.html +0 -0
  261. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/checkmk_settings_list.html +0 -0
  262. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/checkmk_test_folder_scope.html +0 -0
  263. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/copy_as_new_form.html +0 -0
  264. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/data_quality.html +0 -0
  265. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/file/list.html +0 -0
  266. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/file/modals/form.html +0 -0
  267. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/host_details.html +0 -0
  268. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/host_edit.html +0 -0
  269. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/host_inventory_tree.html +0 -0
  270. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/host_list.html +0 -0
  271. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/host_relations_graph.html +0 -0
  272. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/host_timeline.html +0 -0
  273. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/index.html +0 -0
  274. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/local_config_editor.html +0 -0
  275. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/master.html +0 -0
  276. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/model/clone_confirm.html +0 -0
  277. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/model/inline_list_base.html +0 -0
  278. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/object_list.html +0 -0
  279. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/set_cmk_version_form.html +0 -0
  280. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/admin/set_template_form.html +0 -0
  281. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/base.html +0 -0
  282. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/change_password.html +0 -0
  283. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/debug.html +0 -0
  284. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/debug_host.html +0 -0
  285. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/email/newuser.html +0 -0
  286. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/email/notification.html +0 -0
  287. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/email/resetpassword.html +0 -0
  288. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/formular.html +0 -0
  289. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/license_info.html +0 -0
  290. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/login.html +0 -0
  291. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/logout_confirm.html +0 -0
  292. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/request_password.html +0 -0
  293. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/set_2fa.html +0 -0
  294. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/templates/set_theme.html +0 -0
  295. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/themes/dracula.css +0 -0
  296. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/themes/gruvbox-dark.css +0 -0
  297. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/themes/gruvbox-light.css +0 -0
  298. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/themes/nord.css +0 -0
  299. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/themes_registry.py +0 -0
  300. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/views/_form_fields.py +0 -0
  301. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/views/_form_sections.py +0 -0
  302. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/views/account.py +0 -0
  303. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/views/config.py +0 -0
  304. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/views/cron.py +0 -0
  305. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/views/data_quality.py +0 -0
  306. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/views/default.py +0 -0
  307. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/views/field_approval.py +0 -0
  308. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/views/fileadmin.py +0 -0
  309. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/views/host.py +0 -0
  310. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/views/host_filters.py +0 -0
  311. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/views/host_renderers.py +0 -0
  312. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/views/host_widgets.py +0 -0
  313. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/views/license.py +0 -0
  314. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/views/notification_channel.py +0 -0
  315. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/views/notification_rule.py +0 -0
  316. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/views/saved_search.py +0 -0
  317. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/application/views/user.py +0 -0
  318. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/cmdbsyncer.egg-info/dependency_links.txt +0 -0
  319. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/cmdbsyncer.egg-info/entry_points.txt +0 -0
  320. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/cmdbsyncer.egg-info/requires.txt +0 -0
  321. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/cmdbsyncer.egg-info/top_level.txt +0 -0
  322. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/requirements-ansible-windows.txt +0 -0
  323. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/requirements-ansible.txt +0 -0
  324. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/requirements-extras.txt +0 -0
  325. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/requirements.txt +0 -0
  326. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/setup.cfg +0 -0
  327. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/syncerapi/__init__.py +0 -0
  328. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/syncerapi/v1/__init__.py +0 -0
  329. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/syncerapi/v1/core/__init__.py +0 -0
  330. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/syncerapi/v1/inventory/__init__.py +0 -0
  331. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/syncerapi/v1/rest/__init__.py +0 -0
  332. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/tests/test_account_macro.py +0 -0
  333. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/tests/test_api.py +0 -0
  334. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/tests/test_api_csrf_invariant.py +0 -0
  335. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/tests/test_default_view.py +0 -0
  336. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/tests/test_mongo_keys.py +0 -0
  337. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/tests/test_plugin.py +0 -0
  338. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/tests/test_plugin_ssti.py +0 -0
  339. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/tests/test_plugins_cli.py +0 -0
  340. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/tests/test_rule.py +0 -0
  341. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/tests/test_rule_filename_detect.py +0 -0
  342. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/tests/test_rule_match.py +0 -0
  343. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/tests/test_search_parser.py +0 -0
  344. {cmdbsyncer-4.2.2 → cmdbsyncer-4.2.3}/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.2
3
+ Version: 4.2.3
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-15T10:13:29Z
@@ -1,5 +1,11 @@
1
1
  # Version 4.2
2
2
 
3
+ ## Version 4.2.3
4
+
5
+ ### Checkmk
6
+ - FEAT: The Checkmk rule export now respects an account's folder scope ("Limit Host Export to Folders") — a scoped account only receives Setup rules whose target folder is in scope, just like the host export
7
+ - FEAT: DCD rules can be assigned to a Rule Project — they show on the project overview, follow the project's account filter on export (only exported to the accounts the project allows), and are included in the project's JSON export/import; the project list gains an "Import project from JSON" button
8
+
3
9
  ## Version 4.2.2
4
10
 
5
11
  ### Ansible
@@ -83,6 +83,31 @@ def folder_in_scope(rule_folder, target_folder, recursive=False):
83
83
  return rule_folder.startswith(target_folder + '/')
84
84
 
85
85
 
86
+ def folder_within_scope(folder, limits):
87
+ """
88
+ True when ``folder`` falls within an account's ``limit_by_folders`` scope.
89
+
90
+ ``limits`` is the raw comma-separated ``limit_by_folders`` value off the
91
+ account. An empty or missing scope means no restriction (always True).
92
+ Folders typed without a leading slash are tolerated, and the match is
93
+ recursive so selecting ``/test`` also covers ``/test/linux``. Shared by the
94
+ host export (which folder a host lands in) and the rule export (which folder
95
+ a Setup rule is placed in) so both honour the same scope.
96
+ """
97
+ allowed = []
98
+ for entry in (limits or '').split(','):
99
+ entry = entry.strip()
100
+ if not entry:
101
+ continue
102
+ if not entry.startswith('/'):
103
+ entry = '/' + entry
104
+ allowed.append(entry)
105
+ if not allowed:
106
+ return True
107
+ folder = folder or '/'
108
+ return any(folder_in_scope(folder, scope, recursive=True) for scope in allowed)
109
+
110
+
86
111
  def iter_rule_folders():
87
112
  """
88
113
  Collect the literal folders that the configured rules can place objects
@@ -758,6 +783,12 @@ class CheckmkRuleSync(CMK2):
758
783
  value = render_jinja(rule_params['value_template'], **context)
759
784
  rule_params['folder'] = normalize_folder(
760
785
  render_jinja(rule_params['folder'], **context))
786
+ # Respect the account's folder scope (limit_by_folders): a scoped
787
+ # account only receives rules whose target folder is in scope, just
788
+ # like the host export only pushes hosts of those folders.
789
+ if not folder_within_scope(
790
+ rule_params['folder'], self.config.get('limit_by_folders')):
791
+ return None
761
792
  rule_params['value'] = value
762
793
  del rule_params['value_template']
763
794
  rule_params['optimize'] = False
@@ -540,7 +540,13 @@ def export_dcd_rules(account, debug=False, debug_rules=False):
540
540
  Name overwrite
541
541
  """
542
542
  actions = ExportDCD(account)
543
- actions.rules = CheckmkDCDRule.objects(enabled=True)
543
+ # Honour each project's account filter (limit_by_accounts): a DCD rule
544
+ # assigned to a project is only exported to the accounts that project
545
+ # allows. Rules without a project stay global (exported everywhere),
546
+ # matching the Setup-rule export.
547
+ allowed_projects = [None, ''] + projects_for_account(account)
548
+ actions.rules = CheckmkDCDRule.objects(
549
+ enabled=True, project__in=allowed_projects)
544
550
 
545
551
  if not debug_rules:
546
552
  syncer = CheckmkDCDRuleSync(account)
@@ -690,12 +690,19 @@ class CheckmkDCDRule(db.Document):
690
690
  render_cmk_dcd_rule = db.StringField()
691
691
  last_match = db.BooleanField(default=False)
692
692
 
693
+ # Name of the CheckmkRuleProject this DCD rule belongs to (or empty).
694
+ # Referenced by name to match CheckmkRuleMngmt.project. A DCD rule assigned
695
+ # to a project follows that project's account filter (limit_by_accounts) on
696
+ # export, just like a Setup rule — it is only exported to the accounts the
697
+ # project allows. A rule without a project stays global.
698
+ project = db.StringField()
693
699
 
694
700
  enabled = db.BooleanField()
695
701
  sort_field = db.IntField(default=0)
696
702
 
697
703
  meta = {
698
- 'strict': False
704
+ 'strict': False,
705
+ 'indexes': ['project'],
699
706
  }
700
707
 
701
708
  #.
@@ -9,7 +9,7 @@ from rich.progress import Progress, SpinnerColumn, TimeElapsedColumn, MofNComple
9
9
  from application import app, logger, log, init_db
10
10
  from application.models.host import Host
11
11
  from application.plugins.checkmk.cmk2 import CMK2, CmkException
12
- from application.plugins.checkmk.cmk_rules import folder_in_scope
12
+ from application.plugins.checkmk.cmk_rules import folder_within_scope
13
13
  from application.modules.debug import ColorCodes as CC
14
14
 
15
15
 
@@ -349,25 +349,8 @@ class SyncCMK2(CMK2):
349
349
  Returns:
350
350
  bool: True if the host should be exported to this account.
351
351
  """
352
- limits = self.config.get('limit_by_folders')
353
- if not limits:
354
- return True
355
- # A folder entered without a leading slash (e.g. "test/linux" instead of
356
- # "/test/linux") would otherwise never match the slash-prefixed folder a
357
- # rule produces — normalise it so the scope works regardless of how it
358
- # was typed, on this page or directly in the account's custom fields.
359
- allowed = []
360
- for entry in limits.split(','):
361
- entry = entry.strip()
362
- if not entry:
363
- continue
364
- if not entry.startswith('/'):
365
- entry = '/' + entry
366
- allowed.append(entry)
367
- if not allowed:
368
- return True
369
352
  folder = next_actions.get('move_folder') or '/'
370
- return any(folder_in_scope(folder, scope, recursive=True) for scope in allowed)
353
+ return folder_within_scope(folder, self.config.get('limit_by_folders'))
371
354
 
372
355
  def handle_clusters(self):
373
356
  """
@@ -16,6 +16,7 @@ from application.plugins.checkmk.cmk_rules import (
16
16
  render_jinja_in_value,
17
17
  normalize_cmk_folder,
18
18
  folder_in_scope,
19
+ folder_within_scope,
19
20
  cmk_conditions_to_outcome,
20
21
  cmk_rule_to_outcome,
21
22
  CheckmkRuleSync,
@@ -210,6 +211,43 @@ class TestCheckmkRuleSync(unittest.TestCase):
210
211
  self.assertIn('host_label_groups', result['condition'])
211
212
  self.assertNotIn('service_labels', result['condition'])
212
213
 
214
+ @patch('application.plugins.checkmk.cmk_rules.render_jinja')
215
+ def test_folder_scope_skips_out_of_scope_rule(self, mock_render):
216
+ # A scoped account (limit_by_folders) drops a rule whose folder is not
217
+ # in scope — build returns None so the caller skips it.
218
+ mock_render.side_effect = lambda tpl, **kw: tpl
219
+ self.sync.config = {'limit_by_folders': '/test'}
220
+ rule_params = {
221
+ 'value_template': "{'k': 'v'}", 'folder': '/prod', 'comment': 'c',
222
+ }
223
+ result = self.sync.build_condition_and_update_rule_params(
224
+ rule_params, {'all': {'HOSTNAME': 'h'}})
225
+ self.assertIsNone(result)
226
+
227
+ @patch('application.plugins.checkmk.cmk_rules.render_jinja')
228
+ def test_folder_scope_keeps_in_scope_rule(self, mock_render):
229
+ mock_render.side_effect = lambda tpl, **kw: tpl
230
+ self.sync.config = {'limit_by_folders': '/test'}
231
+ rule_params = {
232
+ 'value_template': "{'k': 'v'}", 'folder': '/test/linux',
233
+ 'comment': 'c',
234
+ }
235
+ result = self.sync.build_condition_and_update_rule_params(
236
+ rule_params, {'all': {'HOSTNAME': 'h'}})
237
+ self.assertIsNotNone(result)
238
+ self.assertEqual(result['folder'], '/test/linux')
239
+
240
+ @patch('application.plugins.checkmk.cmk_rules.render_jinja')
241
+ def test_no_folder_scope_keeps_rule(self, mock_render):
242
+ mock_render.side_effect = lambda tpl, **kw: tpl
243
+ # config without limit_by_folders (the setUp default) — no restriction.
244
+ rule_params = {
245
+ 'value_template': "{'k': 'v'}", 'folder': '/prod', 'comment': 'c',
246
+ }
247
+ result = self.sync.build_condition_and_update_rule_params(
248
+ rule_params, {'all': {'HOSTNAME': 'h'}})
249
+ self.assertIsNotNone(result)
250
+
213
251
  @patch('application.plugins.checkmk.cmk_rules.render_jinja')
214
252
  def test_build_condition_v22(self, mock_render):
215
253
  mock_render.side_effect = lambda tpl, **kw: tpl
@@ -624,6 +662,19 @@ class TestCmkFolderHelpers(unittest.TestCase):
624
662
  self.assertFalse(
625
663
  folder_in_scope('/server-old', '/server', recursive=True))
626
664
 
665
+ def test_within_scope_no_limit_allows_all(self):
666
+ self.assertTrue(folder_within_scope('/anything', ''))
667
+ self.assertTrue(folder_within_scope('/anything', None))
668
+
669
+ def test_within_scope_recursive_and_leading_slash_tolerant(self):
670
+ # scope typed without a leading slash still matches, recursively.
671
+ self.assertTrue(folder_within_scope('/test/linux', 'test'))
672
+ self.assertTrue(folder_within_scope('/test', '/test,/other'))
673
+
674
+ def test_within_scope_out_of_scope_folder(self):
675
+ self.assertFalse(folder_within_scope('/prod', '/test'))
676
+ self.assertFalse(folder_within_scope('/', '/test'))
677
+
627
678
 
628
679
  class TestCmkConditionReverse(unittest.TestCase):
629
680
  """cmk_conditions_to_outcome + cmk_rule_to_outcome (reverse of export)."""
@@ -898,5 +949,36 @@ class TestProjectsForAccount(unittest.TestCase):
898
949
  self.assertEqual(for_b, ['all', 'a_and_b', 'only_b'])
899
950
 
900
951
 
952
+ class TestExportDcdRulesProjectFilter(unittest.TestCase):
953
+ """export_dcd_rules restricts DCD rules by their project's account filter."""
954
+
955
+ def test_dcd_export_filters_by_project(self):
956
+ # DefaultRule stand-in (must be subclassable)
957
+ class _StubRule: # pylint: disable=too-few-public-methods
958
+ def __init__(self, account=None):
959
+ self.rules = None
960
+
961
+ # CheckmkDCDRuleSync stand-in
962
+ class _StubSync: # pylint: disable=too-few-public-methods
963
+ def __init__(self, account=False):
964
+ pass
965
+
966
+ def export_rules(self):
967
+ pass
968
+
969
+ with patch.object(inits, '_load_rules',
970
+ return_value={'rewrite': [], 'filter': []}), \
971
+ patch.object(inits, 'projects_for_account',
972
+ return_value=['proj_a']), \
973
+ patch.object(inits, 'DefaultRule', _StubRule), \
974
+ patch.object(inits, 'CheckmkDCDRuleSync', _StubSync), \
975
+ patch.object(inits, 'CheckmkDCDRule') as mock_dcd:
976
+ mock_dcd.objects.return_value = ['rule']
977
+ inits.export_dcd_rules('acc_a')
978
+ # Global (no project) rules plus the projects this account is allowed.
979
+ mock_dcd.objects.assert_called_once_with(
980
+ enabled=True, project__in=[None, '', 'proj_a'])
981
+
982
+
901
983
  if __name__ == '__main__':
902
984
  unittest.main(verbosity=2)
@@ -13,6 +13,7 @@ from application.plugins.checkmk.rule_passwords import (
13
13
  referenced_password_names,
14
14
  password_ident,
15
15
  )
16
+ from application.plugins.checkmk.cmk_rules import deep_compare, clean_postproccessed
16
17
 
17
18
  # The Azure special-agent value the user reported: one explicit_password
18
19
  # ('secret') plus an explicit_proxy that must be left untouched.
@@ -156,5 +157,52 @@ class TestPasswordIdent(unittest.TestCase):
156
157
  self.assertEqual(password_ident('nope'), 'cmdbsyncer_missing_nope')
157
158
 
158
159
 
160
+ class TestStoredPasswordIdempotency(unittest.TestCase):
161
+ """
162
+ A stored_password reference must round-trip through the rule comparison
163
+ without churn, so repeated rule exports don't endlessly update the rule.
164
+ Values here are already resolved (post-Jinja), matching what reaches
165
+ ``clean_rules`` as ``rule['value']`` vs Checkmk's ``value_raw``.
166
+ """
167
+
168
+ def _stored(self):
169
+ return {
170
+ 'user': 'svc',
171
+ 'password': ('cmk_postprocessed', 'stored_password',
172
+ ('cmdbsyncer_deadbeef', '')),
173
+ 'port': 443,
174
+ }
175
+
176
+ def test_repeat_export_no_churn(self):
177
+ # Checkmk stored exactly what we sent → next export is a full match.
178
+ self.assertTrue(deep_compare(self._stored(), self._stored()))
179
+
180
+ def test_tolerates_checkmk_schema_defaults(self):
181
+ # Checkmk enriches the stored value with defaults we didn't set.
182
+ cmk = self._stored()
183
+ cmk['tls'] = True
184
+ self.assertTrue(deep_compare(self._stored(), cmk))
185
+
186
+ def test_clean_postprocessed_leaves_stored_password(self):
187
+ # Unlike explicit_password, a stored_password tuple is not nulled out,
188
+ # so the ident stays comparable across reads.
189
+ cleaned = clean_postproccessed(self._stored())
190
+ self.assertEqual(
191
+ cleaned['password'],
192
+ ('cmk_postprocessed', 'stored_password', ('cmdbsyncer_deadbeef', '')))
193
+
194
+ def test_explicit_to_stored_is_one_update_then_stable(self):
195
+ # First export after converting an explicit rule differs (one PUT),
196
+ # afterwards Checkmk holds the stored form and it matches.
197
+ cmk_explicit = {
198
+ 'user': 'svc',
199
+ 'password': ('cmk_postprocessed', 'explicit_password',
200
+ ('cmdbsyncer_deadbeef', '******')),
201
+ 'port': 443,
202
+ }
203
+ self.assertFalse(deep_compare(self._stored(), cmk_explicit))
204
+ self.assertTrue(deep_compare(self._stored(), self._stored()))
205
+
206
+
159
207
  if __name__ == '__main__':
160
208
  unittest.main()
@@ -44,6 +44,7 @@ from .models import (
44
44
  CheckmkSettings,
45
45
  CheckmkRuleMngmt,
46
46
  CheckmkRuleProject,
47
+ CheckmkDCDRule,
47
48
  )
48
49
 
49
50
 
@@ -806,8 +807,17 @@ class CheckmkMngmtRuleView(RuleModelView):
806
807
 
807
808
 
808
809
  def _render_project_rule_count(_view, _context, model, _name):
809
- """List-column formatter: how many rules are assigned to this project."""
810
- return CheckmkRuleMngmt.objects(project=model.name).count()
810
+ """Assigned Setup-rule count, linking to the filtered Setup-rule list."""
811
+ count = CheckmkRuleMngmt.objects(project=model.name).count()
812
+ url = url_for('checkmkrulemngmt.index_view', flt0_1=model.name)
813
+ return Markup(f'<a href="{escape(url)}">{count}</a>')
814
+
815
+
816
+ def _render_project_dcd_count(_view, _context, model, _name):
817
+ """Assigned DCD-rule count, linking to the filtered DCD-rule list."""
818
+ count = CheckmkDCDRule.objects(project=model.name).count()
819
+ url = url_for('checkmkdcdrule.index_view', flt0_0=model.name)
820
+ return Markup(f'<a href="{escape(url)}">{count}</a>')
811
821
 
812
822
 
813
823
  def _render_project_name_link(_view, _context, model, _name):
@@ -823,6 +833,30 @@ def _render_project_accounts(_view, _context, model, _name):
823
833
  return Markup('<em>all accounts</em>')
824
834
 
825
835
 
836
+ def _import_project_rules(model, rule_dicts, project_name):
837
+ """
838
+ (Re)create rules of one model from exported JSON dicts and assign them to
839
+ ``project_name``. Existing rules with the same name are overwritten. Shared
840
+ by the project JSON import for both Setup rules and DCD rules. Returns the
841
+ number of rules imported.
842
+ """
843
+ count = 0
844
+ for rule_data in rule_dicts or []:
845
+ rule_data = dict(rule_data)
846
+ rule_data.pop('_id', None)
847
+ rule_name = rule_data.get('name')
848
+ if not rule_name:
849
+ continue
850
+ existing = model.objects(name=rule_name).first()
851
+ rule = model.from_json(json.dumps(rule_data))
852
+ if existing:
853
+ rule.id = existing.id
854
+ rule.project = project_name
855
+ rule.save()
856
+ count += 1
857
+ return count
858
+
859
+
826
860
  class CheckmkRuleProjectView(DefaultModelView):
827
861
  """
828
862
  Rule Projects group Checkmk Setup Rules and limit where they are exported.
@@ -832,15 +866,19 @@ class CheckmkRuleProjectView(DefaultModelView):
832
866
  """
833
867
  # Adds a direct link from the edit form to the Setup Rules of this project.
834
868
  edit_template = 'admin/checkmk_rule_project_edit.html'
835
- column_list = ('name', 'limit_by_accounts', 'rule_count')
869
+ # Adds an "Import project from JSON" button to the list toolbar.
870
+ list_template = 'admin/checkmk_rule_project_list.html'
871
+ column_list = ('name', 'limit_by_accounts', 'rule_count', 'dcd_rule_count')
836
872
  column_default_sort = 'name'
837
873
  column_labels = {
838
874
  'rule_count': 'Rules',
875
+ 'dcd_rule_count': 'DCD Rules',
839
876
  'limit_by_accounts': 'Exported to Accounts',
840
877
  }
841
878
  column_formatters = {
842
879
  'name': _render_project_name_link,
843
880
  'rule_count': _render_project_rule_count,
881
+ 'dcd_rule_count': _render_project_dcd_count,
844
882
  'limit_by_accounts': _render_project_accounts,
845
883
  }
846
884
  column_filters = (
@@ -875,10 +913,15 @@ class CheckmkRuleProjectView(DefaultModelView):
875
913
  return redirect(self.get_url('.index_view'))
876
914
  project_rules = CheckmkRuleMngmt.objects(
877
915
  project=project.name).order_by('primary_ruleset', 'name')
916
+ # DCD rules assigned to the project are shown for overview only — they
917
+ # are not part of the Setup-rule export/import workflow.
918
+ dcd_rules = CheckmkDCDRule.objects(
919
+ project=project.name).order_by('name')
878
920
  return self.render(
879
921
  'admin/checkmk_rule_project_overview.html',
880
922
  project=project,
881
923
  project_rules=project_rules,
924
+ dcd_rules=dcd_rules,
882
925
  return_url=self.get_url('.index_view'))
883
926
 
884
927
  @action('export', 'Export as JSON',
@@ -888,9 +931,12 @@ class CheckmkRuleProjectView(DefaultModelView):
888
931
  payload = []
889
932
  for project in CheckmkRuleProject.objects(id__in=ids):
890
933
  project_rules = CheckmkRuleMngmt.objects(project=project.name)
934
+ project_dcd_rules = CheckmkDCDRule.objects(project=project.name)
891
935
  payload.append({
892
936
  'project': json.loads(project.to_json()),
893
937
  'rules': [json.loads(rule.to_json()) for rule in project_rules],
938
+ 'dcd_rules': [json.loads(rule.to_json())
939
+ for rule in project_dcd_rules],
894
940
  })
895
941
  body = json.dumps(payload, indent=2, default=str)
896
942
  return Response(
@@ -920,7 +966,7 @@ class CheckmkRuleProjectView(DefaultModelView):
920
966
  if isinstance(data, dict):
921
967
  data = [data]
922
968
 
923
- projects, imported_rules = 0, 0
969
+ projects, imported_rules, imported_dcd_rules = 0, 0, 0
924
970
  for block in data:
925
971
  proj_data = dict((block or {}).get('project') or {})
926
972
  proj_data.pop('_id', None)
@@ -940,22 +986,13 @@ class CheckmkRuleProjectView(DefaultModelView):
940
986
  project.save()
941
987
  projects += 1
942
988
 
943
- for rule_data in (block.get('rules') or []):
944
- rule_data = dict(rule_data)
945
- rule_data.pop('_id', None)
946
- rule_name = rule_data.get('name')
947
- if not rule_name:
948
- continue
949
- existing = CheckmkRuleMngmt.objects(name=rule_name).first()
950
- rule = CheckmkRuleMngmt.from_json(json.dumps(rule_data))
951
- if existing:
952
- rule.id = existing.id
953
- rule.project = name
954
- rule.save()
955
- imported_rules += 1
956
-
957
- flash(f'Imported {projects} project(s) and {imported_rules} rule(s)',
958
- 'success')
989
+ imported_rules += _import_project_rules(
990
+ CheckmkRuleMngmt, block.get('rules'), name)
991
+ imported_dcd_rules += _import_project_rules(
992
+ CheckmkDCDRule, block.get('dcd_rules'), name)
993
+
994
+ flash(f'Imported {projects} project(s), {imported_rules} rule(s) and '
995
+ f'{imported_dcd_rules} DCD rule(s)', 'success')
959
996
  return redirect(return_url)
960
997
 
961
998
  @action('import_from_cmk', 'Import Rules from Checkmk Folder', None)
@@ -1807,6 +1844,28 @@ class CheckmkDCDView(RuleModelView):
1807
1844
  'render_full_conditions': "Conditions",
1808
1845
  }
1809
1846
 
1847
+ column_filters = (
1848
+ FilterLike('project', 'Project'),
1849
+ )
1850
+
1851
+ form_rules = _modern_rule_form(
1852
+ main_fields=[
1853
+ rules.Field('name'),
1854
+ rules.Field('documentation'),
1855
+ rules.Field('project'),
1856
+ div_open,
1857
+ rules.NestedRule(('enabled', 'last_match')),
1858
+ div_close,
1859
+ rules.Field('sort_field'),
1860
+ ],
1861
+ condition_fields=[
1862
+ rules.Field('condition_typ'),
1863
+ rules.Field('conditions'),
1864
+ ],
1865
+ outcome_fields=[rules.Field('outcomes')],
1866
+ outcome_title='DCD Rule',
1867
+ outcome_desc='The DCD connection(s) to create in Checkmk.',
1868
+ )
1810
1869
 
1811
1870
  def __init__(self, model, **kwargs):
1812
1871
  """
@@ -1819,8 +1878,17 @@ class CheckmkDCDView(RuleModelView):
1819
1878
 
1820
1879
  self.form_overrides.update({
1821
1880
  'render_cmk_dcd_rule': HiddenField,
1881
+ 'project': ProjectSelectField,
1822
1882
  })
1823
1883
 
1884
+ self.form_descriptions = dict(getattr(self, 'form_descriptions', {}) or {})
1885
+ self.form_descriptions['project'] = (
1886
+ "Assign this DCD rule to a Rule Project. It then shows up on the "
1887
+ "project overview and follows the project's account filter — the "
1888
+ "rule is exported only to the accounts the project allows (a "
1889
+ "project without an account filter still exports everywhere)."
1890
+ )
1891
+
1824
1892
  super().__init__(model, **kwargs)
1825
1893
 
1826
1894
  def is_accessible(self):
@@ -5,9 +5,10 @@
5
5
  <h3>Import Rule Project</h3>
6
6
  <p>
7
7
  Upload a JSON file previously exported from a Rule Project. The project
8
- and all of its Setup Rules are (re)created on this instance. Existing
9
- rules with the same name are overwritten; the imported project starts
10
- in status <span class="badge badge-secondary">draft</span>.
8
+ and all of its Setup Rules and DCD Rules are (re)created on this
9
+ instance. Existing rules with the same name are overwritten; the
10
+ imported project starts in status
11
+ <span class="badge badge-secondary">draft</span>.
11
12
  </p>
12
13
  <form method="POST" action="{{ url_for('.import_view') }}" enctype="multipart/form-data">
13
14
  <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
@@ -0,0 +1,25 @@
1
+ {% extends 'admin/model/list.html' %}
2
+
3
+ {# Heading + one-line intro above the default list. #}
4
+ {% block body %}
5
+ <div class="d-flex align-items-center mb-1" style="gap:10px;flex-wrap:wrap;">
6
+ <h4 class="mb-0">Rule Projects</h4>
7
+ </div>
8
+ <p class="text-muted mb-2">
9
+ Group Checkmk Setup &amp; DCD rules and limit their export to selected
10
+ accounts. Click a project name for its overview; click a rule count to
11
+ jump to the filtered rule list.
12
+ </p>
13
+ {{ super() }}
14
+ {% endblock %}
15
+
16
+ {# Add "Import project from JSON" to the list toolbar, next to Create/Export.
17
+ The import route otherwise has no entry point in the UI. #}
18
+ {% block model_menu_bar_before_filters %}
19
+ <li class="nav-item">
20
+ <a href="{{ url_for('.import_view') }}" class="nav-link"
21
+ title="Import a Rule Project (with its Setup and DCD rules) from a JSON file">
22
+ <i class="fa fa-upload"></i> {{ _gettext('Import JSON') }}
23
+ </a>
24
+ </li>
25
+ {% endblock %}
@@ -52,6 +52,8 @@
52
52
  </dd>
53
53
  <dt class="col-sm-3">Assigned Rules</dt>
54
54
  <dd class="col-sm-9">{{ project_rules.count() }}</dd>
55
+ <dt class="col-sm-3">Assigned DCD Rules</dt>
56
+ <dd class="col-sm-9">{{ dcd_rules.count() }}</dd>
55
57
  </dl>
56
58
  </div>
57
59
  </div>
@@ -152,5 +154,72 @@
152
154
  {% endfor %}
153
155
  {% endif %}
154
156
 
157
+ <div class="d-flex align-items-center mb-2 mt-4" style="gap:10px;">
158
+ <h4 class="mb-0">DCD rules in this project</h4>
159
+ <a href="{{ url_for('checkmkdcdrule.create_view') }}"
160
+ class="btn btn-sm btn-outline-primary">
161
+ <i class="fa fa-plus"></i> Add DCD rule
162
+ </a>
163
+ <a href="{{ url_for('checkmkdcdrule.index_view') }}?flt0_0={{ project.name|urlencode }}"
164
+ class="btn btn-sm btn-outline-secondary">
165
+ <i class="fa fa-list"></i> Manage in DCD list
166
+ </a>
167
+ </div>
168
+
169
+ {% if dcd_rules.count() == 0 %}
170
+ <div class="alert alert-info">
171
+ No DCD rules assigned to this project yet. Open a DCD rule and set its
172
+ <strong>Project</strong> to <em>{{ project.name }}</em> to add it here.
173
+ Assigned DCD rules also follow this project's account filter on export.
174
+ </div>
175
+ {% else %}
176
+ {% for rule in dcd_rules %}
177
+ <div class="card app-card mb-2">
178
+ <div class="card-header d-flex align-items-center" style="gap:8px;flex-wrap:wrap;">
179
+ <strong>{{ rule.name }}</strong>
180
+ {% if rule.enabled %}
181
+ <span class="badge badge-success">enabled</span>
182
+ {% else %}
183
+ <span class="badge badge-secondary">disabled</span>
184
+ {% endif %}
185
+ <a href="{{ url_for('checkmkdcdrule.edit_view', id=rule.id, url=request.url) }}"
186
+ class="btn btn-sm btn-outline-secondary ml-auto">
187
+ <i class="fa fa-pencil"></i> Edit
188
+ </a>
189
+ </div>
190
+ <div class="card-body">
191
+ <div class="mb-2">
192
+ <span class="text-muted">Applies to:</span>
193
+ {% if rule.condition_typ == 'anyway' or not rule.conditions %}
194
+ <em>all hosts</em>
195
+ {% else %}
196
+ <span class="text-muted">
197
+ ({{ 'all' if rule.condition_typ == 'all' else 'any' }} of)
198
+ </span>
199
+ <ul class="mb-0">
200
+ {% for c in rule.conditions %}
201
+ <li>{{ render_cond(c) }}</li>
202
+ {% endfor %}
203
+ </ul>
204
+ {% endif %}
205
+ </div>
206
+ {% for o in rule.outcomes %}
207
+ <div class="{{ 'border-top pt-2 mt-2' if not loop.first }}"
208
+ style="display:flex;gap:14px;flex-wrap:wrap;">
209
+ <span><span class="text-muted">Connection:</span>
210
+ <code>{{ o.dcd_id or '—' }}</code></span>
211
+ <span><span class="text-muted">Title:</span>
212
+ <code>{{ o.title or '—' }}</code></span>
213
+ <span><span class="text-muted">Site:</span>
214
+ <code>{{ o.site or '—' }}</code></span>
215
+ <span><span class="text-muted">Connector:</span>
216
+ <code>{{ o.connector_type or '—' }}</code></span>
217
+ </div>
218
+ {% endfor %}
219
+ </div>
220
+ </div>
221
+ {% endfor %}
222
+ {% endif %}
223
+
155
224
  </div>
156
225
  {% endblock %}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cmdbsyncer
3
- Version: 4.2.2
3
+ Version: 4.2.3
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>
@@ -268,6 +268,7 @@ application/templates/admin/checkmk_rule_mngmt_list.html
268
268
  application/templates/admin/checkmk_rule_project_edit.html
269
269
  application/templates/admin/checkmk_rule_project_import.html
270
270
  application/templates/admin/checkmk_rule_project_import_cmk.html
271
+ application/templates/admin/checkmk_rule_project_list.html
271
272
  application/templates/admin/checkmk_rule_project_overview.html
272
273
  application/templates/admin/checkmk_settings_list.html
273
274
  application/templates/admin/checkmk_test_folder_scope.html
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "cmdbsyncer"
7
- version = "4.2.2"
7
+ version = "4.2.3"
8
8
  description = "Rule-based modular synchronizer for Checkmk, Netbox, Ansible, I-DOIT, Jira CMDB and 15+ other CMDB/monitoring systems"
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -1 +0,0 @@
1
- BUILD_DATE=2026-07-14T11:01:00Z