Search code examples
for-loopansibleiteration

iteration and count variable in ansible


I am trying to simplify the code

    - name: Report status
      ansible.builtin.debug:
        msg:
          - "{{ agents.results.0.services.0.display_name }} is {{ agents.results.0.services.0.state }}"
          - "{{ agents.results.1.services.0.display_name }} is {{ agents.results.1.services.0.state }}"
          - "{{ agents.results.2.services.0.display_name }} is {{ agents.results.2.services.0.state }}"
          - "{{ agents.results.3.services.0.display_name }} is {{ agents.results.3.services.0.state }}"
          - "{{ agents.results.4.services.0.display_name }} is {{ agents.results.4.services.0.state }}"
          - "{{ agents.results.5.services.0.display_name }} is {{ agents.results.5.services.0.state }}"
          - "{{ agents.results.6.services.0.display_name }} is {{ agents.results.6.services.0.state }}"

I need to get the name and service state for each item.

I have tried with_sequence but this leads to an error:

{"msg": "The task includes an option with an undefined variable. The error was: 'list object' has no attribute 'item'
    - ansible.builtin.debug:
        msg: 
          - "{{ agents.results.item.services.0.display_name }} is {{ agents.results.item.services.0.state }}"
      with_sequence: end=6

A per suggestion I tried

    - ansible.builtin.debug:
        msg:
          - "{{ agents.results[item].services.0.display_name }} is {{ agents.results[item].services.0.state }}"
      with_sequence: end=6

which leads to an error: "msg": "The task includes an option with an undefined variable. The error was: 'list object' has no attribute '1'

Also, tried:

    - ansible.builtin.debug:
        msg: "{{ item.services.0.display_name }} is {{ item.services.0.state }}"
      loop: "{{ agents.results }}"

which provides more information than required, e.g.

ok: [host] => (item={'changed': False, 'invocation': {'module_args': {'name': 'CSFalconService'}}, 'exists': True, 'services': [{'checkpoint': 0, 'controls_accepted': ['stop', 'pre_shutdown'], 'dependencies': [], 'dependency_of': [], 'description': 'Helps protect the system from malicious activities', 'desktop_interact': False, 'display_name': 'CrowdStrike Falcon Sensor Service', 'error_control': 'normal', 'failure_actions': [{'type': 'restart', 'delay_ms': 60000}, {'type': 'restart', 'delay_ms': 60000}, {'type': 'restart', 'delay_ms': 60000}], 'failure_actions_on_non_crash_failure': False, 'failure_command': None, 'failure_reboot_msg': None, 'failure_reset_period_sec': 86400, 'launch_protection': 'antimalware_light', 'load_order_group': '', 'name': 'CSFalconService', 'path': '"C:\\Program Files\\CrowdStrike\\CSFalconService.exe"', 'pre_shutdown_timeout_ms': 180000, 'preferred_node': None, 'process_id': 7164, 'required_privileges': [], 'service_exit_code': 0, 'service_flags': [], 'service_type': 'win32_own_process', 'sid_info': 'none', 'start_mode': 'auto', 'state': 'started', 'triggers': [], 'username': 'NT AUTHORITY\\SYSTEM', 'wait_hint_ms': 0, 'win32_exit_code': 0}], 'failed': False, 'item': 'CSFalconService', 'ansible_loop_var': 'item'}) => {
    "msg": "CrowdStrike Falcon Sensor Service is started"
}


ok: [host] => (item={'changed': False, 'invocation': {'module_args': {'name': 'Tanium Client'}}, 'exists': True, 'services': [{'checkpoint': 0, 'controls_accepted': ['stop'], 'dependencies': [], 'dependency_of': [], 'description': 'Tanium Client', 'desktop_interact': False, 'display_name': 'Tanium Client', 'error_control': 'normal', 'failure_actions': [{'type': 'restart', 'delay_ms': 60000}, {'type': 'restart', 'delay_ms': 60000}, {'type': 'none', 'delay_ms': 0}], 'failure_actions_on_non_crash_failure': False, 'failure_command': None, 'failure_reboot_msg': None, 'failure_reset_period_sec': 86400, 'launch_protection': 'none', 'load_order_group': '', 'name': 'Tanium Client', 'path': '"C:\\Program Files (x86)\\Tanium\\Tanium Client\\TaniumClient.exe" --service', 'pre_shutdown_timeout_ms': 10000, 'preferred_node': None, 'process_id': 5324, 'required_privileges': [], 'service_exit_code': 0, 'service_flags': [], 'service_type': 'win32_own_process', 'sid_info': 'none', 'start_mode': 'auto', 'state': 'started', 'triggers': [], 'username': 'NT AUTHORITY\\SYSTEM', 'wait_hint_ms': 0, 'win32_exit_code': 0}], 'failed': False, 'item': 'Tanium Client', 'ansible_loop_var': 'item'}) => {
    "msg": "Tanium Client is started"
}

Actually, I need only the msg part.


Solution

  • First, you should read the dedicated article in ansible FAQ. So the direct answer to your above question is:

    "{{ agents.results[item | int].services.0.display_name }} is {{ agents.results[item].services.0.state }}"
    

    Note the int filter to cast the variable as with_sequence actually produces strings.


    But next, why do you make things so complicated? Just loop on the results:

    - ansible.builtin.debug:
        msg: "{{ item.services.0.display_name }} is {{ item.services.0.state }}"
      loop: "{{ agents.results }}"
    

    If each individual item is large and you want to reduce the amount of information which is displayed by Ansible on each loop iteration, see loop control - limiting loop output