Search code examples
ansiblescriptingnested-loops

Ansible script to Assign tickets to a list of users using round-robin method


I have two lists:

inc_numbers: [A, B, C, D, E, F, G] 

users:
- username: u1
  status: active
  
- username: u2
  status: active
  
- username: u3
  status: active

- username: u4
  status: active

Say the first list is tickets and the second list is users. How do I loop trough this? How do I assign these tickets in round-robin manner using Ansible?

I tried the following

  - name: with_together -> loop
    set_fact:
      inc_user_map: "{{ inc_user_map|default([]) + [{ 'inc_numbers':item.0, 'users':item.1.username }] }}"
      with_together:
      - "{{ inc_numbers }}"
      - "{{ users }}"`

  - name: Nested loop
    set_fact:
        inc_sel: "{{ inc_sel|d([]) + [item|combine({'selection': selection})] }}"
    loop: "{{ users }}"
    vars:
      username: "{{ item.username }}"
      selection: "{{ inc_numbers|
                     zip(username)|
                     rejectattr('0', 'eq', '0') }}"

This does'nt give the desired output. It ends after completing single loop of users

Desired Output

A : u1 
B : u2 
C : u3 
D : u1 
E : u2
F : u3 
G : u1

Solution

  • This example does what you ask and also allows you to exclude inactive users

    ---
    - name: Assign Tickets in Round-Robin
      hosts: localhost
      gather_facts: false
      vars:
        inc_numbers: [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]
        users:
          - username: u1
            status: active
          - username: u2
            status: inactive
          - username: u3
            status: active
          - username: u4
            status: active
          - username: u5
            status: active
          - username: u6
            status: active
          - username: u7
            status: active
    
      tasks:
        - name: Assign ticket to user
          set_fact:
            inc_sel: "{{ inc_sel | default({}) | combine({ item: active_users[idx % (active_users | length)].username }) }}"
          loop: "{{ inc_numbers }}"
          loop_control:
            index_var: idx
          vars: 
            active_users: "{{ users | selectattr('status', 'eq', 'active') | list }}"
        - name: Print inc_sel
          debug:
            var: inc_sel
    

    Output:

    PLAY [Assign Tickets in Round-Robin] ******************************************************************************************************************************************************************************
    
    TASK [Assign ticket to user] **************************************************************************************************************************************************************************************
    ok: [localhost] => (item=A)
    ok: [localhost] => (item=B)
    ok: [localhost] => (item=C)
    ok: [localhost] => (item=D)
    ok: [localhost] => (item=E)
    ok: [localhost] => (item=F)
    ok: [localhost] => (item=G)
    ok: [localhost] => (item=H)
    ok: [localhost] => (item=I)
    ok: [localhost] => (item=J)
    ok: [localhost] => (item=K)
    ok: [localhost] => (item=L)
    ok: [localhost] => (item=M)
    ok: [localhost] => (item=N)
    ok: [localhost] => (item=O)
    ok: [localhost] => (item=P)
    ok: [localhost] => (item=Q)
    ok: [localhost] => (item=R)
    ok: [localhost] => (item=S)
    ok: [localhost] => (item=T)
    ok: [localhost] => (item=U)
    ok: [localhost] => (item=V)
    ok: [localhost] => (item=W)
    ok: [localhost] => (item=X)
    ok: [localhost] => (item=Y)
    ok: [localhost] => (item=Z)
    
    TASK [Print inc_sel] **********************************************************************************************************************************************************************************************
    ok: [localhost] => {
        "inc_sel": {
            "A": "u1",
            "B": "u3",
            "C": "u4",
            "D": "u5",
            "E": "u6",
            "F": "u7",
            "G": "u1",
            "H": "u3",
            "I": "u4",
            "J": "u5",
            "K": "u6",
            "L": "u7",
            "M": "u1",
            "N": "u3",
            "O": "u4",
            "P": "u5",
            "Q": "u6",
            "R": "u7",
            "S": "u1",
            "T": "u3",
            "U": "u4",
            "V": "u5",
            "W": "u6",
            "X": "u7",
            "Y": "u1",
            "Z": "u3"
        }
    }
    
    PLAY RECAP ********************************************************************************************************************************************************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
    

    Alternative version

    ---
    - name: Assign Tickets in Round-Robin
      hosts: localhost
      gather_facts: false
      vars:
        inc_numbers: [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]
        users:
          - username: u1
            status: active
          - username: u2
            status: inactive
          - username: u3
            status: active
          - username: u4
            status: active
          - username: u5
            status: active
          - username: u6
            status: active
          - username: u7
            status: active  
    
      tasks:
        - name: Assign ticket to user
          set_fact:
            inc_sel: "{ {% for inc in inc_numbers %}'{{ inc }}':'{{active_users[loop.index0 % (active_users | length)].username}}',{% endfor %} }"
          vars: 
            active_users: "{{ users | selectattr('status', 'eq', 'active') | list }}"
        - name: Print inc_sel
          debug:
            var: inc_sel
    

    Output:

    PLAY [Assign Tickets in Round-Robin] ********************************************************************************************************************************************************************************************************
    
    TASK [Assign ticket to user] ****************************************************************************************************************************************************************************************************************
    ok: [localhost]
    
    TASK [Print inc_sel] ************************************************************************************************************************************************************************************************************************
    ok: [localhost] => {
        "inc_sel": {
            "A": "u1",
            "B": "u3",
            "C": "u4",
            "D": "u5",
            "E": "u6",
            "F": "u7",
            "G": "u1",
            "H": "u3",
            "I": "u4",
            "J": "u5",
            "K": "u6",
            "L": "u7",
            "M": "u1",
            "N": "u3",
            "O": "u4",
            "P": "u5",
            "Q": "u6",
            "R": "u7",
            "S": "u1",
            "T": "u3",
            "U": "u4",
            "V": "u5",
            "W": "u6",
            "X": "u7",
            "Y": "u1",
            "Z": "u3"
        }
    }
    
    PLAY RECAP **********************************************************************************************************************************************************************************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0