English 中文(简体)
How to create a dictionary list of key: value items and append it to the original list in Ansible?
原标题:

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"
}
最佳回答

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

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
问题回答

暂无回答




相关问题
Finding a class within list

I have a class (Node) which has a property of SubNodes which is a List of the Node class I have a list of Nodes (of which each Node may or may not have a list of SubNodes within itself) I need to be ...

How to flatten a List of different types in Scala?

I have 4 elements:List[List[Object]] (Objects are different in each element) that I want to zip so that I can have a List[List[obj1],List[obj2],List[obj3],List[obj4]] I tried to zip them and I ...

How to remove unique, then duplicate dictionaries in a list?

Given the following list that contains some duplicate and some unique dictionaries, what is the best method to remove unique dictionaries first, then reduce the duplicate dictionaries to single ...

Is List<> better than DataSet for UI Layer in ASP.Net?

I want to get data from my data access layer into my business layer, then prepare it for use in my UI. So i wonder: is it better to read my data by DataReader and use it to fill a List<BLClasses&...

What is the benefit to using List<T> over IEnumerable<T>?

or the other way around? I use generic lists all the time. But I hear occasionally about IEnumerables, too, and I honestly have no clue (today) what they are for and why I should use them. So, at ...

灵活性:在滚动之前显示错误的清单

我有一份清单,在你滚动之前没有显示任何物品,然后这些物品就显示。 是否有任何人知道如何解决这一问题? 我尝试了叫人名单。

Converting Dictionary to List? [duplicate]

I m trying to convert a Python dictionary into a Python list, in order to perform some calculations. #My dictionary dict = {} dict[ Capital ]="London" dict[ Food ]="Fish&Chips" dict[ 2012 ]="...

热门标签