ansible-collections / community.zabbix

Zabbix Ansible modules
http://galaxy.ansible.com/community/zabbix
Other
329 stars 285 forks source link

Module zabbix_template fails with "connection error occurred: string indices must be integers" when template name contains - (hyphen) or space #888

Closed HonzaKoren closed 1 year ago

HonzaKoren commented 1 year ago
SUMMARY

When playbook task contains a space or - in its value, the task end up with error "connection error occurred: string indices must be integers". Other variable values work as expected.

ISSUE TYPE
COMPONENT NAME

community.zabbix.zabbix_template

ANSIBLE VERSION
ansible [core 2.14.2]
  config file = /home/honza/Projects/CEZ/Zabbix_Grafana/grafana-zabbix-integration-service/ansible.cfg
  configured module search path = ['/home/honza/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/honza/.virtualenvs/cez_loader/lib/python3.10/site-packages/ansible
  ansible collection location = /home/honza/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/honza/.virtualenvs/cez_loader/bin/ansible
  python version = 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0] (/home/honza/.virtualenvs/cez_loader/bin/python)
  jinja version = 3.1.2
  libyaml = True
CONFIGURATION
CONFIG_FILE() = /home/honza/Projects/CEZ/Zabbix_Grafana/grafana-zabbix-integration-service/ansible.cfg
DEFAULT_HOST_LIST(/home/honza/Projects/CEZ/Zabbix_Grafana/grafana-zabbix-integration-service/ansible.cfg) = ['/home/honza/Projects/CEZ/Zabbix_Grafana/grafana-zabbix-integration-service/inventory.py']
OS / ENVIRONMENT / Zabbix Version

Linux, Ubuntu Focal Python3 virtual environment Python 3.10.6 ansible==7.1.0 ansible-core==2.14.2 certifi==2022.12.7 cffi==1.15.1 charset-normalizer==2.1.1 cryptography==39.0.0 flake8==6.0.0 idna==3.4 Jinja2==3.1.2 MarkupSafe==2.1.2 mccabe==0.7.0 packaging==23.0 pycodestyle==2.10.0 pycparser==2.21 pyflakes==3.0.1 PyYAML==6.0 pyzabbix==1.2.1 requests==2.28.1 resolvelib==0.8.1 urllib3==1.26.14

/home/honza/.virtualenvs/cez_loader/lib/python3.10/site-packages/ansible_collections

Collection Version


amazon.aws 5.1.0
ansible.netcommon 4.1.0
ansible.posix 1.4.0
ansible.utils 2.8.0
ansible.windows 1.12.0 arista.eos 6.0.0
awx.awx 21.10.0 azure.azcollection 1.14.0 check_point.mgmt 4.0.0
chocolatey.chocolatey 1.3.1
cisco.aci 2.3.0
cisco.asa 4.0.0
cisco.dnac 6.6.1
cisco.intersight 1.0.22 cisco.ios 4.0.0
cisco.iosxr 4.0.3
cisco.ise 2.5.9
cisco.meraki 2.13.0 cisco.mso 2.1.0
cisco.nso 1.0.3
cisco.nxos 4.0.1
cisco.ucs 1.8.0
cloud.common 2.1.2
cloudscale_ch.cloud 2.2.3
community.aws 5.0.0
community.azure 2.0.0
community.ciscosmb 1.0.5
community.crypto 2.9.0
community.digitalocean 1.22.0 community.dns 2.4.2
community.docker 3.3.1
community.fortios 1.0.0
community.general 6.1.0
community.google 1.0.0
community.grafana 1.5.3
community.hashi_vault 4.0.0
community.hrobot 1.6.0
community.libvirt 1.2.0
community.mongodb 1.4.2
community.mysql 3.5.1
community.network 5.0.0
community.okd 2.2.0
community.postgresql 2.3.1
community.proxysql 1.4.0
community.rabbitmq 1.2.3
community.routeros 2.5.0
community.sap 1.0.0
community.sap_libs 1.4.0
community.skydive 1.0.0
community.sops 1.5.0
community.vmware 3.2.0
community.windows 1.11.1 community.zabbix 1.9.0
containers.podman 1.10.1 cyberark.conjur 1.2.0
cyberark.pas 1.0.14 dellemc.enterprise_sonic 2.0.0
dellemc.openmanage 6.3.0
dellemc.os10 1.1.1
dellemc.os6 1.0.7
dellemc.os9 1.0.4
f5networks.f5_modules 1.21.0 fortinet.fortimanager 2.1.7
fortinet.fortios 2.2.1
frr.frr 2.0.0
gluster.gluster 1.0.2
google.cloud 1.0.2
grafana.grafana 1.1.0
hetzner.hcloud 1.9.0
hpe.nimble 1.1.4
ibm.qradar 2.1.0
ibm.spectrum_virtualize 1.10.0 infinidat.infinibox 1.3.12 infoblox.nios_modules 1.4.1
inspur.ispim 1.2.0
inspur.sm 2.3.0
junipernetworks.junos 4.1.0
kubernetes.core 2.3.2
lowlydba.sqlserver 1.2.1
mellanox.onyx 1.0.0
netapp.aws 21.7.0 netapp.azure 21.10.0 netapp.cloudmanager 21.21.0 netapp.elementsw 21.7.0 netapp.ontap 22.0.1 netapp.storagegrid 21.11.1 netapp.um_info 21.8.0 netapp_eseries.santricity 1.3.1
netbox.netbox 3.9.0
ngine_io.cloudstack 2.3.0
ngine_io.exoscale 1.0.0
ngine_io.vultr 1.1.2
openstack.cloud 1.10.0 openvswitch.openvswitch 2.1.0
ovirt.ovirt 2.4.1
purestorage.flasharray 1.15.0 purestorage.flashblade 1.10.0 purestorage.fusion 1.2.0
sensu.sensu_go 1.13.1 splunk.es 2.1.0
t_systems_mms.icinga_director 1.31.4 theforeman.foreman 3.7.0
vmware.vmware_rest 2.2.0
vultr.cloud 1.3.1
vyos.vyos 4.0.0
wti.remote 1.0.4

/home/honza/.ansible/collections/ansible_collections

Collection Version


ansible.netcommon 4.1.0
ansible.posix 1.5.1
ansible.utils 2.9.0
ansible.windows 1.13.0 community.general 6.3.0
community.mysql 3.5.1
community.postgresql 2.3.2
community.zabbix 1.9.1

STEPS TO REPRODUCE

Simple playbook to tag existing template (template of such name must exists).

---
- name: Configure Zabbix hosts and groups according to CMDB export
  hosts: all
  become: no
  gather_facts: no

  vars:
    ansible_network_os: community.zabbix.zabbix
    ansible_connection: httpapi
    ansible_httpapi_port: 443
    ansible_httpapi_use_ssl: true
    ansible_httpapi_validate_certs: false
    ansible_zabbix_url_path: 'zabbix'
    ansible_host: "{{ lookup('ansible.builtin.env', 'ZABBIX_HOST') }}"
    ansible_user: "{{ lookup('ansible.builtin.env', 'ZABBIX_USER') }}"
    ansible_httpapi_pass: "{{ lookup('ansible.builtin.env', 'ZABBIX_PASS') }}"

  tasks:
  block:
  - name: Update templates to provide required tags
    community.zabbix.zabbix_template:
      # template_name: '{{item.name}}'
      # tags: '{{item.tags}}'
      template_name: 'Template-RHEL_Base'
      tags:
        - tag: class
          value: Linux
      state: present
EXPECTED RESULTS

Template modification - template is tagged as requested.

ACTUAL RESULTS
TASK [Update templates to provide required tags] *******************************************************************************************************************************************************************************************
task path: /home/honza/Projects/CEZ/Zabbix_Grafana/grafana-zabbix-integration-service/integration_service.yml:28
redirecting (type: connection) ansible.builtin.httpapi to ansible.netcommon.httpapi
Loading collection ansible.netcommon from /home/honza/.ansible/collections/ansible_collections/ansible/netcommon
<zbxtt.cezdata.corp> attempting to start connection
<zbxtt.cezdata.corp> using connection plugin ansible.netcommon.httpapi
Found ansible-connection at path /home/honza/.virtualenvs/cez_loader/bin/ansible-connection
<zbxtt.cezdata.corp> found existing local domain socket, using it!
<zbxtt.cezdata.corp> Web Services: POST https://zbxtt.cezdata.corp:443//zabbix/api_jsonrpc.php
<zbxtt.cezdata.corp> Web Services: POST https://zbxtt.cezdata.corp:443//zabbix/api_jsonrpc.php
<zbxtt.cezdata.corp> updating play_context for connection
<zbxtt.cezdata.corp> 
<zbxtt.cezdata.corp> local domain socket path is /home/honza/.ansible/pc/23c14fbecc
<zbxtt.cezdata.corp> ESTABLISH LOCAL CONNECTION FOR USER: honza
<zbxtt.cezdata.corp> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/honza/.ansible/tmp/ansible-local-19509453hu3tc4r `"&& mkdir "` echo /home/honza/.ansible/tmp/ansible-local-19509453hu3tc4r/ansible-tmp-1675265359.0870333-1951124-29449267759450 `" && echo ansible-tmp-1675265359.0870333-1951124-29449267759450="` echo /home/honza/.ansible/tmp/ansible-local-19509453hu3tc4r/ansible-tmp-1675265359.0870333-1951124-29449267759450 `" ) && sleep 0'
Including module_utils file ansible/__init__.py
Including module_utils file ansible/module_utils/__init__.py
Including module_utils file ansible/module_utils/_text.py
Including module_utils file ansible/module_utils/basic.py
Including module_utils file ansible/module_utils/common/_collections_compat.py
Including module_utils file ansible/module_utils/common/__init__.py
Including module_utils file ansible/module_utils/common/_json_compat.py
Including module_utils file ansible/module_utils/common/_utils.py
Including module_utils file ansible/module_utils/common/arg_spec.py
Including module_utils file ansible/module_utils/common/file.py
Including module_utils file ansible/module_utils/common/locale.py
Including module_utils file ansible/module_utils/common/parameters.py
Including module_utils file ansible/module_utils/common/collections.py
Including module_utils file ansible/module_utils/common/process.py
Including module_utils file ansible/module_utils/common/sys_info.py
Including module_utils file ansible/module_utils/common/text/converters.py
Including module_utils file ansible/module_utils/common/text/__init__.py
Including module_utils file ansible/module_utils/common/text/formatters.py
Including module_utils file ansible/module_utils/common/validation.py
Including module_utils file ansible/module_utils/common/warnings.py
Including module_utils file ansible/module_utils/compat/selectors.py
Including module_utils file ansible/module_utils/compat/__init__.py
Including module_utils file ansible/module_utils/compat/_selectors2.py
Including module_utils file ansible/module_utils/compat/selinux.py
Including module_utils file ansible/module_utils/distro/__init__.py
Including module_utils file ansible/module_utils/distro/_distro.py
Including module_utils file ansible/module_utils/errors.py
Including module_utils file ansible/module_utils/parsing/convert_bool.py
Including module_utils file ansible/module_utils/parsing/__init__.py
Including module_utils file ansible/module_utils/pycompat24.py
Including module_utils file ansible/module_utils/six/__init__.py
Including module_utils file ansible_collections/community/zabbix/plugins/module_utils/base.py
Including module_utils file ansible_collections/__init__.py
Including module_utils file ansible_collections/community/__init__.py
Including module_utils file ansible_collections/community/zabbix/__init__.py
Including module_utils file ansible_collections/community/zabbix/plugins/__init__.py
Including module_utils file ansible_collections/community/zabbix/plugins/module_utils/__init__.py
Including module_utils file ansible_collections/community/zabbix/plugins/module_utils/api_request.py
Including module_utils file ansible/module_utils/connection.py
Including module_utils file ansible/module_utils/common/json.py
Including module_utils file ansible/module_utils/urls.py
Including module_utils file ansible/module_utils/compat/typing.py
Including module_utils file ansible_collections/community/zabbix/plugins/module_utils/helpers.py
Including module_utils file ansible_collections/community/zabbix/plugins/module_utils/version.py
Including module_utils file ansible_collections/community/zabbix/plugins/module_utils/_version.py
Including module_utils file ansible_collections/community/zabbix/plugins/module_utils/wrappers.py
Using module file /home/honza/.ansible/collections/ansible_collections/community/zabbix/plugins/modules/zabbix_template.py
<zbxtt.cezdata.corp> PUT /home/honza/.ansible/tmp/ansible-local-19509453hu3tc4r/tmpaqen7czg TO /home/honza/.ansible/tmp/ansible-local-19509453hu3tc4r/ansible-tmp-1675265359.0870333-1951124-29449267759450/AnsiballZ_zabbix_template.py
<zbxtt.cezdata.corp> EXEC /bin/sh -c 'chmod u+x /home/honza/.ansible/tmp/ansible-local-19509453hu3tc4r/ansible-tmp-1675265359.0870333-1951124-29449267759450/ /home/honza/.ansible/tmp/ansible-local-19509453hu3tc4r/ansible-tmp-1675265359.0870333-1951124-29449267759450/AnsiballZ_zabbix_template.py && sleep 0'
<zbxtt.cezdata.corp> EXEC /bin/sh -c '/home/honza/.virtualenvs/cez_loader/bin/python /home/honza/.ansible/tmp/ansible-local-19509453hu3tc4r/ansible-tmp-1675265359.0870333-1951124-29449267759450/AnsiballZ_zabbix_template.py && sleep 0'
<zbxtt.cezdata.corp> EXEC /bin/sh -c 'rm -f -r /home/honza/.ansible/tmp/ansible-local-19509453hu3tc4r/ansible-tmp-1675265359.0870333-1951124-29449267759450/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
  File "/tmp/ansible_community.zabbix.zabbix_template_payload_id2zel2n/ansible_community.zabbix.zabbix_template_payload.zip/ansible_collections/community/zabbix/plugins/module_utils/api_request.py", line 29, in _httpapi_error_handle
    code, response = self.connection.send_request(data=payload)
  File "/tmp/ansible_community.zabbix.zabbix_template_payload_id2zel2n/ansible_community.zabbix.zabbix_template_payload.zip/ansible/module_utils/connection.py", line 200, in __rpc__
    raise ConnectionError(to_text(msg, errors='surrogate_then_replace'), code=code)
fatal: [ca00253]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "clear_templates": null,
            "dump_format": "json",
            "http_login_password": null,
            "http_login_user": null,
            "link_templates": null,
            "login_password": null,
            "login_user": null,
            "macros": null,
            "omit_date": false,
            "server_url": null,
            "state": "present",
            "tags": [
                {
                    "tag": "class",
                    "value": "Linux"
                }
            ],
            "template_groups": null,
            "template_json": null,
            "template_name": "Template-RHEL_Base",
            "template_xml": null,
            "timeout": null,
            "validate_certs": null
        }
    },
    "msg": "connection error occurred: string indices must be integers"
}

The full traceback is: File "/tmp/ansible_community.zabbix.zabbix_template_payload_t9r5agev/ansible_community.zabbix.zabbix_template_payload.zip/ansible_collections/community/zabbix/plugins/module_utils/api_request.py", line 29, in _httpapi_error_handle code, response = self.connection.send_request(data=payload) File "/tmp/ansible_community.zabbix.zabbix_template_payload_t9r5agev/ansible_community.zabbix.zabbix_template_payload.zip/ansible/module_utils/connection.py", line 200, in rpc raise ConnectionError(to_text(msg, errors='surrogate_then_replace'), code=code) fatal: [ca00253]: FAILED! => { "changed": false, "invocation": { "module_args": { "clear_templates": null, "dump_format": "json", "http_login_password": null, "http_login_user": null, "link_templates": null, "login_password": null, "login_user": null, "macros": null, "omit_date": false, "server_url": null, "state": "present", "tags": [ { "tag": "class", "value": "Linux" } ], "template_groups": null, "template_json": null, "template_name": "Template-RHEL_Base", "template_xml": null, "timeout": null, "validate_certs": null } }, "msg": "connection error occurred: string indices must be integers" }

BGmot commented 1 year ago

I cannot reproduce. What version of Zabbix?

BGmot commented 1 year ago

When playbook task contains a space or - in its value, the task end up with error "connection error occurred: string indices must be integers". Other variable values work as expected.

Can you please clarify what you mean by "value of playbook task" here? What code works?

niklasweimann commented 1 year ago

I suspect that this behavior is not tight to the _templatename attribute. I'm using the _templatexml attribute with a jinja lookup like so:

    template_xml: "{{ lookup('template', '{{ item }}') if 'j2' in item else lookup('file', '{{ item }}') }}"

Which worked fine until i switched to the new httpapi-plugin. After switching to the new plugin i could no longer import any template with a xml file extension. Resulting in the following error:

failed: [host] (item=templates/template/rabbit_mq_node_by_zabbix_agent2.xml) => {"ansible_loop_var": "item", "changed": false, "item": "templates/template/rabbit_mq_node_by_zabbix_agent2.xml", "msg": "connection error occurred: string indices must be integers"}

So this works with the newest version:

- name: Import templates
  local_action:
    module: community.zabbix.zabbix_template
    server_url: "https://{{ zabbix_host_url }}"
    login_user: "{{ zabbix_admin_user }}"
    login_password: "{{ zabbix_admin_user_password }}"
    template_groups:
      - Zabbix servers
    template_xml: "{{ lookup('template', '{{ item }}') if 'j2' in item else lookup('file', '{{ item }}') }}"
    state: present
  loop: "{{ result_list }}"

This does not work (for lookup == file):

- name: Init connection parameters
  ansible.builtin.set_fact:
    ansible_become: false
    ansible_network_os: community.zabbix.zabbix
    ansible_connection: httpapi
    ansible_httpapi_port: 443
    ansible_httpapi_use_ssl: true
    ansible_httpapi_validate_certs: true
    ansible_user: "{{ zabbix_admin_user }}"
    ansible_host: "{{ zabbix_host_url }}"
    ansible_httpapi_pass: "{{ zabbix_admin_user_password }}"
- name: Import templates
  community.zabbix.zabbix_template:
    template_groups:
      - Zabbix servers
    template_xml: "{{ lookup('template', '{{ item }}') if 'j2' in item else lookup('file', '{{ item }}') }}"
    state: present
  loop: "{{ result_list }}"

Unfortunately I cloud not determine the root cause for this behavior. 😢 I switched this task back to local_action and the old way (server_url, login_user, login_password) which worked fine for now.

HonzaKoren commented 1 year ago

I cannot reproduce. What version of Zabbix?

6.0 LTS

HonzaKoren commented 1 year ago

When playbook task contains a space or - in its value, the task end up with error "connection error occurred: string indices must be integers". Other variable values work as expected.

Can you please clarify what you mean by "value of playbook task" here? What code works?

  - name: Update templates to provide required tags
    community.zabbix.zabbix_template:
      # template_name: '{{item.name}}'
      # tags: '{{item.tags}}'
      template_name: 'Template-RHEL_Base'
      tags:
        - tag: class
          value: Linux
      state: present

If I use another template name, it passes.

---
  - name: Update templates to provide required tags
    community.zabbix.zabbix_template:
      # template_name: '{{item.name}}'
      # tags: '{{item.tags}}'
      template_name: 'Template_RHEL_Base'
      tags:
        - tag: class
          value: Linux
      state: present
HonzaKoren commented 1 year ago

I suspect that this behavior is not tight to the _templatename attribute. I'm using the _templatexml attribute with a jinja lookup like so:

    template_xml: "{{ lookup('template', '{{ item }}') if 'j2' in item else lookup('file', '{{ item }}') }}"

Which worked fine until i switched to the new httpapi-plugin. After switching to the new plugin i could no longer import any template with a xml file extension. Resulting in the following error:

failed: [host] (item=templates/template/rabbit_mq_node_by_zabbix_agent2.xml) => {"ansible_loop_var": "item", "changed": false, "item": "templates/template/rabbit_mq_node_by_zabbix_agent2.xml", "msg": "connection error occurred: string indices must be integers"}

So this works with the newest version:

- name: Import templates
  local_action:
    module: community.zabbix.zabbix_template
    server_url: "https://{{ zabbix_host_url }}"
    login_user: "{{ zabbix_admin_user }}"
    login_password: "{{ zabbix_admin_user_password }}"
    template_groups:
      - Zabbix servers
    template_xml: "{{ lookup('template', '{{ item }}') if 'j2' in item else lookup('file', '{{ item }}') }}"
    state: present
  loop: "{{ result_list }}"

This does not work (for lookup == file):

- name: Init connection parameters
  ansible.builtin.set_fact:
    ansible_become: false
    ansible_network_os: community.zabbix.zabbix
    ansible_connection: httpapi
    ansible_httpapi_port: 443
    ansible_httpapi_use_ssl: true
    ansible_httpapi_validate_certs: true
    ansible_user: "{{ zabbix_admin_user }}"
    ansible_host: "{{ zabbix_host_url }}"
    ansible_httpapi_pass: "{{ zabbix_admin_user_password }}"
- name: Import templates
  community.zabbix.zabbix_template:
    template_groups:
      - Zabbix servers
    template_xml: "{{ lookup('template', '{{ item }}') if 'j2' in item else lookup('file', '{{ item }}') }}"
    state: present
  loop: "{{ result_list }}"

Unfortunately I cloud not determine the root cause for this behavior. cry I switched this task back to local_action and the old way (server_url, login_user, login_password) which worked fine for now.

Interesting hint, thank you. I'll try to play with httpapi versions.

BGmot commented 1 year ago

I am confused, when did you get this problem? 1) When template_name had space or - in it 2) When template_xml performs 'file' type lookup?

BGmot commented 1 year ago

Anyway I tried with .xml and still works without problems:

  tasks:
  - name: Update templates to provide required tags
    community.zabbix.zabbix_template:
      #template_name: 'Template-RHEL_Base'
      template_groups:
        - Templates
      tags:
        - tag: class
          value: Linux
      template_xml: "{{ lookup('template', '{{ item }}') if 'j2' in item else lookup('file', '{{ item }}') }}"
      state: present
    loop:
    - zbx_export_templates.xml
xchotard-talentsoft commented 1 year ago

I had difficult times with this generic/cryptic error message. Here is how I am able to reproduce it:

- zabbix_template_info:
  template_name: "Windows by Zabbix agent active"
    format: json
    omit_date: yes

Note that Windows by Zabbix agent active is a default template.

Results:

TASK [zabbix_template_info] ******************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "connection error occurred: string indices must be integers"}

This seems related to Windows by Zabbix agent active > Discovery rules > Network interfaces discovery I was able to "make it work" by:

I'd say there are multiple possible causes but at least the keyword errors crashes the connection.

I use Zabbix 6.2.6 & ansible-core 2.14.3 installed from pip3 on Debian.

barzog commented 1 year ago

I've experiencing same behaviour (zabbix 6.0.17 LTS, community.zabbix is 56f94d151da34b71a1a09af0b4eca6c7ddee319b) on one of our templates (others imported OK). Template link: https://nextcloud.managed-it.a1.by/s/3WbDkfBHfRtqFLw error is failed: [] (item=files/zabbix/template_juniper_bgp.xml) => {"ansible_loop_var": "item", "changed": false, "item": "files/zabbix/template_juniper_bgp.xml", "msg": "connection error occurred: string indices must be integers"} playbook task:

- name: Create zabbix templates task
  community.zabbix.zabbix_template:
    template_xml: "{{ lookup('file',item) }}"
  loop:
    - files/zabbix/template_juniper-optical-interface.xml
    - files/zabbix/template_multi_icmp_ping.xml
    - files/zabbix/template_net_mtr.xml
    - files/zabbix/template_multi_web_perf.xml
    - files/zabbix/template_juniper_bgp.xml # This one causes error
miettal commented 1 year ago

this error related to configuration.export api calling.

zabbix_template module call configuration.export api. but this call dont care returning xml string so this error was happen.

condition of this bug happening is

I feel it seems to this bug not related to including hyphen or space.

Nebula83 commented 1 year ago

Running into the same issue: template import works fine via legacy interface, but fails with the httpapi interface. Included the culprit attached. zbx_export_templates.json.txt

pulsar895 commented 1 year ago

Hello,

I think the problem is only with the discovery rules. If you try to import one more time "Linux by Zabbix agent active" (for example), you have the same error message:

TASK [zabbix_6 : Import templates] *********************************************************************************************************************************************************************************************************
failed: [inf-adm-zabbix-web-1] (item=/home/pulsar895/git/ansible/playbooks/deploy_zabbix/files/zbx_export_templates-linux.json) => {"ansible_loop_var": "item", "changed": false, "item": "/home/pulsar895/git/ansible/playbooks/deploy_zabbix/files/zbx_export_templates-linux.json", "msg": "connection error occurred: string indices must be integers"}

If you remove discovery rules, it's ok:

TASK [zabbix_6 : Import templates] *********************************************************************************************************************************************************************************************************
ok: [inf-adm-zabbix-web-1] => (item=/home/pulsar895/git/ansible/playbooks/deploy_zabbix/files/zbx_export_templates-linux.json)

I hope my comment helps devteam to solve this problem.

BGmot commented 1 year ago

Running into the same issue: template import works fine via legacy interface, but fails with the httpapi interface. Included the culprit attached. zbx_export_templates.json.txt

Just tested with Zabbix 6.4 - no problems importing this templates file.

BGmot commented 1 year ago

See my comment in https://github.com/ansible-collections/community.zabbix/pull/1006 I'd love to have a file to import that would cause this issue.

IzakEygelaar commented 1 year ago

So running into the same issue, tested on both zabbix latest LTS version 6.0 and 6.4.

Versions:

Problem description: Able to import the template on the 1st Ansible run, however on subsequent Ansible runs, import task fails with:

"msg": "connection error occurred: string indices must be integers, not 'str'"

1st Ansible run on import task (verbose output):

changed: [zabbix_host] => {
    "changed": true,
    "invocation": {
        "module_args": {
            "clear_templates": null,
            "http_login_password": null,
            "http_login_user": null,
            "link_templates": null,
            "macros": null,
            "state": "present",
            "tags": null,
            "template_groups": null,
            "template_json": null,
            "template_name": null,
            "template_xml": "<zabbix_export>\n    <version>6.0</version>\n    <groups>\n        <group>\n            <uuid>52a9bce1d9ac4ea7880a0b618c011577</uuid>\n            <name>Storage</name>\n        </group>\n    </groups>\n    <templates>\n        <template>\n            <uuid>cf82f065616a4a0392477a2a2d7e1393</uuid>\n            <template>Storage1</template>\n            <name>Storage1</name>\n            <groups>\n                <group>\n                    <name>Storage</name>\n                </group>\n            </groups>\n            <items>\n                <item>\n                    <uuid>f4495906698f45f1866c7494e7a01913</uuid>\n                    <name>storage_quotas</name>\n                    <key>storage_user_quota</key>\n                    <trends>0</trends>\n                    <value_type>CHAR</value_type>\n                    <preprocessing>\n                        <step>\n                            <type>CSV_TO_JSON</type>\n                            <parameters>\n                              <parameter>,</parameter>\n                              <parameter>&quot;</parameter>\n                              <parameter>1</parameter>\n                            </parameters>\n                            <error_handler>CUSTOM_ERROR</error_handler>\n                            <error_handler_params>Failed to populate user quotas</error_handler_params>\n                        </step>\n                    </preprocessing>\n                </item>\n            </items>\n        </template>\n    </templates>\n</zabbix_export>"
        }
    },
    "result": "Template import successful"
}

Subsequent Ansible run on import task (verbose output):

The full traceback is:
  File "/var/folders/fc/s3k1pmdn42v_p669fm12mjvw0000gn/T/ansible_community.zabbix.zabbix_template_payload_bvy93set/ansible_community.zabbix.zabbix_template_payload.zip/ansible_collections/community/zabbix/plugins/module_utils/api_request.py", line 29, in _httpapi_error_handle
    code, response = self.connection.send_request(data=payload)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/var/folders/fc/s3k1pmdn42v_p669fm12mjvw0000gn/T/ansible_community.zabbix.zabbix_template_payload_bvy93set/ansible_community.zabbix.zabbix_template_payload.zip/ansible/module_utils/connection.py", line 200, in __rpc__
    raise ConnectionError(to_text(msg, errors='surrogate_then_replace'), code=code)
fatal: [zabbix_host]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "clear_templates": null,
            "http_login_password": null,
            "http_login_user": null,
            "link_templates": null,
            "macros": null,
            "state": "present",
            "tags": null,
            "template_groups": null,
            "template_json": null,
            "template_name": null,
            "template_xml": "<zabbix_export>\n    <version>6.0</version>\n    <groups>\n        <group>\n            <uuid>52a9bce1d9ac4ea7880a0b618c011577</uuid>\n            <name>Storage</name>\n        </group>\n    </groups>\n    <templates>\n        <template>\n            <uuid>cf82f065616a4a0392477a2a2d7e1393</uuid>\n            <template>Storage1</template>\n            <name>Storage1</name>\n            <groups>\n                <group>\n                    <name>Storage</name>\n                </group>\n            </groups>\n            <items>\n                <item>\n                    <uuid>f4495906698f45f1866c7494e7a01913</uuid>\n                    <name>storage_quotas</name>\n                    <key>storage_user_quota</key>\n                    <trends>0</trends>\n                    <value_type>CHAR</value_type>\n                    <preprocessing>\n                        <step>\n                            <type>CSV_TO_JSON</type>\n                            <parameters>\n                              <parameter>,</parameter>\n                              <parameter>&quot;</parameter>\n                              <parameter>1</parameter>\n                            </parameters>\n                            <error_handler>CUSTOM_ERROR</error_handler>\n                            <error_handler_params>Failed to populate user quotas</error_handler_params>\n                        </step>\n                    </preprocessing>\n                </item>\n            </items>\n        </template>\n    </templates>\n</zabbix_export>"
        }
    },
    "msg": "connection error occurred: string indices must be integers, not 'str'"
}

XML template used for testing: zabbix_import_failure_template.xml.txt

I don't think it's related to spaces or hyphens, as I have tested on the template with spaces and hyphens in the names, etc and was able to do multiple Ansible runs.

One thing that was interesting to me is that when commenting out these 2 lines in the template, I am able to perform multiple Ansible runs without issues also adding the word error in the template / item name causes the import failure:

                          <error_handler>CUSTOM_ERROR</error_handler>
                          <error_handler_params>Failed to populate user quotas</error_handler_params>

Is it failing due to the keyword error being present in the template?

Hope this helps!

wschoot commented 1 year ago

For me, unsetting the "custom on fail" in the discovery's preprocessing leads to having no "error"-like lines in my template and after that, it successfully imports. Not sure if it's due to the keyword "error", but that's the main thing that has changed in my template.

More specifically, it removed these two lines:

error_handler: CUSTOM_ERROR
error_handler_params: 'Endpoint healthcheck contains no checks'

Zabbix 6.2.9 and Ansible core 2.15.1 using the community 2.1.0 release version

wschoot commented 1 year ago

After checking a few more templates, it's not specifically tied to the error_handler, but rather to something more. Other templates that don't have error_handler but do have "error" as text in them, also fail.

niklasweimann commented 1 year ago

This seems to also happen when used to set a macro for a template:

- name: Configure macro of network interfaces by Zabbix agent active template
  community.zabbix.zabbix_template:
    template_name: "Linux network interfaces by Zabbix agent active"
    state: present
    macros:
      - macro: 'TEST'
        value: 'value'

Output:

TASK [zabbix-server-config : Configure macro of network interfaces by Zabbix agent active template] *************************
fatal: [ops_zabbix_1]: FAILED! => {"changed": false, "msg": "connection error occurred: string indices must be integers"}
niklasweimann commented 1 year ago

I suspect that this behavior is not tight to the _templatename attribute. I'm using the _templatexml attribute with a jinja lookup like so:

    template_xml: "{{ lookup('template', '{{ item }}') if 'j2' in item else lookup('file', '{{ item }}') }}"

Which worked fine until i switched to the new httpapi-plugin. After switching to the new plugin i could no longer import any template with a xml file extension. Resulting in the following error:

failed: [host] (item=templates/template/rabbit_mq_node_by_zabbix_agent2.xml) => {"ansible_loop_var": "item", "changed": false, "item": "templates/template/rabbit_mq_node_by_zabbix_agent2.xml", "msg": "connection error occurred: string indices must be integers"}

So this works with the newest version:

- name: Import templates
  local_action:
    module: community.zabbix.zabbix_template
    server_url: "https://{{ zabbix_host_url }}"
    login_user: "{{ zabbix_admin_user }}"
    login_password: "{{ zabbix_admin_user_password }}"
    template_groups:
      - Zabbix servers
    template_xml: "{{ lookup('template', '{{ item }}') if 'j2' in item else lookup('file', '{{ item }}') }}"
    state: present
  loop: "{{ result_list }}"

This does not work (for lookup == file):

- name: Init connection parameters
  ansible.builtin.set_fact:
    ansible_become: false
    ansible_network_os: community.zabbix.zabbix
    ansible_connection: httpapi
    ansible_httpapi_port: 443
    ansible_httpapi_use_ssl: true
    ansible_httpapi_validate_certs: true
    ansible_user: "{{ zabbix_admin_user }}"
    ansible_host: "{{ zabbix_host_url }}"
    ansible_httpapi_pass: "{{ zabbix_admin_user_password }}"
- name: Import templates
  community.zabbix.zabbix_template:
    template_groups:
      - Zabbix servers
    template_xml: "{{ lookup('template', '{{ item }}') if 'j2' in item else lookup('file', '{{ item }}') }}"
    state: present
  loop: "{{ result_list }}"

Unfortunately I cloud not determine the root cause for this behavior. 😢 I switched this task back to local_action and the old way (server_url, login_user, login_password) which worked fine for now.

I just tried the ansible plugin way again with community.zabbix version 2.1.0. I still get the same error:

failed: [ops_zabbix_1] (item=templates/template/template1.xml) => {"ansible_loop_var": "item", "changed": false, "item": "templates/template/template1.xml", "msg": "connection error occurred: string indices must be integers"}
failed: [ops_zabbix_1] (item=templates/template/template2.xml.j2) => {"ansible_loop_var": "item", "changed": false, "item": "templates/template/template2.xml.j2", "msg": "connection error occurred: string indices must be integers"}
failed: [ops_zabbix_1] (item=templates/template/template3.xml.j2) => {"ansible_loop_var": "item", "changed": false, "item": "templates/template/template3.xml.j2", "msg": "connection error occurred: string indices must be integers"}
failed: [ops_zabbix_1] (item=templates/template/template4.xml) => {"ansible_loop_var": "item", "changed": false, "item": "templates/template/template4.xml", "msg": "connection error occurred: string indices must be integers"}
BGmot commented 1 year ago

I just tried the ansible plugin way again with community.zabbix version 2.1.0. I still get the same error: It is fixed in main branch, 2.1.0 does not have this fix. You either need to wait for 2.2.0 or get your collection to use main branch of this repository.