Ansible - multiple statements with the same variables
Solution 1:
I'm new to ansible
I'm listing here some different options, so you can learn a bit more than just the ideal solution (Option 5)
Option 1: Use YAML anchors and references
This is completely unrelated to Ansible but since the files are in YAML format you're able to do something like this:
- name: Create real users
user: name="{{item.user_name}}" comment="{{item.user_description}}" home="/home/{{item.user_name}}" shell="/bin/bash" uid="{{item.user_id}}"
with_items: &my_items
- user_name: user1
user_description: user 1
user_id: 2000
- user_name: user2
user_description: user 2
user_id: 2001
- name: Copy SSH keys
copy:
src: "keys/{{ item.user_name }}.key"
dest: "/home/{{ item.user_name }}/.ssh/authorized_keys"
owner: "{{ item.user_name }}"
group: "{{ item.user_name }}"
mode: 0600
with_items: *my_items
Option 2: Variables in blocks
Blocks are a feature introduced in Ansible 2. You can define variables for blocks and use them in the contained tasks
- vars:
userlist:
- user_name: user1
user_description: user 1
user_id: 2000
- user_name: user2
user_description: user 2
user_id: 2001
block:
- name: Create real users
user: name="{{item.user_name}}" comment="{{item.user_description}}" home="/home/{{item.user_name}}" shell="/bin/bash" uid="{{item.user_id}}"
with_items: "{{ userlist }}"
- name: Copy SSH keys
copy:
src: "keys/{{ item.user_name }}.key"
dest: "/home/{{ item.user_name }}/.ssh/authorized_keys"
owner: "{{ item.user_name }}"
group: "{{ item.user_name }}"
mode: 0600
with_items: "{{ userlist }}"
Option 3: Apply the loop to an include
task and have your tasks in the included file
- include: other_file.yml
with_items:
- user_name: user1
user_description: user 1
user_id: 2000
- user_name: user2
user_description: user 2
user_id: 2001
In the included file you will be able to access the item and its properties, e.g. item.user_name
, just like you already had it:
- name: Create real users
user: name="{{item.user_name}}" comment="{{item.user_description}}" home="/home/{{item.user_name}}" shell="/bin/bash" uid="{{item.user_id}}"
- name: Copy SSH keys
copy:
src: "keys/{{ item.user_name }}.key"
dest: "/home/{{ item.user_name }}/.ssh/authorized_keys"
owner: "{{ item.user_name }}"
group: "{{ item.user_name }}"
mode: 0600
Option 4: set a fact containing your user list in a separate task
- set_fact:
userlist:
- user_name: user1
user_description: user 1
user_id: 2000
- user_name: user2
user_description: user 2
user_id: 2001
- name: Create real users
user: name="{{item.user_name}}" comment="{{item.user_description}}" home="/home/{{item.user_name}}" shell="/bin/bash" uid="{{item.user_id}}"
with_items: "{{ userlist }}"
- name: Copy SSH keys
copy:
src: "keys/{{ item.user_name }}.key"
dest: "/home/{{ item.user_name }}/.ssh/authorized_keys"
owner: "{{ item.user_name }}"
group: "{{ item.user_name }}"
mode: 0600
with_items: "{{ userlist }}"
Option 5: Use group_vars
group_vars probably make the most sense here. I guess your hosts are in some group in your inventory file, let's call it foo
.
Create a file group_vars/foo
relative to your playbook with the content:
userlist:
- user_name: user1
user_description: user 1
user_id: 2000
- user_name: user2
user_description: user 2
user_id: 2001
All hosts which belong to the group foo
will now automatically have access to the userlist
variable. And you can just use it in your tasks:
- name: Create real users
user: name="{{item.user_name}}" comment="{{item.user_description}}" home="/home/{{item.user_name}}" shell="/bin/bash" uid="{{item.user_id}}"
with_items: "{{ userlist }}"
- name: Copy SSH keys
copy:
src: "keys/{{ item.user_name }}.key"
dest: "/home/{{ item.user_name }}/.ssh/authorized_keys"
owner: "{{ item.user_name }}"
group: "{{ item.user_name }}"
mode: 0600
with_items: "{{ userlist }}"
If you don't have groups or don't want to limit it to certain groups, you can store the vars file as group_vars/all
where all hosts have access to.
Solution 2:
Thanks for such a complete answer. In the end I discovered I could use with_dict like this:
1) Create a vars.yml file (in the same directory)
---
usersxxx:
user1:
description: User1
user_id: 2001
shell: /bin/bash
...other options here
user2:
description: User2
user_id: 2002
shell: /bin/bash
...other options here
2) Create the new playbook:
---
- hosts: home
vars_files:
- vars.yml
become: yes
tasks:
- name: Create real users
user: name="{{item.key}}" comment="{{item.value.description}}" home="/home/{{item.key}}" uid="{{item.value.user_id}}"
with_dict: "{{usersxxx}}"
Looks like it works perfectly.
I only changed it to usersxxx to ensure that I wasn't hitting any python/ansible primitives.
Hope this helps someone else!