Home > Software engineering >  Error "Vars in a Task must be specified as a dictionary, or a list of dictionaries"
Error "Vars in a Task must be specified as a dictionary, or a list of dictionaries"

Time:09-08


'data_list' consists of the values in the csv file. I want to use the values in 'data_list' to loop through the parameters in the 'Create user' section of the playbook, but I am getting this error after running my playbook:
TASK [Create Multiple Users : Create multiple users] ***************************
fatal: [10.12.201.20]: FAILED! => {"reason": "Vars in a Task must be specified as a dictionary, or a list of dictionaries\n\nThe error appears to be in '/runner/project/Windows AD/roles/Create Multiple Users/tasks/Create_multiple_users.yml': line 14, column 9, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n      - \"{{ item.groups }}\"\n  vars: data_list\n        ^ here\n"}

This is my playbook:

---
- name: Read Users 
  hosts: localhost
  vars:
    data_list: []
  tasks:
  - read_csv:
      path: user.csv
      key: name  
      fieldnames: name,firstname,surname,displayName,groups
      delimiter: ','
    register: userdata


  - name: Extract the list
    set_fact:
      data_list: "{{ data_list   [{ 'name': item.value.name, 'firstname': item.value.firstname, 'surname': item.value.surname, 'displayName': item.value.displayName, 'groups': item.value.groups }] }}"
    loop: "{{ userdata.dict|dict2items }}"


- name: Create multiple Windows AD user accounts
  hosts: "{{ hostname }}"
  gather_facts: false
  any_errors_fatal: false
  become: yes
  become_method: runas
  become_user: admin
  roles:
    - { role: Create Multiple Users }


- name: Create users
  community.windows.win_domain_user:
    name: "{{ item.name }}"
    firstname: "{{ item.firstname }}"
    surname: "{{ item.surname }}"
    attributes:
      displayName: "{{ item.firstname   ' '   item.surname }}"
    groups:
      - "{{ item.groups }}"
  vars: data_list 
  with_items: 
    - "{{ data_list }}"

What is the correct vars that I should write?

CodePudding user response:

This is the line causing the error in your task

    vars: data_list

As mentioned in your error message, the vars section should look like:

    vars:
      var1: value1
      var2: value2

But this is not the only problem in you above script. You are gathering your csv data in a separate play on localhost and setting that info as a fact in variable data_list. When your first play is over, that var will only be known from the localhost target. If you want to reuse it in a second play targeting other hosts, you'll have to get that var from the hostvars magic variable

{{ hostvars.localhost.data_list }}

This is not the best approach here as you can easily shorten your playbook to a single play. The trick here is to delegate your csv gathering task to localhost and set run_once: true so that the registered var is calculated only once and distributed to all hosts with the same value. You can also drop the set fact which basically copies the same key: value to a new var.

Here is an (untested) example playbook to show you the way:

---
- name: Create multiple Windows AD user accounts from CSV
  hosts: "{{ hostname }}"
  gather_facts: false

  tasks:
    - name: read csv from localhost (single run same registered var for all hosts)
      read_csv:
        path: user.csv
        key: name  
        fieldnames: name,firstname,surname,displayName,groups
        delimiter: ','
      register: userdata
      run_once: true
      delegate_to: localhost

    - name: Create users
      community.windows.win_domain_user:
        name: "{{ item.name }}"
        firstname: "{{ item.firstname }}"
        surname: "{{ item.surname }}"
        attributes:
          displayName: "{{ item.firstname   ' '   item.surname }}"
        groups:
          - "{{ item.groups }}"
      # This will work on any number of hosts as `userdata`
      # now has the same value for each hosts inside this play.
      # we just have to extract the values from each keys from
      # `userdata` and loop on that list
      loop: "{{ userdata.dict | dict2items | map(attribute='value') }}"
  • Related