Ansible: working with loops within a task not on a task

51 Views Asked by At

i want to build a dynamically task, that creates an action within zabbix. The task works like charm, but it would be great, if it would be possible to add parameters with looping through a list. Currently my playbook creates on action for each discovery rule, but I want to add only one action with all discovery rules in it. Is that even possible?

Here is the specific task in the playbook

  1. The first task in this playbook builds my new list with the correct Discovery-Rule names
  2. The next two tasks will create the discovery rules, but with "looping" over the list. Currently I do not run over the list, because I need to generate this - type: block for each Discovery-rule, so I can add it correctly to zabbix :-)
- name: Create the discovery-rule list for the customer
  vars:
    discovery_rule_list: []
  set_fact:
    discovery_rule_list: "{{ discovery_rule_list + [ zabbix_host_customer_short + ' - Subnetz: ' + item ] }}"
  loop: "{{ zabbix_discovery_subnets }}"
- debug: var=discovery_rule_list


- name: Add an action to add hosts that are discovered by discovery-rule - {{ item }}
  community.zabbix.zabbix_action:
    name: "Add hosts for {{ zabbix_host_customer_short }} - {{ item }} - Linux"
    state: present
    event_source: "discovery"
    status: "enabled"
    esc_period: "1m"
    conditions:
      - type: "discovery_status"
        operator: "="
        value: "Up"
        formulaid: "A"
      - type: "discovery_rule"
        operator: "="
        value: "{{ zabbix_host_customer_short }} - Subnetz: {{ item }}"
        formulaid: "B"
      - type: "discovered_service_type"
        operator: "="
        value: "Zabbix agent"
        formulaid: "C"
      - type: "received_value"
        operator: "contains"
        value: "Linux"
        formulaid: "D"
    formula: "A and B and C and D"
    operations:
      - type: add_host
      - type: add_to_host_group
        host_groups: 
        - "{{ zabbix_host_customer_short }}"
        - "Linux servers"
  loop: "{{ zabbix_discovery_subnets }}"
- name: Add an action to add hosts that are discovered by discovery-rule - {{ item }}
  community.zabbix.zabbix_action:
    name: "Add hosts for {{ zabbix_host_customer_short }} - {{ item }} - Windows"
    state: present
    event_source: "discovery"
    status: "enabled"
    esc_period: "1m"
    conditions:
      - type: "discovery_status"
        operator: "="
        value: "Up"
        formulaid: "A"
      - type: "discovery_rule"
        operator: "="
        value: "{{ zabbix_host_customer_short }} - Subnetz: {{ item }}"
        formulaid: "B"
      - type: "discovered_service_type"
        operator: "="
        value: "Zabbix agent"
        formulaid: "C"
      - type: "received_value"
        operator: "contains"
        value: "Windows"
        formulaid: "D"
    formula: "A and B and C and D"
    operations:
      - type: add_host
      - type: add_to_host_group
        host_groups: 
        - "{{ zabbix_host_customer_short }}"
        - "Windows servers"
  loop: "{{ zabbix_discovery_subnets }}"

For more information, here is the output of the debug:

This is the variable, I want to use

TASK [zabbix-add-customer : debug] **********************************************************************************************************************************************************
task path: /home/uweichert/projects/fks-zabbix-rollout/maintain-zabbix/roles/zabbix-add-customer/tasks/add-discovery-trigger.yaml:10
redirecting (type: connection) ansible.builtin.httpapi to ansible.netcommon.httpapi
ok: [zabbixserver] => {
    "discovery_rule_list": [
        "TestKunde 01 - Subnetz: 192.168.100.0/24",
        "TestKunde 01 - Subnetz: 192.168.101.0/24",
        "TestKunde 01 - Subnetz: 192.168.102.0/24"
    ]
}

This is the output of the task, that creates the action

TASK [zabbix-add-customer : Add an action to add hosts that are discovered by discovery-rule - {{ item }}] **********************************************************************************
task path: /home/uweichert/projects/fks-zabbix-rollout/maintain-zabbix/roles/zabbix-add-customer/tasks/add-discovery-trigger.yaml:13
redirecting (type: connection) ansible.builtin.httpapi to ansible.netcommon.httpapi
<192.168.210.17> ESTABLISH LOCAL CONNECTION FOR USER: uweichert
<192.168.210.17> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/uweichert/.ansible/tmp/ansible-local-230678238kjb18 `"&& mkdir "` echo /home/uweichert/.ansible/tmp/ansible-local-230678238kjb18/ansible-tmp-1711106720.9670377-231219-228532287612647 `" && echo ansible-tmp-1711106720.9670377-231219-228532287612647="` echo /home/uweichert/.ansible/tmp/ansible-local-230678238kjb18/ansible-tmp-1711106720.9670377-231219-228532287612647 `" ) && sleep 0'
Using module file /usr/lib/python3/dist-packages/ansible_collections/community/zabbix/plugins/modules/zabbix_action.py
<192.168.210.17> PUT /home/uweichert/.ansible/tmp/ansible-local-230678238kjb18/tmpckgpmqqe TO /home/uweichert/.ansible/tmp/ansible-local-230678238kjb18/ansible-tmp-1711106720.9670377-231219-228532287612647/AnsiballZ_zabbix_action.py
<192.168.210.17> EXEC /bin/sh -c 'chmod u+x /home/uweichert/.ansible/tmp/ansible-local-230678238kjb18/ansible-tmp-1711106720.9670377-231219-228532287612647/ /home/uweichert/.ansible/tmp/ansible-local-230678238kjb18/ansible-tmp-1711106720.9670377-231219-228532287612647/AnsiballZ_zabbix_action.py && sleep 0'
<192.168.210.17> EXEC /bin/sh -c '/usr/bin/python3 /home/uweichert/.ansible/tmp/ansible-local-230678238kjb18/ansible-tmp-1711106720.9670377-231219-228532287612647/AnsiballZ_zabbix_action.py && sleep 0'
<192.168.210.17> EXEC /bin/sh -c 'rm -f -r /home/uweichert/.ansible/tmp/ansible-local-230678238kjb18/ansible-tmp-1711106720.9670377-231219-228532287612647/ > /dev/null 2>&1 && sleep 0'
ok: [zabbixserver] => (item=192.168.100.0/24) => {
    "ansible_loop_var": "item",
    "changed": false,
    "invocation": {
        "module_args": {
            "acknowledge_default_message": "",
            "acknowledge_default_subject": "",
            "acknowledge_operations": [],
            "conditions": [
                {
                    "formulaid": "A",
                    "operator": "=",
                    "type": "discovery_status",
                    "value": "Up",
                    "value2": null
                },
                {
                    "formulaid": "B",
                    "operator": "=",
                    "type": "discovery_rule",
                    "value": "TestKunde 01 - Subnetz: 192.168.100.0/24",
                    "value2": null
                },
                {
                    "formulaid": "C",
                    "operator": "=",
                    "type": "discovered_service_type",
                    "value": "Zabbix agent",
                    "value2": null
                },
                {
                    "formulaid": "D",
                    "operator": "contains",
                    "type": "received_value",
                    "value": "Linux",
                    "value2": null
                }
            ],
            "default_message": "",
            "default_subject": "",
            "esc_period": "1m",
            "eval_type": null,
            "event_source": "discovery",
            "formula": "A and B and C and D",
            "http_login_password": null,
            "http_login_user": null,
            "login_password": null,
            "login_user": null,
            "name": "Add hosts for TestKunde 01 - 192.168.100.0/24 - Linux",
            "operations": [
                {
                    "command": null,
                    "command_type": null,
                    "esc_period": null,
                    "esc_step_from": 1,
                    "esc_step_to": 1,
                    "execute_on": null,
                    "host_groups": null,
                    "inventory": null,
                    "media_type": null,
                    "message": null,
                    "operation_condition": null,
                    "password": null,
                    "port": null,
                    "run_on_groups": null,
                    "run_on_hosts": null,
                    "script_name": null,
                    "send_to_groups": null,
                    "send_to_users": null,
                    "ssh_auth_type": null,
                    "ssh_privatekey_file": null,
                    "ssh_publickey_file": null,
                    "subject": null,
                    "templates": null,
                    "type": "add_host",
                    "username": null
                },
                {
                    "command": null,
                    "command_type": null,
                    "esc_period": null,
                    "esc_step_from": 1,
                    "esc_step_to": 1,
                    "execute_on": null,
                    "host_groups": [
                        "TestKunde 01",
                        "Linux servers"
                    ],
                    "inventory": null,
                    "media_type": null,
                    "message": null,
                    "operation_condition": null,
                    "password": null,
                    "port": null,
                    "run_on_groups": null,
                    "run_on_hosts": null,
                    "script_name": null,
                    "send_to_groups": null,
                    "send_to_users": null,
                    "ssh_auth_type": null,
                    "ssh_privatekey_file": null,
                    "ssh_publickey_file": null,
                    "subject": null,
                    "templates": null,
                    "type": "add_to_host_group",
                    "username": null
                }
            ],
            "pause_in_maintenance": true,
            "recovery_default_message": "",
            "recovery_default_subject": "",
            "recovery_operations": [],
            "server_url": null,
            "state": "present",
            "status": "enabled",
            "timeout": null,
            "validate_certs": null
        }
    },
    "item": "192.168.100.0/24",
    "msg": "Action is up to date: Add hosts for TestKunde 01 - 192.168.100.0/24 - Linux"
}

This would be the part, that I want to create dynamically:

{
                    "formulaid": "B",
                    "operator": "=",
                    "type": "discovery_rule",
                    "value": "TestKunde 01 - Subnetz: 192.168.100.0/24",
                    "value2": null
                }

by creating this part of the playbook dynamically:

      - type: "discovery_rule"
        operator: "="
        value: "{{ zabbix_host_customer_short }} - Subnetz: {{ item }}"
        formulaid: "B"
2

There are 2 best solutions below

0
Alexander Pletnev On BEST ANSWER

I think I finally understood what you wanted to achieve initially - just to add the generated elements directly to the existing list of conditions using something like this:

---
- name: Add the generated discovery rule list to the list of conditions
  vars:
    conditions:
      - type: "discovery_status"
        operator: "="
        value: "Up"
        formulaid: "A"
      - type: "discovered_service_type"
        operator: "="
        value: "Zabbix agent"
        formulaid: "C"
      - type: "received_value"
        operator: "contains"
        value: "Linux"
        formulaid: "D"
  set_fact:
    conditions: >
      conditions + [
        {
          type: "discovery_rule",
          operator: "=",
          value: zabbix_host_customer_short + ' - Subnetz: ' + zabbix_discovery_subnet,
          formulaid: "B"
        }
      ]
  loop: "{{ zabbix_discovery_subnets }}"
  loop_control:
    loop_var: zabbix_discovery_subnet
2
w3ich3rt On

I have now solved it with a different approach because I simply assume that it won’t work differently. Instead of creating a separate discovery rule for each subnet, I am now creating a single rule that I assign to the discovery action. This also reduces the ‘rule set’ complexity in the individual menus in Zabbix. Thank you for your support; it really helped me think and led me to the alternative approach. Below are the two new tasks.

## Create the discovery rules with all subnets
- name: "Add discovery rule in Zabbix for customer {{ zabbix_host_customer_short }}"
  community.zabbix.zabbix_discovery_rule:
    name: "Discovery: {{ zabbix_host_customer_short }}"
    iprange: "{{ zabbix_discovery_subnets|join(',') }}"
    delay: 3600
    status: enabled
    state: present
    proxy: '{{ zabbix_proxy_customer[0]["ProxyName"] }}'
    dchecks:
      - type: ICMP
      - type: Zabbix
        key: system.hostname
        ports: 10050
        uniq: true
        host_source: discovery
        name_source: discovery
      - type: Zabbix
        key: system.uname
        ports: 10050
  ## Ignore tasks because, if the rule already exists, it will fail, but it can be skipped then
  ignore_errors: true

## Create the discovery rules for linux and windows server
- name: Add an action to add hosts that are discovered by discovery-rule - Linux
  community.zabbix.zabbix_action:
    name: "Add hosts for {{ zabbix_host_customer_short }} - Linux"
    state: present
    event_source: "discovery"
    status: "enabled"
    esc_period: "1m"
    conditions:
      - type: "discovery_status"
        operator: "="
        value: "Up"
        formulaid: "A"
      - type: "discovery_rule"
        operator: "="
        value: 'Discovery: {{ zabbix_host_customer_short }}'
        formulaid: "B"
      - type: "discovered_service_type"
        operator: "="
        value: "Zabbix agent"
        formulaid: "C"
      - type: "received_value"
        operator: "contains"
        value: "Linux"
        formulaid: "D"
    formula: "A and B and C and D"
    operations:
      - type: add_host
      - type: add_to_host_group
        host_groups: 
        - "{{ zabbix_host_customer_short }}"
        - "Linux servers"
- name: Add an action to add hosts that are discovered by discovery-rule - Windows
  community.zabbix.zabbix_action:
    name: "Add hosts for {{ zabbix_host_customer_short }} - Windows"
    state: present
    event_source: "discovery"
    status: "enabled"
    esc_period: "1m"
    conditions:
      - type: "discovery_status"
        operator: "="
        value: "Up"
        formulaid: "A"
      - type: "discovery_rule"
        operator: "="
        value: 'Discovery: {{ zabbix_host_customer_short }}'
        formulaid: "B"
      - type: "discovered_service_type"
        operator: "="
        value: "Zabbix agent"
        formulaid: "C"
      - type: "received_value"
        operator: "contains"
        value: "Windows"
        formulaid: "D"
    formula: "A and B and C and D"
    operations:
      - type: add_host
      - type: add_to_host_group
        host_groups: 
        - "{{ zabbix_host_customer_short }}"
        - "Windows servers"