Reputation: 797
I want to create some directories from a list I have in my vars/main.yml
.
- app_root:
network_prod: "/var/www/prod/network/app"
database_prod: "/var/www/prod/db/app"
My tasks/main.yml
so far has this:
- name: Create application directory structure
file:
path: "{{ item }}"
state: directory
mode: 755
with_items:
- app_root
but doesn't work. I thought this could be achieved using with_dict
and I also tried:
- name: Create application directory structure
file:
path: "{{ item.value }}"
state: directory
mode: 755
with_dict:
- app_root
but I got: fatal: [vagrant.dev] => with_dict expects a dict
.
I've read all about looping-over-hashes, but this doesn't seem to work.
The reason I'm using this notation is because I use these variables elsewhere as well and I need to know how to call them.
Upvotes: 4
Views: 7625
Reputation: 416
I think that the approach with with_dict
was correct and I believe that the only issue here is the dash -
in front of app_root
variable. Instead of:
- name: Create application directory structure
file:
path: "{{ item.value }}"
state: directory
mode: 755
with_dict:
- app_root
It should be:
- name: Create application directory structure
file:
path: "{{ item.value }}"
state: directory
mode: 755
with_dict: app_root
See the difference on the way the variable app_root
is passed to with_dict
.
A dash in YAML starts a list and the elements are not treated as variables but as literals, think of it as if you were passing an immutable string 'app_root' to with_dict
(not exactly true but it helps me to think it this way) so when_dict
fails to parse it because it is given a list instead of the expected dictionary. However, without a dash, with_dict
is populated with the variable app_root
instead and it will parse it without issues.
Upvotes: 0
Reputation: 103
In vars/main.yml
, try removing the dash in front of app_root
.
app_root:
network_prod: "/var/www/prod/network/app"
database_prod: "/var/www/prod/db/app"
Upvotes: 0
Reputation: 20719
I personally find it a bit easier to convert yaml to json to make sure I'm understanding it properly. Take your example:
- app_root:
network_prod: "/var/www/prod/network/app"
database_prod: "/var/www/prod/db/app"
What you have here is not a list, but a nested dictionary. If you converted this to json it would look like this:
[
{
"app_root": {
"network_prod": "/var/www/prod/network/app",
"database_prod": "/var/www/prod/db/app"
}
}
]
In order to loop through this in Ansible you would need to dereference two levels of a dictionary, the first being app_root
and the second being the path elements. Unfortunately I don't think Ansible supports looping through nested dictionaries, only through nested loops.
Your best bet is probably to redo the way you're defining your paths so that you're not creating as complex a data structure. If all you're doing in this case is iterating over a list of paths in order to ensure the directories exist then I'd suggest something like this in your vars/main.yml
file:
network_prod: "/var/www/prod/network/app"
database_prod: "/var/www/prod/db/app"
app_root:
- network_prod
- database_prod
Then you can have a task like this:
file: path={{ item }}
state=directory
with_items: app_root
Upvotes: 1