On Wed, 15 Mar 2023 17:44:55 +0000
Aharonu <[email protected]> wrote:

> I am working to get failed hosts from 'rescue' section into a CSV file.
> [...]
> > *when  i tried to append data to a list. *  
> 
> >         - set_fact:
> >             failed_list: "{{ failed_list + [ansible_host] }}"
> 
> *failed_hosts.csv:*
> *number of failed hots: 2*
> *hostname:*
> *bogus1*
> *bogus2*

Each host will have its own variable *failed_list*. Therefore, it
makes no sense to record *ansible_host* in this list. Instead, you
might want to record the failed tasks. For example, the block below
runs three tasks. If any of the tasks fails the name of it will be
added to the list *failed_list*

    - name: block A
      block:
        - name: task1A
          command: "{{ ['true', 'false']|random }}"
        - name: task2A
          command: "{{ ['true', 'false']|random }}"
        - name: task3A
          command: "{{ ['true', 'false']|random }}"
      rescue:
        - set_fact:
            failed_list: "{{ failed_list +
                             [ansible_failed_task.name] }}"

Create dictionary of all hosts and failed tasks

  failed_lists: "{{ dict(groups.all|
                    zip(hostvars|dict2items|
                    map(attribute='value.failed_list',
                    default=[]))) }}"

For example, given the inventory

  shell> cat hosts
  host_A ansible_host=10.1.0.61
  host_B ansible_host=10.1.0.62
  host_C ansible_host=10.1.0.63

a play running two blocks (A and B) on two hosts (host_A and host_C)
gives

  failed_lists:
    host_A: [task1A, task1B]
    host_B: []
    host_C: [task3A, task2B]

Declare the list of failed hosts by selecting nonempty lists

  failed_hosts: "{{ failed_lists|dict2items|
                    selectattr('value')|
                    map(attribute='key')|list }}"

gives

  failed_hosts: [host_A, host_C]

Now you can create reports. For example, to write the file on the
controller, delegate the task to localhost 

    - copy:
        dest: /tmp/failed_hosts.yaml
        content: |
          number_of_failed_hosts: {{ failed_hosts|length }}
          hostnames: {{ failed_hosts|join(', ') }}
          {% for h,l in failed_lists.items() %}
          {{ h }}: {{ l|sort|join(', ') }}
          {% endfor %}
      delegate_to: localhost
      run_once: true

gives the YAML file

  shell> cat /tmp/failed_hosts.yaml 
  number_of_failed_hosts: 2
  hostnames: host_A, host_C
  host_A: task1A, task1B
  host_B: 
  host_C: task2B, task3A

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Example of a complete playbook for testing

---
- hosts: host_A,host_C

  vars:

    failed_list: []
    failed_lists: "{{ dict(groups.all|
                      zip(hostvars|dict2items|
                      map(attribute='value.failed_list',
                      default=[]))) }}"
    failed_hosts: "{{ failed_lists|dict2items|
                      selectattr('value')|
                      map(attribute='key')|list }}"

  tasks:

    - name: block A
      block:
        - name: task1A
          command: "{{ ['true', 'false']|random }}"
        - name: task2A
          command: "{{ ['true', 'false']|random }}"
        - name: task3A
          command: "{{ ['true', 'false']|random }}"
      rescue:
        - set_fact:
            failed_list: "{{ failed_list +
                             [ansible_failed_task.name] }}"

    - name: block B
      block:
        - name: task1B
          command: "{{ ['true', 'false']|random }}"
        - name: task2B
          command: "{{ ['true', 'false']|random }}"
        - name: task3B
          command: "{{ ['true', 'false']|random }}"
      rescue:
        - set_fact:
            failed_list: "{{ failed_list +
                             [ansible_failed_task.name] }}"

    - block:
        - debug:
            var: failed_lists|to_yaml
        - debug:
            var: failed_hosts|to_yaml
      run_once: true

    - copy:
        dest: /tmp/failed_hosts.yaml
        content: |
          number_of_failed_hosts: {{ failed_hosts|length }}
          hostnames: {{ failed_hosts|join(', ') }}
          {% for h,l in failed_lists.items() %}
          {{ h }}: {{ l|sort|join(', ') }}
          {% endfor %}
      delegate_to: localhost
      run_once: true

    - block:
        - include_vars:
            file: /tmp/failed_hosts.yaml
            name: test
        - debug:
            var: test
      run_once: true
...


-- 
Vladimir Botka

-- 
You received this message because you are subscribed to the Google Groups 
"Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/ansible-project/20230316002416.11d4a3c7%40gmail.com.

Attachment: pgpWv9i4PU0yT.pgp
Description: OpenPGP digital signature

Reply via email to