英文:
How to create a dictionary list of key: value items and append it to the original list in Ansible?
问题
It appears that you're working with Ansible and trying to manipulate a list of user data based on their "ClassType" to add a "path" value to each user. However, there are some issues in your playbook, and you want to achieve a specific output format.
Here's the corrected playbook snippet to achieve the desired output:
- name: If class is full time
set_fact:
path: "OU=fulltime,OU=Test OU,DC=localdemo,DC=local"
when: item.ClassType == "Full Time"
loop: "{{ data_list }}"
- name: If employment type is part time
set_fact:
path: "OU=parttime,OU=Test OU,DC=localdemo,DC=local"
when: item.ClassType == "Part Time"
loop: "{{ data_list }}"
- name: If employment type is flexi
set_fact:
path: "OU=flexi,OU=Test OU,DC=localdemo,DC=local"
when: item.ClassType == "Flexi"
loop: "{{ data_list }}"
- name: Append to original userdata list
set_fact:
userdata: "{{ userdata + [{'ClassType': item.ClassType, 'FirstName': item.FirstName, 'LastName': item.LastName, 'path': path}] }}"
loop: "{{ data_list }}"
This playbook will correctly set the "path" value based on "ClassType" and append the modified user data to the "userdata" list in the desired format.
英文:
I want to create a new dictionary list, 'path: value' to be looped for each user and appended under each item in the user list. The end result would look something like below:
"userdata": [
{
"ClassType": "Full Time",
"FirstName": "Grace",
"LastName": "Higgins",
"path": "OU=fulltime,OU=Test OU,DC=localdemo,DC=local"
},
{
"ClassType": "Part Time",
"FirstName": "Robert",
"LastName": "Miller",
"path": "OU=parttime,OU=Test OU,DC=localdemo,DC=local"
},
{
"ClassType": "Flexi",
"FirstName": "Jeffrey",
"LastName": "Keller",
"path": "OU=flexi,OU=Test OU,DC=localdemo,DC=local"
}
]
The values for path is dependent on the value of the ClassType.
However, when I tried to append the new path: value dictionary list to the original userdata list, the 'path: item.path' is in the wrong layout and also has the wrong value:
TASK [Read_csv_creation : Append to original userdata list] *******************************************************************************************
ok: [localhost] => (item={'FirstName': '}) => {
"ansible_facts": {
"userdata": [
{
"ClassType": "Full Time",
"FirstName": "Grace",
"LastName": "Higgins"
},
{
"ClassType": "Part Time",
"FirstName": "Robert",
"LastName": "Miller"
},
{
"ClassType": "Flexi",
"FirstName": "Jeffrey",
"LastName": "Keller"
},
"path: item.path"
]
},
How can I get the final output as shown below?
"userdata": [
{
"ClassType": "Full Time",
"FirstName": "Grace",
"LastName": "Higgins",
"path": "OU=fulltime,OU=Test OU,DC=localdemo,DC=local"
},
{
"ClassType": "Part Time",
"FirstName": "Robert",
"LastName": "Miller",
"path": "OU=parttime,OU=Test OU,DC=localdemo,DC=local"
},
{
"ClassType": "Flexi",
"FirstName": "Jeffrey",
"LastName": "Keller",
"path": "OU=flexi,OU=Test OU,DC=localdemo,DC=local"
}
]
Below is my tasks file. The variable 'data_list' would be my original list.
- name: Read input file
read_csv:
path: /var/lib/awx/projects/file/creation.csv
key: FirstName
fieldnames: FirstName,LastName,ClassType
delimiter: ','
register: userdata
- name: Initialise data list
set_fact:
data_list: []
- name: Extract the list
set_fact:
data_list: "{{ data_list + [{ 'FirstName': item.FirstName, 'LastName': item.LastName, 'ClassType': item.ClassType }] }}"
loop: "{{ userdata | community.general.json_query('dict.[*][0]') }}"
- name: Set fact for data_list
set_fact:
data_list: "{{ data_list[1:] }}"
- name: If class is full time
set_fact:
path: "OU=fulltime,OU=Test OU,DC=localdemo,DC=local"
when: item.ClassType == "Full Time"
loop: "{{ data_list }}"
- name: If employment type is part time
set_fact:
path: "OU=parttime,OU=Test OU,DC=localdemo,DC=local"
when: item.ClassType == "Part Time"
loop: "{{ data_list }}"
- name: If employment type is flexi
set_fact:
path: "OU=flexi,OU=Test OU,DC=localdemo,DC=local"
when: item.ClassType == "Flexi"
loop: "{{ data_list }}"
- name: Append to original userdata list
set_fact:
userdata: "{{ data_list + ['path: item.path'] }}"
loop: "{{ data_list }}"
The job run output is as below. I have omitted some of it as it is very lengthy:
TASK [Read_csv_creation : Initialise data list] *******************************************************************************************************
ok: [localhost] => {
"ansible_facts": {
"data_list": []
},
"changed": false
}
TASK [Read_csv_creation : Read input file] ************************************************************************************************************
ok: [localhost] => {
"changed": false,
"dict": {
" FirstName ": {
"ClassType": " Employment Type ",
"FirstName": " FirstName ",
"LastName": " Last Name "
},
"Grace": {
"ClassType": "Sub Contract",
"FirstName": "Grace",
"LastName": "Higgins"
},
"Robert": {
"ClassType": "Contract",
"FirstName": "Robert",
"LastName": "Miller"
},
"Jeffrey": {
"ClassType": "Full Time",
"FirstName": "Jeffrey",
"LastName": "Keller"
}
},
"invocation": {
"module_args": {
"delimiter": ",",
"dialect": "excel",
"fieldnames": [
"FirstName",
"LastName",
"ClassType"
],
"key": "FirstName",
"path": "/var/lib/awx/projects/file/creation.csv",
"skipinitialspace": null,
"strict": null,
"unique": true
}
},
"list": []
}
TASK [Read_csv_creation : Extract the list] ***********************************************************************************************************
ok: [localhost] => (item={'FirstName': ' FirstName ', 'LastName': ' Last Name ', 'ClassType': ' Class Type '}) => {
"ansible_facts": {
"data_list": [
{
"ClassType": " Class Type ",
"FirstName": " FirstName ",
"LastName": " Last Name "
}
]
},
"ansible_loop_var": "item",
"changed": false,
"item": {
"ClassType": " Class Type ",
"FirstName": " FirstName ",
"LastName": " Last Name ",
}
}
ok: [localhost] => (item={'FirstName': '}) => {
"ansible_facts": {
"data_list": [
{
"ClassType": " Class Type ",
"FirstName": " FirstName ",
"LastName": " Last Name ",
}
]
},
"ansible_loop_var": "item",
"changed": false,
"item": {
"ClassType": "Class Time",
"FirstName": "Grace",
"LastName": "Higgins"
}
}
TASK [Read_csv_creation : Set fact for data_list] *****************************************************************************************************
ok: [localhost] => {
"ansible_facts": {
"data_list": [
{
"ClassType": "Full Time",
"FirstName": "Grace",
"LastName": "Higgins"
},
{
"ClassType": "Part Time",
"FirstName": "Robert",
"LastName": "Miller"
},
{
"EmploymentType": "Flexi",
"FirstName": "Jeffrey",
"LastName": "Keller"
}
]
},
"changed": false
}
TASK [Read_csv_creation : If class type is full time] *******************************************************************************************
ok: [localhost] => (item={'FirstName': 'Grace', 'LastName': 'Higgins', 'ClassType': 'Full Time'}) => {
"ansible_facts": {
"path": "OU=fulltime,OU=Test OU,DC=localdemo,DC=local"
},
"ansible_loop_var": "item",
"changed": false,
"item": {
"ClassType": "Full Time",
"FirstName": "Grace",
"LastName": "Higgins"
}
}
skipping: [localhost] => (item={'FirstName': 'Robert', 'LastName': 'Miller', 'ClassType': 'Part Time'}) => {
"ansible_loop_var": "item",
"changed": false,
"item": {
"EmploymentType": "Contract",
"FirstName": "Robert",
"LastName": "Miller"
},
"skip_reason": "Conditional result was False"
}
skipping: [localhost] => (item={'FirstName': .....
"ansible_loop_var": "item",
"changed": false,
"item": {
.......
"ClassType": "Flexi"
},
"skip_reason": "Conditional result was False"
}
答案1
得分: 1
给定用于测试的文件 mre
shell> cat /tmp/creation.csv
Grace,Higgins,Full Time
Robert,Miller,Part Time
Jeffrey,Keller,Flexi
读取 CSV 文件
- read_csv:
path: /tmp/creation.csv
# key: FirstName
fieldnames: FirstName,LastName,ClassType
delimiter: ','
register: userdata
当你省略参数 key 时,你会得到列表而不会'提取'
userdata.list:
- ClassType: Full Time
FirstName: Grace
LastName: Higgins
- ClassType: Part Time
FirstName: Robert
LastName: Miller
- ClassType: Flexi
FirstName: Jeffrey
LastName: Keller
要添加属性 path,创建字典 class_path
class_path:
Full Time: "OU=fulltime,OU=Test OU,DC=localdemo,DC=local"
Part Time: "OU=parttime,OU=Test OU,DC=localdemo,DC=local"
Flexi: "OU=flexi,OU=Test OU,DC=localdemo,DC=local"
从列表 map 属性 ClassType,提取 path,并创建哈希列表
path: "{{ userdata.list|map(attribute='ClassType')|
map('extract', class_path)|
map('community.general.dict_kv', 'path') }}"
得到
path:
- path: OU=fulltime,OU=Test OU,DC=localdemo,DC=local
- path: OU=parttime,OU=Test OU,DC=localdemo,DC=local
- path: OU=flexi,OU=Test OU,DC=localdemo,DC=local
zip 列表并 combine 项目。你必须使用 set_facts 因为变量 userdata 已经在 registered vars 中使用过了
- set_fact:
userdata: "{{ userdata.list|zip(path)|map('combine') }}"
得到你想要的结果
userdata:
- ClassType: Full Time
FirstName: Grace
LastName: Higgins
path: OU=fulltime,OU=Test OU,DC=localdemo,DC=local
- ClassType: Part Time
FirstName: Robert
LastName: Miller
path: OU=parttime,OU=Test OU,DC=localdemo,DC=local
- ClassType: Flexi
FirstName: Jeffrey
LastName: Keller
path: OU=flexi,OU=Test OU,DC=localdemo,DC=local
用于测试的完整 playbook 示例
- hosts: localhost
vars:
class_path:
Full Time: "OU=fulltime,OU=Test OU,DC=localdemo,DC=local"
Part Time: "OU=parttime,OU=Test OU,DC=localdemo,DC=local"
Flexi: "OU=flexi,OU=Test OU,DC=localdemo,DC=local"
path: "{{ userdata.list|map(attribute='ClassType')|
map('extract', class_path)|
map('community.general.dict_kv', 'path') }}"
tasks:
- read_csv:
path: /tmp/creation.csv
# key: FirstName
fieldnames: FirstName,LastName,ClassType
delimiter: ','
register: userdata
- debug:
var: userdata.list
- debug:
var: path
- set_fact:
userdata: "{{ userdata.list|zip(path)|map('combine') }}"
- debug:
var: userdata
英文:
Given the file for mre testing
shell> cat /tmp/creation.csv
Grace,Higgins,Full Time
Robert,Miller,Part Time
Jeffrey,Keller,Flexi
read the CSV file
- read_csv:
path: /tmp/creation.csv
# key: FirstName
fieldnames: FirstName,LastName,ClassType
delimiter: ','
register: userdata
When you omit the parameter key you get the list without 'extracting'
userdata.list:
- ClassType: Full Time
FirstName: Grace
LastName: Higgins
- ClassType: Part Time
FirstName: Robert
LastName: Miller
- ClassType: Flexi
FirstName: Jeffrey
LastName: Keller
To add the attribute path create the dictionary class_path
class_path:
Full Time: "OU=fulltime,OU=Test OU,DC=localdemo,DC=local"
Part Time: "OU=parttime,OU=Test OU,DC=localdemo,DC=local"
Flexi: "OU=flexi,OU=Test OU,DC=localdemo,DC=local"
From the list map the attribute ClassType, extract the path, and create the list of the hashes
path: "{{ userdata.list|map(attribute='ClassType')|
map('extract', class_path)|
map('community.general.dict_kv', 'path') }}"
gives
path:
- path: OU=fulltime,OU=Test OU,DC=localdemo,DC=local
- path: OU=parttime,OU=Test OU,DC=localdemo,DC=local
- path: OU=flexi,OU=Test OU,DC=localdemo,DC=local
zip the lists and combine the items. You have to use set_facts because the variable userdata has already been used in registered vars
- set_fact:
userdata: "{{ userdata.list|zip(path)|map('combine') }}"
gives what you want
userdata:
- ClassType: Full Time
FirstName: Grace
LastName: Higgins
path: OU=fulltime,OU=Test OU,DC=localdemo,DC=local
- ClassType: Part Time
FirstName: Robert
LastName: Miller
path: OU=parttime,OU=Test OU,DC=localdemo,DC=local
- ClassType: Flexi
FirstName: Jeffrey
LastName: Keller
path: OU=flexi,OU=Test OU,DC=localdemo,DC=local
<hr>
<sup>
Example of a complete playbook for testing
- hosts: localhost
vars:
class_path:
Full Time: "OU=fulltime,OU=Test OU,DC=localdemo,DC=local"
Part Time: "OU=parttime,OU=Test OU,DC=localdemo,DC=local"
Flexi: "OU=flexi,OU=Test OU,DC=localdemo,DC=local"
path: "{{ userdata.list|map(attribute='ClassType')|
map('extract', class_path)|
map('community.general.dict_kv', 'path') }}"
tasks:
- read_csv:
path: /tmp/creation.csv
# key: FirstName
fieldnames: FirstName,LastName,ClassType
delimiter: ','
register: userdata
- debug:
var: userdata.list
- debug:
var: path
- set_fact:
userdata: "{{ userdata.list|zip(path)|map('combine') }}"
- debug:
var: userdata
</sup>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论