When working with Ansible's file module to create symbolic links using a list of variables, you might encounter the frustrating error:
fatal: [vmdev] => One or more undefined variables: 'item' is undefined
The error occurs because the with_items directive isn't properly formatted in modern Ansible versions (2.4+). The correct approach uses loop instead:
tasks:
- name: Create drush alias symlinks
file:
src: /drupal/drush/{{ item.path }}.aliases.drushrc.php
dest: /home/vagrant/.drush/{{ item.dest }}.aliases.drushrc.php
state: link
loop:
- { path: 'new', dest: 'new' }
- { path: 'vmdev', dest: 'vmdev' }
Here's a full playbook example that demonstrates the correct implementation:
- hosts: all
become: yes
tasks:
- name: Ensure .drush directory exists
file:
path: /home/vagrant/.drush
state: directory
mode: '0755'
owner: vagrant
group: vagrant
- name: Create multiple symlinks for drush aliases
file:
src: "/drupal/drush/{{ item.path }}.aliases.drushrc.php"
dest: "/home/vagrant/.drush/{{ item.dest }}.aliases.drushrc.php"
state: link
force: yes
loop:
- { path: 'new', dest: 'new' }
- { path: 'vmdev', dest: 'vmdev' }
- { path: 'production', dest: 'prod' }
The solution includes several best practices:
- Uses modern
loopinstead of deprecatedwith_items - Adds directory creation as a prerequisite
- Includes
force: yesto handle existing files - Sets proper permissions with
mode,owner, andgroup
For more complex scenarios where the list comes from a variable:
vars:
drush_aliases:
- { path: 'new', dest: 'new' }
- { path: 'vmdev', dest: 'vmdev' }
tasks:
- name: Create symlinks from variable list
file:
src: "/drupal/drush/{{ item.path }}.aliases.drushrc.php"
dest: "/home/vagrant/.drush/{{ item.dest }}.aliases.drushrc.php"
state: link
loop: "{{ drush_aliases }}"
If you still encounter issues:
- Verify file paths exist with
ls -la /drupal/drush/ - Check Ansible version with
ansible --version - Run with
-vvvflag for detailed debugging - Ensure proper permissions on target directories
When working with Ansible's file module to create symbolic links using a list of variables, you might encounter the frustrating error:
fatal: [vmdev] => One or more undefined variables: 'item' is undefined
This typically occurs when trying to use the with_items loop incorrectly with the file module.
The proper way to create multiple symlinks using variables in Ansible is:
- name: Create drush alias symlinks
file:
src: "/drupal/drush/{{ item.path }}.aliases.drushrc.php"
dest: "/home/vagrant/.drush/{{ item.dest }}.aliases.drushrc.php"
state: link
loop:
- { path: 'new', dest: 'new' }
- { path: 'vmdev', dest: 'vmdev' }
- Use
loopinstead of deprecatedwith_items(Ansible 2.5+) - Proper YAML formatting with consistent indentation
- Quoted paths to handle potential spaces
For more complex scenarios where you need additional parameters:
- name: Create multiple symlinks with various parameters
file:
src: "{{ item.src_path }}"
dest: "{{ item.dest_path }}"
owner: "{{ item.owner | default('vagrant') }}"
group: "{{ item.group | default('vagrant') }}"
mode: "{{ item.mode | default('0644') }}"
state: link
loop:
- { src_path: '/drupal/drush/new.aliases.drushrc.php', dest_path: '/home/vagrant/.drush/new.aliases.drushrc.php' }
- { src_path: '/drupal/drush/vmdev.aliases.drushrc.php', dest_path: '/home/vagrant/.drush/vmdev.aliases.drushrc.php', owner: 'root' }
Sometimes you might need to:
- name: Ensure parent directory exists
file:
path: "/home/vagrant/.drush"
state: directory
mode: '0755'
- name: Create symlinks only if source exists
file:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
state: link
loop: "{{ symlink_items }}"
when: item.src is file
If you're still having issues:
- Run with
-vvvfor verbose output - Check variable names are consistent in your loop
- Verify paths exist on the target system
- Consider using
ignore_errors: yestemporarily to identify which item fails