Is there an equivalent to Puppet's Resource Collector?

I have a largish Ansible code base with yum tasks scattered throughout. Example:

- name: Thing | Install MongoDB
  yum:
    state: present
    name:
      - mongodb-org
      - numactl
      - python-pymongo

This would intermittently fail at the worse times. So I added retries and delay attributes …

  yum:
    state: present
    name:
      - mongodb-org
      - numactl
      - python-pymongo
  register: mongo_yum_result
  until: "mongo_yum_result is not failed"
  retries: 10
  delay: 10

My question is:

Do I have to find every yum tasks and add those 4 lines everywhere I find a yum task, or is there some slick trick I do at the top of my playbook to make all yum tasks have the retries and deplay set?" I think the equivalent in Puppet would be the resource collector. Language: Resources (advanced)

Hi,

If I get you right, you’d like to have some sort of task template you could reuse in your playbook, with overridable parameters.

If so, you could use a YAML anchor; here is a (truncated) example showing two tasks to deploy containers, with an anchor allowing the second one to reuse (and then override) some parameters:

    - name: "Create 'netbox' container"
      community.docker.docker_container: &netbox
        name: "{{ 'netbox_' + dst_netbox_env|d('staging')|lower + '_netbox' }}"
        image: "{{ 'netboxcommunity/netbox:' + dst_netbox_netbox_image_version }}"
        restart_policy: unless-stopped
        published_ports:
          - 80:8080/tcp
        networks:
          - name: "{{ 'br_netbox_' + dst_netbox_env|d('staging')|lower }}"
        healthcheck:
          test: curl --fail --silent http://localhost:8080/api/ &>/dev/null || exit 1
          interval: 15s
          start_period: 60s
          timeout: 3s
          retries: 3
        state: started
        comparisons:
          '*': strict
      register: _dst_netbox_container_netbox_output
      notify: Docker-container-healthcheck

    - name: "Create 'netbox-worker' container"
      community.docker.docker_container:
        <<: *netbox
        name: "{{ 'netbox_' + dst_netbox_env|d('staging')|lower + '_netbox-worker' }}"
        command: ['/opt/netbox/venv/bin/python', '/opt/netbox/netbox/manage.py', 'rqworker']
        healthcheck:
          test: pgrep [r]qworker &>/dev/null || exit 1
          interval: 15s
          start_period: 20s
          timeout: 3s
          retries: 3
        published_ports: []

Another more Ansible-focused option would be to use a role in which you define your task once and reuse it in your playbooks using, like so:

---

- name: Update installed packages on GNU/Linux nodes
  gather_facts: false
  hosts: '!excluded,!windows'
  become: true
  tasks:
    - name: "[INCLUDE] Include tasks from role"
      ansible.builtin.include_role:
        name: gbt_packages
        tasks_from: update_packages.yml

Then in your case, you’d just have to pass another variable set depending on which packages you’d like to install.

You could even include the whole role, assuming you don’t want to specifically pinpoint one single task, like this:

- name: Update installed packages on GNU/Linux nodes
  gather_facts: false
  hosts: '!excluded,!windows'
  become: true
  roles:
    - role: gbt_packages

Now writing a role for a single task might be overkill, but why not ? You could also write a role as a toolbox containing multiple tasks you’d like to reuse elsewhere.

Edit: Trimmed my example a bit more, as you don’t need all this mostly irrelevant info.

2 Likes