如何用Ansible以Round-Robin(轮询)方式分配工单给用户?
问题描述
我有两个列表:
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
第一个列表是工单,第二个是用户,需要在Ansible中通过轮询(Round-Robin)方式分配这些工单。
我尝试了以下代码,但未能得到预期输出,仅完成一轮用户循环就结束了:
- 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|\n zip(username)|\n rejectattr('0', 'eq', '0') }}"
预期输出:
A : u1 B : u2 C : u3 D : u1 E : u2 F : u3 G : u1
解决方案
可以通过索引取模的方式实现轮询分配,步骤如下:
1. 提取目标用户列表
先从用户列表中筛选出需要参与分配的用户(比如预期输出里用到的u1-u3,这里以活跃用户且取前3个为例,可按需调整):
- name: 提取目标用户用户名列表 set_fact: target_users: "{{ users | selectattr('status', 'equalto', 'active') | map(attribute='username') | list | slice(3) | first }}"
如果直接指定用户,也可以写成:
target_users: ["u1", "u2", "u3"]
2. 轮询分配工单
利用enumerate过滤器获取工单的索引,再通过索引对用户列表长度取模,实现循环分配:
- name: 轮询分配工单到用户 set_fact: inc_user_map: "{{ inc_user_map | default([]) + [{'ticket': item.1, 'user': target_users[item.0 % target_users|length]}] }}" loop: "{{ inc_numbers | enumerate }}"
3. 输出分配结果
如果需要打印成预期的格式,执行以下任务:
- name: 打印分配结果 debug: msg: "{{ item.ticket }} : {{ item.user }}" loop: "{{ inc_user_map }}"
原理说明
enumerate会为每个工单添加从0开始的索引,比如第一个工单A的索引是0,第二个B是1,以此类推item.0 % target_users|length用索引对用户列表的长度取模,确保索引超出用户列表长度时,会重新从第一个用户开始分配,实现轮询效果
内容的提问来源于stack exchange,提问作者SoorajRaju Spowers4u
相关产品推荐
相关产品推荐

