From 8d3957587ce262594e78b32c28db92aead7b797d Mon Sep 17 00:00:00 2001 From: Xiangce Liu Date: Mon, 29 Sep 2025 16:55:56 +0800 Subject: [PATCH] feat(spec/parser): new spec and parser for AnsibleTelemetry - New spec to collect command "/usr/share/ansible/telemetry/telemetry.py" - New AnsibleTelemetry to parse the command - Jira: RHINENG-20964 Signed-off-by: Xiangce Liu --- docs/shared_parsers_catalog/ansible.rst | 3 ++ insights/parsers/ansible.py | 61 +++++++++++++++++++++++++ insights/specs/__init__.py | 13 ++---- insights/specs/default.py | 5 +- insights/tests/parsers/test_ansible.py | 58 +++++++++++++++++++++++ 5 files changed, 130 insertions(+), 10 deletions(-) create mode 100644 docs/shared_parsers_catalog/ansible.rst create mode 100644 insights/parsers/ansible.py create mode 100644 insights/tests/parsers/test_ansible.py diff --git a/docs/shared_parsers_catalog/ansible.rst b/docs/shared_parsers_catalog/ansible.rst new file mode 100644 index 000000000..d5ec8b2d1 --- /dev/null +++ b/docs/shared_parsers_catalog/ansible.rst @@ -0,0 +1,3 @@ +.. automodule:: insights.parsers.ansible + :members: + :show-inheritance: diff --git a/insights/parsers/ansible.py b/insights/parsers/ansible.py new file mode 100644 index 000000000..1e3eeeee2 --- /dev/null +++ b/insights/parsers/ansible.py @@ -0,0 +1,61 @@ +""" +Ansible - Parsers relates to Ansible +==================================== + +Below Parser is included in this module + +AnsibleTelemetry - command "/usr/share/ansible/telemetry/telemetry.py" +---------------------------------------------------------------------- +""" + +from insights import CommandParser, JSONParser, parser +from insights.specs import Specs + + +@parser(Specs.ansible_telemetry) +class AnsibleTelemetry(CommandParser, JSONParser): + """ + Parse the output of command "/usr/share/ansible/telemetry/telemetry.py". + + Sample output of the command is in JSON format:: + + { + "collections":{ + "ansible.builtin":{ + "resources":{ + "action":{ + "ansible.builtin.add_host":78, + "ansible.builtin.uri":147, + "ansible.builtin.set_fact":96, + "ansible.builtin.debug":30, + "ansible.builtin.find":2, + "ansible.builtin.file":6, + "ansible.builtin.template":2, + "ansible.builtin.command":13 + }, + "connection":{ + "ansible.builtin.local":113, + "ansible.builtin.ssh":290 + } + }, + "version":"*" + } + }, + "ansible_core":{ + "version":"2.18.9rc1" + }, + "hosts":{ + "count":44 + } + } + + Examples: + >>> type(ansible_telemetry) + + >>> ansible_telemetry['collections']['ansible.builtin']['version'] == '*' + True + >>> ansible_telemetry['ansible_core']['version'] == '2.18.9rc1' + True + """ + + pass diff --git a/insights/specs/__init__.py b/insights/specs/__init__.py index 0255c9eaf..0b9e2d68a 100644 --- a/insights/specs/__init__.py +++ b/insights/specs/__init__.py @@ -20,6 +20,7 @@ class Specs(SpecSet): malware_detection = RegistryPoint() # Regular collection specs + ansible_telemetry = RegistryPoint() abrt_ccpp_conf = RegistryPoint( filterable=True, no_obfuscate=['hostname', 'ipv4', 'ipv6', 'mac'] ) @@ -439,12 +440,8 @@ class Specs(SpecSet): lsblk_pairs = RegistryPoint() lscpu = RegistryPoint(no_obfuscate=['hostname', 'ipv4', 'ipv6', 'mac']) lsinitrd = RegistryPoint(filterable=True, no_obfuscate=['ipv4', 'ipv6', 'mac']) - lsinitrd_kdump_image = RegistryPoint( - filterable=True, no_obfuscate=['ipv4', 'ipv6', 'mac'] - ) - lsinitrd_lvm_conf = RegistryPoint( - filterable=True, no_obfuscate=['ipv4', 'ipv6', 'mac'] - ) + lsinitrd_kdump_image = RegistryPoint(filterable=True, no_obfuscate=['ipv4', 'ipv6', 'mac']) + lsinitrd_lvm_conf = RegistryPoint(filterable=True, no_obfuscate=['ipv4', 'ipv6', 'mac']) lsmod = RegistryPoint(no_obfuscate=['hostname', 'ipv4', 'ipv6', 'mac']) lsof = RegistryPoint(filterable=True) lspci = RegistryPoint(no_obfuscate=['hostname', 'ipv4', 'ipv6', 'mac']) @@ -815,9 +812,7 @@ class Specs(SpecSet): no_obfuscate=['hostname', 'ipv4', 'ipv6', 'mac'] ) subscription_manager_status = RegistryPoint(no_obfuscate=['hostname', 'ipv4', 'ipv6', 'mac']) - subscription_manager_syspurpose = RegistryPoint( - no_obfuscate=['ipv4', 'ipv6', 'mac'] - ) + subscription_manager_syspurpose = RegistryPoint(no_obfuscate=['ipv4', 'ipv6', 'mac']) sudoers = RegistryPoint(multi_output=True, filterable=True) swift_conf = RegistryPoint() swift_log = RegistryPoint(filterable=True) diff --git a/insights/specs/default.py b/insights/specs/default.py index 18b1a3704..80d494097 100644 --- a/insights/specs/default.py +++ b/insights/specs/default.py @@ -118,6 +118,7 @@ class DefaultSpecs(Specs): malware_detection = malware_detection_ds.malware_detection # Regular collection specs + ansible_telemetry = simple_command("/usr/share/ansible/telemetry/telemetry.py") abrt_ccpp_conf = simple_file("/etc/abrt/plugins/CCpp.conf") abrt_status_bare = simple_command("/usr/bin/abrt status --bare=True") alternatives_display_python = simple_command("/usr/sbin/alternatives --display python") @@ -316,7 +317,9 @@ class DefaultSpecs(Specs): fapolicyd_rules = glob_file(r"/etc/fapolicyd/rules.d/*.rules") fcoeadm_i = simple_command("/usr/sbin/fcoeadm -i") files_dirs_number = ls.files_dirs_number - filefrag = simple_command("/sbin/filefrag /boot/grub2/grubenv /boot/initramfs*.img /boot/vmlinuz*", keep_rc=True) + filefrag = simple_command( + "/sbin/filefrag /boot/grub2/grubenv /boot/initramfs*.img /boot/vmlinuz*", keep_rc=True + ) findmnt_lo_propagation = simple_command("/bin/findmnt -lo+PROPAGATION") firewall_cmd_list_all_zones = simple_command("/usr/bin/firewall-cmd --list-all-zones") firewalld_conf = simple_file("/etc/firewalld/firewalld.conf") diff --git a/insights/tests/parsers/test_ansible.py b/insights/tests/parsers/test_ansible.py new file mode 100644 index 000000000..5154ee685 --- /dev/null +++ b/insights/tests/parsers/test_ansible.py @@ -0,0 +1,58 @@ +import doctest +import pytest + +from insights.core.exceptions import ContentException +from insights.parsers import ansible +from insights.tests import context_wrap + +AT_INPUT_NG = """ +no such file or directory: /usr/share/ansible/telemetry/telemetry.py +""" + +AT_INPUT = """ +{ + "collections":{ + "ansible.builtin":{ + "resources":{ + "action":{ + "ansible.builtin.add_host":78, + "ansible.builtin.uri":147, + "ansible.builtin.set_fact":96, + "ansible.builtin.debug":30, + "ansible.builtin.find":2, + "ansible.builtin.file":6, + "ansible.builtin.template":2, + "ansible.builtin.command":13 + }, + "connection":{ + "ansible.builtin.local":113, + "ansible.builtin.ssh":290 + } + }, + "version":"*" + } + }, + "ansible_core":{ + "version":"2.18.9rc1" + }, + "hosts":{ + "count":44 + } +} +""".strip() + + +def test_ansible_telemetry(): + ret = ansible.AnsibleTelemetry(context_wrap(AT_INPUT)) + assert ret['hosts']['count'] == 44 + + with pytest.raises(ContentException): + ansible.AnsibleTelemetry(context_wrap(AT_INPUT_NG)) + + +def test_doc_examples(): + env = { + 'ansible_telemetry': ansible.AnsibleTelemetry(context_wrap(AT_INPUT)), + } + failed, total = doctest.testmod(ansible, globs=env) + assert failed == 0