cmdbsyncer 4.1.0.dev14__tar.gz → 4.1.0.dev15__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/PKG-INFO +1 -1
- cmdbsyncer-4.1.0.dev15/application/buildinfo.txt +1 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/changelog/v4.1.md +4 -0
- cmdbsyncer-4.1.0.dev15/application/plugins/jira_cloud/__init__.py +60 -0
- cmdbsyncer-4.1.0.dev15/application/plugins/jira_cloud/admin_views.py +39 -0
- cmdbsyncer-4.1.0.dev15/application/plugins/jira_cloud/export.py +303 -0
- cmdbsyncer-4.1.0.dev15/application/plugins/jira_cloud/models.py +159 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/jira_cloud/plugin.json +2 -2
- cmdbsyncer-4.1.0.dev15/application/plugins/jira_cloud/rules.py +51 -0
- cmdbsyncer-4.1.0.dev15/application/plugins/jira_cloud/schema_sync.py +82 -0
- cmdbsyncer-4.1.0.dev15/application/plugins/jira_cloud/views.py +224 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/debug_host.html +5 -3
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/cmdbsyncer.egg-info/PKG-INFO +1 -1
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/cmdbsyncer.egg-info/SOURCES.txt +6 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/pyproject.toml +1 -1
- cmdbsyncer-4.1.0.dev14/application/buildinfo.txt +0 -1
- cmdbsyncer-4.1.0.dev14/application/plugins/jira_cloud/__init__.py +0 -25
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/LICENSE +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/README.md +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/_version.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/api/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/api/inventory.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/api/objects.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/api/rules.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/api/syncer.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/api/views.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/auth/views.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/changelog/.pages +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/changelog/v3.10.md +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/changelog/v3.11.md +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/changelog/v3.12.md +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/changelog/v3.5.md +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/changelog/v3.7.md +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/changelog/v3.8.md +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/changelog/v3.9.md +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/changelog/v4.0.md +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/cli.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/config.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/docu_links.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/enterprise.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/helpers/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/helpers/audit.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/helpers/cron.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/helpers/get_account.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/helpers/inventory.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/helpers/local_config_file.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/helpers/local_config_presets.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/helpers/mongo_keys.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/helpers/notification_channels.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/helpers/notification_dispatch.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/helpers/plugins.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/helpers/sates.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/helpers/sql.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/helpers/syncer_jinja.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/helpers/tablib_formater.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/helpers/tests/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/helpers/tests/test_sql.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/mcp_server.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/models/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/models/account.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/models/config.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/models/cron.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/models/field_approval.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/models/forms.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/models/host.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/models/host_inventory_tree.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/models/notification_channel.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/models/notification_rule.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/models/notification_state.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/models/saved_search.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/models/states.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/models/user.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/modules/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/modules/custom_attributes/models.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/modules/custom_attributes/rules.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/modules/custom_attributes/views.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/modules/debug.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/modules/email.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/modules/inventory/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/modules/log/log.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/modules/log/models.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/modules/log/views.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/modules/plugin.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/modules/rule/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/modules/rule/filter.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/modules/rule/match.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/modules/rule/models.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/modules/rule/rewrite.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/modules/rule/rule.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/modules/rule/views.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/modules/statefile.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/notices/strict_certificate_verification.txt +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/ansible/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/ansible/admin_views.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/ansible/inventory.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/ansible/models.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/ansible/playbook_rules.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/ansible/plugin.json +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/ansible/rules.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/ansible/runner.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/ansible/site_syncer.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/ansible/views.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/bmc_remedy/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/bmc_remedy/bmc_remedy.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/bmc_remedy/plugin.json +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/admin_views.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/bi.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/cmk2.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/cmk_rules.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/dcd.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/downtimes.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/groups.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/helpers.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/import_v1.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/import_v2.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/inits.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/inventorize.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/models.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/notification_rules.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/passwords.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/plugin.json +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/poolfolder.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/rules.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/sites.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/syncer.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/tags.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/tests/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/tests/test_bi.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/tests/test_cmk2.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/tests/test_cmk_rules.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/tests/test_dcd.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/tests/test_downtimes.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/tests/test_groups.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/tests/test_helpers.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/tests/test_import_v1.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/tests/test_import_v2.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/tests/test_inventorize.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/tests/test_notification_rules.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/tests/test_passwords.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/tests/test_poolfolder.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/tests/test_rules.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/tests/test_sites.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/tests/test_syncer.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/tests/test_tags.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/tests/test_users.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/users.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/checkmk/views.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/cisco_dna/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/cisco_dna/plugin.json +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/cisco_dna/syncer.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/cron.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/csv/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/csv/csv.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/csv/plugin.json +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/file_requests.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/idoit/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/idoit/admin_views.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/idoit/models.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/idoit/plugin.json +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/idoit/rules.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/idoit/syncer.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/idoit/views.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/jdisc/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/jdisc/applications.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/jdisc/devices.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/jdisc/executables.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/jdisc/jdisc.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/jdisc/plugin.json +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/jira/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/jira/jira.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/jira/plugin.json +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/jira_cloud/jira_cloud.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/json/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/json/json.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/json/plugin.json +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/ldap/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/ldap/ldap.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/ldap/plugin.json +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/maintenance/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/maintenance/plugin.json +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/mssql/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/mssql/plugin.json +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/mysql/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/mysql/mysql.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/mysql/plugin.json +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/netbox/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/netbox/admin_views.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/netbox/cluster.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/netbox/contacts.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/netbox/dataflow.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/netbox/devices.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/netbox/interfaces.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/netbox/ips.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/netbox/models.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/netbox/netbox.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/netbox/networks.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/netbox/plugin.json +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/netbox/prefixes.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/netbox/rules.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/netbox/views.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/netbox/virtualmachines.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/prtg/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/prtg/plugin.json +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/prtg/prtg.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/pyodbc/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/pyodbc/plugin.json +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/pyodbc/pyodbc.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/rest/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/rest/plugin.json +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/rest/rest.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/rules/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/rules/admin_views.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/rules/autorules.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/rules/models.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/rules/plugin.json +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/rules/rule_definitions.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/rules/rule_import_export.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/rules/views.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/syncer_shell.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/vmware/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/vmware/admin_views.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/vmware/custom_attributes.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/vmware/models.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/vmware/plugin.json +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/vmware/rules.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/vmware/views.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/vmware/vmware.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/yml/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/yml/plugin.json +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/yml/yml.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins_cli.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/static/css/cmdbsyncer.css +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/static/js/main.js +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/static/logo_white.png +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/_brand.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/_theme.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/_host_tabs.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/account_pick_type.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/ansible_playbook_run.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/ansible_project_detail.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/ansible_rule_list.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/bulk_label_form.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/changelog_archive.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/checkmk_rule_mngmt_list.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/checkmk_settings_list.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/copy_as_new_form.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/data_quality.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/file/list.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/file/modals/form.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/host_details.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/host_edit.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/host_inventory_tree.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/host_list.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/host_relations_graph.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/host_timeline.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/index.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/local_config_editor.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/master.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/model/clone_confirm.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/model/inline_list_base.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/object_list.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/set_cmk_version_form.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/admin/set_template_form.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/base.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/change_password.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/debug.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/email/newuser.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/email/notification.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/email/resetpassword.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/formular.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/license_info.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/login.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/logout_confirm.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/request_password.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/set_2fa.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/templates/set_theme.html +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/themes/dracula.css +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/themes/gruvbox-dark.css +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/themes/gruvbox-light.css +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/themes/nord.css +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/themes_registry.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/views/_form_fields.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/views/_form_sections.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/views/account.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/views/config.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/views/cron.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/views/data_quality.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/views/default.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/views/field_approval.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/views/fileadmin.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/views/host.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/views/host_filters.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/views/host_renderers.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/views/host_widgets.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/views/license.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/views/notification_channel.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/views/notification_rule.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/views/saved_search.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/views/user.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/cmdbsyncer.egg-info/dependency_links.txt +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/cmdbsyncer.egg-info/entry_points.txt +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/cmdbsyncer.egg-info/requires.txt +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/cmdbsyncer.egg-info/top_level.txt +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/requirements-ansible.txt +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/requirements-extras.txt +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/requirements.txt +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/setup.cfg +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/syncerapi/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/syncerapi/v1/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/syncerapi/v1/core/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/syncerapi/v1/inventory/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/syncerapi/v1/rest/__init__.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/tests/test_api.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/tests/test_api_csrf_invariant.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/tests/test_default_view.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/tests/test_mongo_keys.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/tests/test_plugin.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/tests/test_plugin_ssti.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/tests/test_plugins_cli.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/tests/test_rule.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/tests/test_rule_match.py +0 -0
- {cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/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.1.0.
|
|
3
|
+
Version: 4.1.0.dev15
|
|
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-05-12T15:19:26Z
|
|
@@ -53,8 +53,12 @@
|
|
|
53
53
|
- FEAT: Quick-search on Rule Management matches name and ruleset
|
|
54
54
|
- FIX: Saving a rule with outcomes that target different rulesets is rejected with a flash
|
|
55
55
|
- FEAT: New "Manage Notification Rules" view exports notification rules to Checkmk 2.4 / 2.5 with `cmdbsyncer checkmk export_notifications`; admin edits are detected and corrected on the next run
|
|
56
|
+
- FIX: Host debug page — clicking the "Setup Rules" group on a Checkmk host now expands its rule table (the space in the group name was breaking the collapse anchor)
|
|
56
57
|
- FIX: HW/SW inventorize fetches the inventory tree via the REST API's `host_mk_inventory` Livestatus column instead of the legacy `host_inv_api.py` endpoint — works behind OIDC/SSO proxies that block the Multisite path. Parses both Checkmk 2.5's JSON blob and older releases' Python-repr blob. Each multiprocessing worker also gets its own MongoDB connection, and on failure the failing hostname, exception type and full traceback are reported instead of a misleading "Timeout error"
|
|
57
58
|
|
|
59
|
+
### Jira
|
|
60
|
+
- FEAT: Jira Cloud plugin can now export host fields to Jira Assets objects. Configure target object type and per-attribute field mapping (with autocomplete from the cached Jira schema) in Modules → Jira Cloud → Export Rules, run with `cmdbsyncer jira sync_schema <account>` and `cmdbsyncer jira export_cloud <account>`. Multiple rules let one run write to several object types; create-on-missing is opt-in and unchanged objects are not re-sent
|
|
61
|
+
|
|
58
62
|
### API
|
|
59
63
|
- FEAT: `/api/v1/objects/<hostname>/relations` reads, adds and removes typed Host relations (CMDB_MODE only)
|
|
60
64
|
- FIX: `/api/v1/objects/all` rejects `limit > 10000`
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Jira Cloud plugin."""
|
|
2
|
+
import click
|
|
3
|
+
from application.plugins.jira import jira_cli
|
|
4
|
+
|
|
5
|
+
from syncerapi.v1 import (
|
|
6
|
+
register_cronjob,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
from .jira_cloud import import_jira_cloud
|
|
10
|
+
from .export import export_jira_cloud
|
|
11
|
+
from .schema_sync import sync_jira_schema
|
|
12
|
+
|
|
13
|
+
@jira_cli.command('import_cloud')
|
|
14
|
+
@click.argument("account")
|
|
15
|
+
@click.option("--debug", is_flag=True)
|
|
16
|
+
def cmd_import_jira(account, debug):
|
|
17
|
+
"""
|
|
18
|
+
Import from Cloud Instance
|
|
19
|
+
"""
|
|
20
|
+
try:
|
|
21
|
+
import_jira_cloud(account, debug)
|
|
22
|
+
except Exception as error: # pylint: disable=broad-exception-caught
|
|
23
|
+
if debug:
|
|
24
|
+
raise
|
|
25
|
+
print(f"Error: {error}")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@jira_cli.command('export_cloud')
|
|
29
|
+
@click.argument("account")
|
|
30
|
+
@click.option("--debug", is_flag=True)
|
|
31
|
+
def cmd_export_jira(account, debug):
|
|
32
|
+
"""
|
|
33
|
+
Export Hosts/Fields to a Jira Cloud Assets Instance
|
|
34
|
+
"""
|
|
35
|
+
try:
|
|
36
|
+
export_jira_cloud(account, debug)
|
|
37
|
+
except Exception as error: # pylint: disable=broad-exception-caught
|
|
38
|
+
if debug:
|
|
39
|
+
raise
|
|
40
|
+
print(f"Error: {error}")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@jira_cli.command('sync_schema')
|
|
44
|
+
@click.argument("account")
|
|
45
|
+
@click.option("--debug", is_flag=True)
|
|
46
|
+
def cmd_sync_jira_schema(account, debug):
|
|
47
|
+
"""
|
|
48
|
+
Cache the Jira Cloud Assets schema (used by the export GUI / plugin)
|
|
49
|
+
"""
|
|
50
|
+
try:
|
|
51
|
+
sync_jira_schema(account, debug)
|
|
52
|
+
except Exception as error: # pylint: disable=broad-exception-caught
|
|
53
|
+
if debug:
|
|
54
|
+
raise
|
|
55
|
+
print(f"Error: {error}")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
register_cronjob('Jira Cloud: Import Hosts', import_jira_cloud)
|
|
59
|
+
register_cronjob('Jira Cloud: Export Objects', export_jira_cloud)
|
|
60
|
+
register_cronjob('Jira Cloud: Sync Schema', sync_jira_schema)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Flask-Admin registration for the Jira Cloud Export views."""
|
|
2
|
+
from application.modules.rule.views import RewriteAttributeView
|
|
3
|
+
|
|
4
|
+
from .views import (
|
|
5
|
+
JiraCloudFilterView,
|
|
6
|
+
JiraExportRuleView,
|
|
7
|
+
JiraSchemaCacheView,
|
|
8
|
+
)
|
|
9
|
+
from .models import (
|
|
10
|
+
JiraCloudFilterRule,
|
|
11
|
+
JiraCloudRewriteAttributeRule,
|
|
12
|
+
JiraExportRule,
|
|
13
|
+
JiraSchemaCache,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def register_admin_views(admin):
|
|
18
|
+
"""Register the Jira Cloud submenu."""
|
|
19
|
+
admin.add_sub_category(name="Jira Cloud", parent_name="Modules")
|
|
20
|
+
|
|
21
|
+
admin.add_view(JiraCloudFilterView(
|
|
22
|
+
JiraCloudFilterRule,
|
|
23
|
+
name="Filter", category="Jira Cloud",
|
|
24
|
+
menu_icon_type='fa', menu_icon_value='fa-filter'))
|
|
25
|
+
|
|
26
|
+
admin.add_view(RewriteAttributeView(
|
|
27
|
+
JiraCloudRewriteAttributeRule,
|
|
28
|
+
name="Rewrite Attributes", category="Jira Cloud",
|
|
29
|
+
menu_icon_type='fa', menu_icon_value='fa-exchange'))
|
|
30
|
+
|
|
31
|
+
admin.add_view(JiraExportRuleView(
|
|
32
|
+
JiraExportRule,
|
|
33
|
+
name="Export Rules", category="Jira Cloud",
|
|
34
|
+
menu_icon_type='fa', menu_icon_value='fa-upload'))
|
|
35
|
+
|
|
36
|
+
admin.add_view(JiraSchemaCacheView(
|
|
37
|
+
JiraSchemaCache,
|
|
38
|
+
name="Schema Cache", category="Jira Cloud",
|
|
39
|
+
menu_icon_type='fa', menu_icon_value='fa-database'))
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Export host attributes to Jira Cloud Assets objects.
|
|
3
|
+
|
|
4
|
+
Every enabled JiraExportRule is loaded into a single rule engine, every
|
|
5
|
+
referenced object type's existing objects are bulk-fetched once via AQL,
|
|
6
|
+
and hosts are iterated exactly once. Per host the engine merges all
|
|
7
|
+
matching rules' outcomes; we then walk the resulting per-type field
|
|
8
|
+
bundles, diff against the cached existing values and only PUT/POST when
|
|
9
|
+
something actually changed.
|
|
10
|
+
|
|
11
|
+
The lookup attribute is always "Name" — Jira Assets' default label
|
|
12
|
+
attribute on every object type.
|
|
13
|
+
"""
|
|
14
|
+
# pylint: disable=too-many-locals,too-many-branches,too-many-nested-blocks
|
|
15
|
+
# pylint: disable=too-many-statements
|
|
16
|
+
import json
|
|
17
|
+
from collections import defaultdict
|
|
18
|
+
|
|
19
|
+
from rich.progress import Progress, SpinnerColumn, MofNCompleteColumn, TimeElapsedColumn
|
|
20
|
+
|
|
21
|
+
from syncerapi.v1 import (
|
|
22
|
+
Host,
|
|
23
|
+
cc,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
from application import logger
|
|
27
|
+
from application.modules.rule.filter import Filter
|
|
28
|
+
from application.modules.rule.rewrite import Rewrite
|
|
29
|
+
from application.plugins.jira_cloud.jira_cloud import JiraCloud
|
|
30
|
+
from application.plugins.jira_cloud.models import (
|
|
31
|
+
JiraCloudFilterRule,
|
|
32
|
+
JiraCloudRewriteAttributeRule,
|
|
33
|
+
JiraExportRule,
|
|
34
|
+
JiraSchemaCache,
|
|
35
|
+
)
|
|
36
|
+
from application.plugins.jira_cloud.rules import JiraExportAttributeRule
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
LOOKUP_ATTRIBUTE_NAME = "Name"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class JiraCloudExport(JiraCloud):
|
|
43
|
+
"""Export driver."""
|
|
44
|
+
|
|
45
|
+
name = "Jira Cloud: Export Objects"
|
|
46
|
+
source = "jira_cloud_export"
|
|
47
|
+
|
|
48
|
+
def __init__(self, account):
|
|
49
|
+
super().__init__(account)
|
|
50
|
+
self._schema_cache = None
|
|
51
|
+
# type_id -> (type_entry, name_to_id, lookup_attr_id, existing_map)
|
|
52
|
+
self._type_state = {}
|
|
53
|
+
|
|
54
|
+
# Honour rewrite + filter rules the same way Checkmk does —
|
|
55
|
+
# the Plugin base class calls them inside `get_attributes`, so
|
|
56
|
+
# we don't have to invoke them anywhere in here.
|
|
57
|
+
self.rewrite = Rewrite()
|
|
58
|
+
self.rewrite.cache_name = "jira_cloud_rewrite"
|
|
59
|
+
self.rewrite.rules = (
|
|
60
|
+
JiraCloudRewriteAttributeRule
|
|
61
|
+
.objects(enabled=True).order_by('sort_field'))
|
|
62
|
+
|
|
63
|
+
self.filter = Filter()
|
|
64
|
+
self.filter.cache_name = "jira_cloud_filter"
|
|
65
|
+
self.filter.rules = JiraCloudFilterRule.objects(enabled=True).order_by('sort_field')
|
|
66
|
+
|
|
67
|
+
def _load_schema(self):
|
|
68
|
+
"""Cache lookup for the persisted schema; fail loud if missing."""
|
|
69
|
+
if self._schema_cache is None:
|
|
70
|
+
doc = JiraSchemaCache.objects(account=self.account_name).first()
|
|
71
|
+
if not doc:
|
|
72
|
+
raise ValueError(
|
|
73
|
+
f"No Jira schema cache for account '{self.account_name}'. "
|
|
74
|
+
f"Run `cmdbsyncer jira sync_schema {self.account_name}` first."
|
|
75
|
+
)
|
|
76
|
+
self._schema_cache = doc
|
|
77
|
+
return self._schema_cache
|
|
78
|
+
|
|
79
|
+
def _get_type(self, object_type_id):
|
|
80
|
+
"""Return the cached object type or None."""
|
|
81
|
+
for entry in self._load_schema().object_types:
|
|
82
|
+
if entry.object_type_id == object_type_id:
|
|
83
|
+
return entry
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
def _build_payload(self, object_type_id, attr_values):
|
|
87
|
+
"""Translate {attribute_id: value} into the Atlassian write format."""
|
|
88
|
+
return {
|
|
89
|
+
"objectTypeId": str(object_type_id),
|
|
90
|
+
"attributes": [
|
|
91
|
+
{
|
|
92
|
+
"objectTypeAttributeId": str(attr_id),
|
|
93
|
+
"objectAttributeValues": [{"value": str(value)}],
|
|
94
|
+
}
|
|
95
|
+
for attr_id, value in attr_values.items()
|
|
96
|
+
],
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
def _existing_objects(self, type_name, lookup_attr_id):
|
|
100
|
+
"""
|
|
101
|
+
Map ``{lookup_value: (object_id, {attr_id: current_value})}`` for
|
|
102
|
+
every existing object of the target type.
|
|
103
|
+
|
|
104
|
+
The AQL response carries attributes only by id (no name), so the
|
|
105
|
+
caller resolves the lookup attribute's id from the schema cache
|
|
106
|
+
and passes it in.
|
|
107
|
+
"""
|
|
108
|
+
existing = {}
|
|
109
|
+
ql = f'objectType = "{type_name}"'
|
|
110
|
+
for obj in self._iter_aql_objects(ql):
|
|
111
|
+
current_attrs = {}
|
|
112
|
+
lookup_value = None
|
|
113
|
+
for attr in obj.get('attributes', []):
|
|
114
|
+
attr_id = int(attr.get('objectTypeAttributeId', 0))
|
|
115
|
+
values = attr.get('objectAttributeValues') or []
|
|
116
|
+
if not values:
|
|
117
|
+
continue
|
|
118
|
+
value = values[0].get('value')
|
|
119
|
+
current_attrs[attr_id] = value
|
|
120
|
+
if attr_id == lookup_attr_id:
|
|
121
|
+
lookup_value = value
|
|
122
|
+
if lookup_value is not None:
|
|
123
|
+
existing[lookup_value] = (obj['id'], current_attrs)
|
|
124
|
+
return existing
|
|
125
|
+
|
|
126
|
+
def _prepare_type(self, object_type_id):
|
|
127
|
+
"""
|
|
128
|
+
Load schema + existing objects for one object type and remember
|
|
129
|
+
the state. Returns the state tuple or ``None`` when the type or
|
|
130
|
+
its ``Name`` attribute isn't cached.
|
|
131
|
+
"""
|
|
132
|
+
if object_type_id in self._type_state:
|
|
133
|
+
return self._type_state[object_type_id]
|
|
134
|
+
|
|
135
|
+
type_entry = self._get_type(object_type_id)
|
|
136
|
+
if not type_entry:
|
|
137
|
+
print(f"{cc.WARNING} -- {cc.ENDC}object_type_id={object_type_id} "
|
|
138
|
+
f"not in schema cache, skipping its outcomes")
|
|
139
|
+
self._type_state[object_type_id] = None
|
|
140
|
+
return None
|
|
141
|
+
|
|
142
|
+
name_to_id = {a.name: a.attribute_id for a in type_entry.attributes}
|
|
143
|
+
if LOOKUP_ATTRIBUTE_NAME not in name_to_id:
|
|
144
|
+
print(f"{cc.WARNING} -- {cc.ENDC}'{type_entry.name}' has no "
|
|
145
|
+
f"'{LOOKUP_ATTRIBUTE_NAME}' attribute, skipping its outcomes")
|
|
146
|
+
self._type_state[object_type_id] = None
|
|
147
|
+
return None
|
|
148
|
+
lookup_attr_id = name_to_id[LOOKUP_ATTRIBUTE_NAME]
|
|
149
|
+
|
|
150
|
+
print(f"{cc.OKGREEN} -- {cc.ENDC}Preparing "
|
|
151
|
+
f"{type_entry.schema_name} / {type_entry.name} "
|
|
152
|
+
f"(type id {object_type_id})")
|
|
153
|
+
existing = self._existing_objects(type_entry.name, lookup_attr_id)
|
|
154
|
+
print(f"{cc.OKGREEN} + {cc.ENDC}{len(existing)} existing object(s) loaded")
|
|
155
|
+
|
|
156
|
+
state = (type_entry, name_to_id, lookup_attr_id, existing)
|
|
157
|
+
self._type_state[object_type_id] = state
|
|
158
|
+
return state
|
|
159
|
+
|
|
160
|
+
def _put_object(self, object_id, object_type_id, attr_values):
|
|
161
|
+
"""Update an existing Jira Assets object."""
|
|
162
|
+
payload = self._build_payload(object_type_id, attr_values)
|
|
163
|
+
self.inner_request(
|
|
164
|
+
method="PUT",
|
|
165
|
+
url=f"{self.base_url}/v1/object/{object_id}",
|
|
166
|
+
headers=self.headers, auth=self.auth,
|
|
167
|
+
data=json.dumps(payload),
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
def _post_object(self, object_type_id, attr_values):
|
|
171
|
+
"""Create a new Jira Assets object."""
|
|
172
|
+
payload = self._build_payload(object_type_id, attr_values)
|
|
173
|
+
self.inner_request(
|
|
174
|
+
method="POST",
|
|
175
|
+
url=f"{self.base_url}/v1/object/create",
|
|
176
|
+
headers=self.headers, auth=self.auth,
|
|
177
|
+
data=json.dumps(payload),
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
def export_objects(self):
|
|
181
|
+
"""Single-pass export: prepare types, iterate hosts once."""
|
|
182
|
+
rules = list(JiraExportRule.objects(enabled=True).order_by('sort_field'))
|
|
183
|
+
if not rules:
|
|
184
|
+
print(f"{cc.WARNING} -- {cc.ENDC}No enabled JiraExportRule rows, "
|
|
185
|
+
f"nothing to do")
|
|
186
|
+
return
|
|
187
|
+
|
|
188
|
+
all_type_ids = sorted({
|
|
189
|
+
type_id
|
|
190
|
+
for r in rules
|
|
191
|
+
for o in (r.outcomes or [])
|
|
192
|
+
if (type_id := o.object_type_id) is not None
|
|
193
|
+
})
|
|
194
|
+
if not all_type_ids:
|
|
195
|
+
print(f"{cc.WARNING} -- {cc.ENDC}No outcomes on any enabled rule, "
|
|
196
|
+
f"nothing to do")
|
|
197
|
+
return
|
|
198
|
+
|
|
199
|
+
for type_id in all_type_ids:
|
|
200
|
+
self._prepare_type(type_id)
|
|
201
|
+
|
|
202
|
+
rule_engine = JiraExportAttributeRule()
|
|
203
|
+
rule_engine.rules = rules
|
|
204
|
+
rule_engine.debug = self.debug
|
|
205
|
+
rule_engine.name = self.name
|
|
206
|
+
cache_key = "jira_cloud_export"
|
|
207
|
+
|
|
208
|
+
# Honour the per-account object_filter the user picks on the
|
|
209
|
+
# Account → Plugin Settings line for this plugin, same as every
|
|
210
|
+
# other outbound syncer.
|
|
211
|
+
object_filter = self.config.get('settings', {}).get(self.name, {}).get('filter')
|
|
212
|
+
db_objects = Host.objects_by_filter(object_filter)
|
|
213
|
+
total = db_objects.count()
|
|
214
|
+
counts = defaultdict(lambda: {"updated": 0, "created": 0,
|
|
215
|
+
"unchanged": 0, "skipped": 0})
|
|
216
|
+
|
|
217
|
+
with Progress(SpinnerColumn(), MofNCompleteColumn(),
|
|
218
|
+
*Progress.get_default_columns(),
|
|
219
|
+
TimeElapsedColumn()) as progress:
|
|
220
|
+
console = progress.console.print
|
|
221
|
+
task = progress.add_task("Jira Cloud export", total=total)
|
|
222
|
+
for db_host in db_objects:
|
|
223
|
+
progress.advance(task)
|
|
224
|
+
try:
|
|
225
|
+
self._process_host(db_host, rule_engine, cache_key,
|
|
226
|
+
counts, console)
|
|
227
|
+
except Exception as error: # pylint: disable=broad-exception-caught
|
|
228
|
+
if self.debug:
|
|
229
|
+
raise
|
|
230
|
+
logger.exception("Export failed for %s", db_host.hostname)
|
|
231
|
+
self.log_details.append(
|
|
232
|
+
(f'export_error {db_host.hostname}', str(error)))
|
|
233
|
+
|
|
234
|
+
for type_id in all_type_ids:
|
|
235
|
+
c = counts[type_id]
|
|
236
|
+
summary = (f"updated={c['updated']} created={c['created']} "
|
|
237
|
+
f"unchanged={c['unchanged']} skipped={c['skipped']}")
|
|
238
|
+
type_entry = self._get_type(type_id)
|
|
239
|
+
label = type_entry.name if type_entry else f"type {type_id}"
|
|
240
|
+
print(f"{cc.OKGREEN} == {cc.ENDC}{label} [type {type_id}]: {summary}")
|
|
241
|
+
self.log_details.append((f'type {type_id}', summary))
|
|
242
|
+
|
|
243
|
+
# pylint: disable-next=too-many-arguments,too-many-positional-arguments
|
|
244
|
+
def _process_host(self, db_host, rule_engine, cache_key, counts, console):
|
|
245
|
+
"""Apply every matching rule to one host."""
|
|
246
|
+
attrs = self.get_attributes(db_host, cache_key)
|
|
247
|
+
if not attrs:
|
|
248
|
+
return
|
|
249
|
+
outcomes = rule_engine.get_outcomes(db_host, attrs['all'])
|
|
250
|
+
fields_by_type = outcomes.get('fields_by_type') or {}
|
|
251
|
+
if not fields_by_type:
|
|
252
|
+
return
|
|
253
|
+
lookup_value = db_host.hostname
|
|
254
|
+
|
|
255
|
+
for type_id_str, fields in fields_by_type.items():
|
|
256
|
+
type_id = int(type_id_str)
|
|
257
|
+
state = self._type_state.get(type_id)
|
|
258
|
+
if not state:
|
|
259
|
+
counts[type_id]["skipped"] += 1
|
|
260
|
+
continue
|
|
261
|
+
_entry, name_to_id, lookup_attr_id, existing = state
|
|
262
|
+
|
|
263
|
+
target_attrs = {}
|
|
264
|
+
unknown = []
|
|
265
|
+
for name, value in fields.items():
|
|
266
|
+
if name not in name_to_id:
|
|
267
|
+
unknown.append(name)
|
|
268
|
+
continue
|
|
269
|
+
target_attrs[name_to_id[name]] = value
|
|
270
|
+
if unknown:
|
|
271
|
+
console(f"{cc.WARNING} ? {cc.ENDC}"
|
|
272
|
+
f"{db_host.hostname} [type {type_id}]: "
|
|
273
|
+
f"unknown Jira attribute(s) {unknown}")
|
|
274
|
+
if not target_attrs:
|
|
275
|
+
counts[type_id]["skipped"] += 1
|
|
276
|
+
continue
|
|
277
|
+
|
|
278
|
+
if lookup_value in existing:
|
|
279
|
+
obj_id, current = existing[lookup_value]
|
|
280
|
+
changed = {a: v for a, v in target_attrs.items()
|
|
281
|
+
if str(current.get(a, '')) != str(v)}
|
|
282
|
+
if not changed:
|
|
283
|
+
counts[type_id]["unchanged"] += 1
|
|
284
|
+
continue
|
|
285
|
+
self._put_object(obj_id, type_id, changed)
|
|
286
|
+
console(f"{cc.OKGREEN} ↻ {cc.ENDC}"
|
|
287
|
+
f"{db_host.hostname} [type {type_id}] "
|
|
288
|
+
f"({len(changed)} field(s))")
|
|
289
|
+
counts[type_id]["updated"] += 1
|
|
290
|
+
else:
|
|
291
|
+
if lookup_attr_id not in target_attrs:
|
|
292
|
+
target_attrs[lookup_attr_id] = lookup_value
|
|
293
|
+
self._post_object(type_id, target_attrs)
|
|
294
|
+
console(f"{cc.OKBLUE} + {cc.ENDC}"
|
|
295
|
+
f"{db_host.hostname} [type {type_id}] (created)")
|
|
296
|
+
counts[type_id]["created"] += 1
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def export_jira_cloud(account, debug=False):
|
|
300
|
+
"""Entry point for CLI / cronjob."""
|
|
301
|
+
syncer = JiraCloudExport(account)
|
|
302
|
+
syncer.debug = debug
|
|
303
|
+
syncer.export_objects()
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Jira Cloud Export Models
|
|
3
|
+
"""
|
|
4
|
+
# pylint: disable=too-few-public-methods
|
|
5
|
+
from application import db
|
|
6
|
+
from application.modules.rule.models import rule_types
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class JiraExportOutcome(db.EmbeddedDocument):
|
|
10
|
+
"""
|
|
11
|
+
One field mapping: a Jira attribute on a specific object type
|
|
12
|
+
receives a (Jinja-rendered) value.
|
|
13
|
+
|
|
14
|
+
Object type and attribute are stored together in a single ``target``
|
|
15
|
+
string of the form ``"<object_type_id>|<attribute_name>"``. In
|
|
16
|
+
Jira Assets, attributes belong to their type — attribute "Name" on
|
|
17
|
+
"Hardware Server" is a different attribute from "Name" on
|
|
18
|
+
"Laptop", with different ids — so the GUI presents a single
|
|
19
|
+
dropdown over all (type, attribute) pairs and that's what we store.
|
|
20
|
+
"""
|
|
21
|
+
target = db.StringField(required=True)
|
|
22
|
+
value = db.StringField()
|
|
23
|
+
meta = {
|
|
24
|
+
'strict': False,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
def object_type_id(self):
|
|
29
|
+
"""Convenience accessor: int part of ``target``."""
|
|
30
|
+
if not self.target or '|' not in self.target:
|
|
31
|
+
return None
|
|
32
|
+
try:
|
|
33
|
+
return int(self.target.split('|', 1)[0])
|
|
34
|
+
except (ValueError, TypeError):
|
|
35
|
+
return None
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def jira_attribute(self):
|
|
39
|
+
"""Convenience accessor: name part of ``target``."""
|
|
40
|
+
if not self.target or '|' not in self.target:
|
|
41
|
+
return ''
|
|
42
|
+
return self.target.split('|', 1)[1]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class JiraExportRule(db.Document):
|
|
46
|
+
"""
|
|
47
|
+
Defines which hosts get exported to Jira Cloud Assets and which
|
|
48
|
+
fields are written.
|
|
49
|
+
|
|
50
|
+
The set of target object types follows from the rule's outcomes
|
|
51
|
+
(one outcome = one field on one object type) — a single rule may
|
|
52
|
+
cover several object types at once.
|
|
53
|
+
"""
|
|
54
|
+
name = db.StringField(required=True, unique=True)
|
|
55
|
+
documentation = db.StringField()
|
|
56
|
+
|
|
57
|
+
condition_typ = db.StringField(choices=rule_types)
|
|
58
|
+
conditions = db.ListField(field=db.EmbeddedDocumentField(document_type='FullCondition'))
|
|
59
|
+
render_full_conditions = db.StringField() # GUI preview helper
|
|
60
|
+
|
|
61
|
+
outcomes = db.ListField(field=db.EmbeddedDocumentField(document_type='JiraExportOutcome'))
|
|
62
|
+
render_jira_export_outcome = db.StringField() # GUI preview helper
|
|
63
|
+
|
|
64
|
+
last_match = db.BooleanField(default=False)
|
|
65
|
+
enabled = db.BooleanField(default=True)
|
|
66
|
+
sort_field = db.IntField(default=0)
|
|
67
|
+
meta = {
|
|
68
|
+
'strict': False,
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class JiraCloudRewriteAttributeRule(db.Document):
|
|
73
|
+
"""
|
|
74
|
+
Rewrite host attribute keys/values before the export rule engine
|
|
75
|
+
evaluates them — mirrors the Checkmk / Netbox rewrite pattern.
|
|
76
|
+
"""
|
|
77
|
+
name = db.StringField()
|
|
78
|
+
documentation = db.StringField()
|
|
79
|
+
|
|
80
|
+
condition_typ = db.StringField(choices=rule_types)
|
|
81
|
+
conditions = db.ListField(field=db.EmbeddedDocumentField(document_type='FullCondition'))
|
|
82
|
+
render_full_conditions = db.StringField() # GUI preview helper
|
|
83
|
+
|
|
84
|
+
outcomes = db.ListField(
|
|
85
|
+
field=db.EmbeddedDocumentField(document_type='AttributeRewriteAction'))
|
|
86
|
+
render_attribute_rewrite = db.StringField() # GUI preview helper
|
|
87
|
+
|
|
88
|
+
last_match = db.BooleanField(default=False)
|
|
89
|
+
enabled = db.BooleanField(default=True)
|
|
90
|
+
sort_field = db.IntField(default=0)
|
|
91
|
+
meta = {
|
|
92
|
+
'strict': False,
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class JiraCloudFilterRule(db.Document):
|
|
97
|
+
"""
|
|
98
|
+
Exclude hosts from the Jira Cloud export.
|
|
99
|
+
|
|
100
|
+
Mirrors the Checkmk pattern: hosts matching this rule (any
|
|
101
|
+
``ignore_hosts`` filter action) are dropped by the Plugin base
|
|
102
|
+
class's ``get_attributes`` before the export rule engine sees them.
|
|
103
|
+
"""
|
|
104
|
+
name = db.StringField(required=True, unique=True)
|
|
105
|
+
documentation = db.StringField()
|
|
106
|
+
condition_typ = db.StringField(choices=rule_types)
|
|
107
|
+
conditions = db.ListField(field=db.EmbeddedDocumentField(document_type="FullCondition"))
|
|
108
|
+
render_full_conditions = db.StringField() # GUI preview helper
|
|
109
|
+
|
|
110
|
+
outcomes = db.ListField(field=db.EmbeddedDocumentField(document_type="FilterAction"))
|
|
111
|
+
render_filter_outcome = db.StringField() # GUI preview helper
|
|
112
|
+
|
|
113
|
+
last_match = db.BooleanField(default=False)
|
|
114
|
+
enabled = db.BooleanField(default=True)
|
|
115
|
+
sort_field = db.IntField(default=0)
|
|
116
|
+
|
|
117
|
+
meta = {
|
|
118
|
+
'strict': False,
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class JiraSchemaAttribute(db.EmbeddedDocument):
|
|
123
|
+
"""One attribute belonging to an object type."""
|
|
124
|
+
attribute_id = db.IntField(required=True)
|
|
125
|
+
name = db.StringField(required=True)
|
|
126
|
+
type_name = db.StringField()
|
|
127
|
+
editable = db.BooleanField(default=True)
|
|
128
|
+
meta = {
|
|
129
|
+
'strict': False,
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class JiraSchemaObjectType(db.EmbeddedDocument):
|
|
134
|
+
"""One Jira Assets object type with its attributes."""
|
|
135
|
+
object_type_id = db.IntField(required=True)
|
|
136
|
+
name = db.StringField(required=True)
|
|
137
|
+
schema_id = db.IntField()
|
|
138
|
+
schema_name = db.StringField()
|
|
139
|
+
attributes = db.ListField(field=db.EmbeddedDocumentField(document_type='JiraSchemaAttribute'))
|
|
140
|
+
meta = {
|
|
141
|
+
'strict': False,
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class JiraSchemaCache(db.Document):
|
|
146
|
+
"""
|
|
147
|
+
Per-account snapshot of the Jira Cloud Assets schema.
|
|
148
|
+
|
|
149
|
+
Populated by `cmdbsyncer jira sync_schema <account>` and consumed by
|
|
150
|
+
the export plugin (attribute-name → id resolution, validation) and
|
|
151
|
+
by the GUI (autocomplete suggestions in the rule form).
|
|
152
|
+
"""
|
|
153
|
+
account = db.StringField(required=True, unique=True)
|
|
154
|
+
updated = db.DateTimeField()
|
|
155
|
+
object_types = db.ListField(
|
|
156
|
+
field=db.EmbeddedDocumentField(document_type='JiraSchemaObjectType'))
|
|
157
|
+
meta = {
|
|
158
|
+
'strict': False,
|
|
159
|
+
}
|
{cmdbsyncer-4.1.0.dev14 → cmdbsyncer-4.1.0.dev15}/application/plugins/jira_cloud/plugin.json
RENAMED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
"account_presets" : {
|
|
8
8
|
},
|
|
9
9
|
"account_custom_field_presets": {
|
|
10
|
-
"workspace_id": "
|
|
11
|
-
"ql_query": "
|
|
10
|
+
"workspace_id": "00000000-0000-0000-0000-000000000000",
|
|
11
|
+
"ql_query": "objectType = \"Server\"",
|
|
12
12
|
"verify_cert": "True",
|
|
13
13
|
"ca_cert_chain": "",
|
|
14
14
|
"ca_root_cert": ""
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Jira Cloud Export Rule
|
|
3
|
+
"""
|
|
4
|
+
from application.modules.rule.rule import Rule
|
|
5
|
+
from application.helpers.syncer_jinja import render_jinja
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class JiraExportAttributeRule(Rule):
|
|
9
|
+
"""
|
|
10
|
+
Resolves the per-host outcome of one or more JiraExportRule rows.
|
|
11
|
+
|
|
12
|
+
All enabled rules are loaded into a single engine instance so the
|
|
13
|
+
export plugin can iterate hosts once and let the engine merge every
|
|
14
|
+
matching rule's outcomes per host. Outcomes are grouped by Jira
|
|
15
|
+
object type id; missing objects are always created (filter out
|
|
16
|
+
hosts you don't want exported via a JiraCloudFilterRule).
|
|
17
|
+
"""
|
|
18
|
+
name = "Jira Cloud -> Export Attributes"
|
|
19
|
+
|
|
20
|
+
def add_outcomes(self, _rule, rule_outcomes, outcomes):
|
|
21
|
+
"""
|
|
22
|
+
Build per-type field bundles.
|
|
23
|
+
|
|
24
|
+
Output shape::
|
|
25
|
+
|
|
26
|
+
outcomes['fields_by_type'] = {
|
|
27
|
+
"<type_id>": {"<attr_name>": "<rendered_value>", ...},
|
|
28
|
+
...
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
Mongo DictFields require string keys, so ``object_type_id`` is
|
|
32
|
+
stored as a string and converted back to int by the consumer.
|
|
33
|
+
Empty/None-rendered values are dropped so an unset host attribute
|
|
34
|
+
does not blank out a populated field in Jira.
|
|
35
|
+
"""
|
|
36
|
+
outcomes.setdefault('fields_by_type', {})
|
|
37
|
+
for outcome in rule_outcomes:
|
|
38
|
+
target = (outcome.get('target') or '').strip()
|
|
39
|
+
if '|' not in target:
|
|
40
|
+
continue
|
|
41
|
+
type_id_str, attr = target.split('|', 1)
|
|
42
|
+
attr = attr.strip()
|
|
43
|
+
if not type_id_str or not attr:
|
|
44
|
+
continue
|
|
45
|
+
template = outcome.get('value') or ''
|
|
46
|
+
rendered = render_jinja(template, mode="nullify", **self.attributes)
|
|
47
|
+
rendered = (rendered or '').strip()
|
|
48
|
+
if rendered in ('', 'None'):
|
|
49
|
+
continue
|
|
50
|
+
outcomes['fields_by_type'].setdefault(type_id_str, {})[attr] = rendered
|
|
51
|
+
return outcomes
|