0
votes

Using the below snippet of ansible code, I am trying to create multiple subdirectories as per the variables stored in vars/main.yml. So the goal is for every user per env, I am attempting to create multiple sub folders

Eventually, the folders should be created like

/home/testuser1/subdir1
/home/testuser1/subdir2
/home/testuser2/subdir3/subdir4
/home/testuser2/subdir5/subdir6
/home/testuser3/subdir7
/home/testuser3/subdir8
/home/testuser4 - testuser4 will not have any subfolders, so i assume ansible will not take any action

Playbook file:

---
- hosts: all
user: test
sudo: yes
vars_files:
- defaults/main.yml

tasks:

  - name: Create directories for each env
  file: path="{{ home }}/{{ item.0 }}{{ item.1.name }}/{{item.0.subdir}}" owner="{{ item.0 }}{{ item.1.name }}" group="{{ item.0 }}{{ item.1.name }}" mode=755 state=directory
  with_subelements:
  - "{{ env }}"
  - "{{ userdir }}"
  - "{{ subdirs }}"

vars/main.yml

env:
- test
- qa

userdir:
- name: user1
  subdir:
  - subdir1
  - subdir2
- name: user2
  subdirs:
  - subdir3/subdir4
  - subdir5/subdir6
- name: user3
  subdirs:
  - subdir7
  - subdir8
- name: user4
  subdirs:
  - []

However, after the execution of the playbook, I am getting a strange error. I am sure something is wrong in the above code, but I couldnt move further. Appreciate if some experts can throw some light

TASK: [Create directories for each env]         ****************************
fatal: [localhost] => subelements lookup expects a list of two items, first a dict or a list, and second a string

FATAL: all hosts have already failed -- aborting
1

1 Answers

1
votes

As the error message tells, with_subelements expects a string, not a var for the 2nd element. The string must be a property in each element of the first dict/list. But more problematic is, a 3rd element is not supported.

The best probably would be to loop only over the users and their directories and make the environments static, because there currently is no solution to have nested loops:

- name: Create directories for test env
  file: path="{{ home }}/test{{ item.0.name }}/{{item.1}}" owner="test{{ item.0.name }}" group="test{{ item.0.name }}" mode=755 state=directory
  with_subelements:
  - userdir
  - subdirs

- name: Create directories for qa env
  file: path="{{ home }}/qa{{ item.0.name }}/{{item.1}}" owner="qa{{ item.0.name }}" group="qa{{ item.0.name }}" mode=755 state=directory
  with_subelements:
  - userdir
  - subdirs

In Ansible 2.0 it will (again) be possible to have nested loops by using with_items together with the include statement. Then you will be able to do something like this:

- include: create_directories.yml env={{ item }}
  with_items: env

And in the file create_directories.yml then only one task:

- name: Create directories for {{ env }} env
  file: path="{{ home }}/{{ env }}{{ item.0.name }}/{{item.1}}" owner="{{ env }}{{ item.0.name }}" group="{{ env }}{{ item.0.name }}" mode=755 state=directory
  with_subelements:
  - userdir
  - subdirs

I don't know when Ansible 2.0 will be released but you could try the code directly from github. They have a v2_final branch, but it appears the devel branch has more recent code.