debops / debops-playbooks

Ansible playbooks used by DebOps project
GNU General Public License v3.0
488 stars 88 forks source link

cannot use lookup on paths with a space #185

Open muelli opened 9 years ago

muelli commented 9 years ago

I am trying to use the MySQL role and debops uses the lookup function to locate a password. That, however, does not work when the directory contains spaces.

TASK: [debops.mysql | debug var=secret] *************************************** 
ok: [default] => {
    "var": {
        "secret": "/home/muelli/vcs/repository/2015 Projects Deliverables/some more spaces/ansible/../secret"
    }
}

TASK: [debops.mysql | Manage MySQL users] ************************************* 
fatal: [default] => Failed to template {{ item.password | default(lookup("password", secret|replace(" ", "\\ ") + "/credentials/" + ansible_fqdn + "/mysql/" + item.name + "/password length=" + mysql_password_length)) }}: need more than 1 value to unpack

FATAL: all hosts have already failed -- aborting

The playbook is as simple as that:

- hosts: all
  sudo: yes

  vars:
    # Hm, mysql seems to be locked
    tcpwrappers: False

  pre_tasks:
    ### This is more logic for detecting whether mysql is already installed
    - name: Check if foo is installed
      command: dpkg-query -l mysql-server
      failed_when: False
      changed_when: False
      register: deb_check

    - debug: var=ohai_ip_address
    - command: echo Always restart mysql prior to making changes...
      # Because when we already run with --skip-grant-tables then we
      # cannot update users' passwords.
      changed_when: True
      # This does not necessarily help when mysqld is not yet installed :(
      failed_when: False
      # So we add more logic here
      when: deb_check.stdout.find('no packages found') != -1
      notify: ['Restart mysql']

  roles:
    # Include SSHd so that SSH access (for ansible) will be allowed
    - debops.sshd
    - role: debops.mysql
      mysql_mysqld_bind_address: '0.0.0.0'
      mysql_root_password: root
      mysql_users:
        - name: root
          host: '%'
          password: 'root'
          priv: mysql.*:ALL
          append_privs: yes
          state: present

and I run ansible like this:

env ANSIBLE_FILTER_PLUGINS=~/.ansible/plugins/filter_plugins/:/usr/share/ansible_plugins/filter_plugins:~/vcs/debops.playbooks/playbooks/filter_plugins/   ANSIBLE_LOOKUP_PLUGINS=~/.ansible/plugins/lookup_plugins/:/usr/share/ansible:~/vcs/debops.playbooks/playbooks/:~/vcs/debops.playbooks/playbooks/library/database/ldap/:~/vcs/debops.playbooks/playbooks/library/database/:~/vcs/debops.playbooks/playbooks/library/database/   ANSIBLE_ROLES_PATH=~/vcs/:~/vcs/ansible-hydra/roles   ANSIBLE_LIBRARY=~/vcs/debops.playbooks/playbooks/library/  ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=false PYTHONUNBUFFERED=1 ANSIBLE_SSH_ARGS='-o ForwardAgent=yes -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/home/muelli/.vagrant.d/insecure_private_key --user=vagrant --connection=ssh --inventory-file=ansible/vagrant_ansible_inventory  -vv --limit='all' ansible/playbook.yml

I expected it to work fine, because it does in a directory without spaces.

drybjed commented 9 years ago

It looks like the Ansible password lookup plugin does not handle paths with spaces correctly. You can test this using the playbook:

---

- hosts: localhost

  vars:

    dir: '/tmp/dir with spaces'

  tasks:

    - name: Lookup the password
      set_fact:
        pass: '{{ lookup("password", dir + "/subdir/password") }}'

    - name: Display password
      debug: var=pass

When the file is created manually and looked up with file plugin, Ansible works correctly.

I suggest that you should create an issue in the Ansible project repository about this. It cannot be sloved with a playbook change.

muelli commented 9 years ago

yep, that fails:

>cat ansible/playbook.yml 
---

- hosts: localhost

  vars:

    dir: '/tmp/dir with spaces'

  tasks:

    - name: Lookup the password
      set_fact:
        pass: '{{ lookup("password", dir + "/subdir/password") }}'

    - name: Display password
      debug: var=pass
>
ansible-playbook --inventory-file=ansible/vagrant_ansible_inventory  -vv  ansible/playbook.yml 
 [WARNING]: provided hosts list is empty, only localhost is available

PLAY [localhost] ************************************************************** 

GATHERING FACTS *************************************************************** 
<localhost> REMOTE_MODULE setup
ok: [localhost]

TASK: [Lookup the password] *************************************************** 
fatal: [localhost] => Failed to template {{ lookup("password", dir + "/subdir/password") }}: need more than 1 value to unpack

FATAL: all hosts have already failed -- aborting

PLAY RECAP ******************************************************************** 
           to retry, use: --limit @/home/muelli/playbook.retry

localhost                  : ok=1    changed=0    unreachable=1    failed=0   

Other lookup plugins work (well, I've only tested the file one), but the password one seems to be broken. Let me file a bug.