Search code examples
loopsrolesansiblefile-globs

Ansible - Loops with_fileglob - become_user not working -- running action on source machine


Env is: Ansible 1.9.4 or 1.9.2, Linux CentOS 6.5

I have a role build where:

$ cat roles/build/defaults/main.yml:

---
build_user: confman
build_group: confman
tools_dir: ~/tools


$ cat roles/build/tasks/main.yml

- debug: msg="User is = {{ build_user }} -- {{ tools_dir }}"
  tags:
    - koba

- name: Set directory ownership
  file: path="{{ tools_dir }}" owner={{ build_user }} group={{ build_group }} mode=0755 state=directory recurse=yes
  become_user: "{{ build_user }}"
  tags:
    - koba

- name: Set private key file access
  file: path="{{ item }}" owner={{ build_user }} group={{ build_group }} mode=0600 state=touch
  with_fileglob:
    - "{{ tools_dir }}/vmwaretools-lib-*/lib/insecure_private_key"
#  with_items:
#   - ~/tools/vmwaretools/lib/insecure_private_key
  become_user: "{{ build_user }}"
  tags:
    - koba

In my workspace: hosts file (inventory) contains:

[ansible_servers]
server01.project.jenkins

site.yml (playbook) contains:

---
- hosts: ansible_servers
  sudo: yes

  roles:
    - build

I'm running the following command:

$ ansible-playbook site.yml -i hosts -u confman --private-key ${DEPLOYER_KEY_FILE} -t koba

I'm getting the following error and for some reason, become_user in Ansible while using Ansible loop: with_fileglob is NOT using ~ (home directory) of confman user (which is set in variable {{ build_user }}, instead of that, it's picking my own user ID (c123456).

In the console output for debug action, it's clear that the user (due to become_user) is confman and value of tools_dir variable is ~/tools.

PLAY [ansible_servers] ********************************************************

GATHERING FACTS ***************************************************************
ok: [server01.project.jenkins]

TASK: [build | debug msg="User is = {{ build_user }} -- {{ tools_dir }}"] *****
ok: [server01.project.jenkins] => {
    "msg": "User is = confman -- ~/tools"
}

TASK: [build | Set directory ownership] ***************************************
changed: [server01.project.jenkins]

TASK: [build | Set private key file access] ***********************************
failed: [server01.project.jenkins] => (item=/user/home/c123456/tools/vmwaretools-lib-1.0.8-SNAPSHOT/lib/insecure_private_key) => {"failed": true, "item": "/user/home/c123456/tools/vmwaretools-lib-1.0.8-SNAPSHOT/lib/insecure_private_key", "parsed": false}
BECOME-SUCCESS-ajtxlfymjcquzuolgfrrxbssfolqgrsg
Traceback (most recent call last):
  File "/tmp/ansible-tmp-1449615824.69-82085663620220/file", line 1994, in <module>
    main()
  File "/tmp/ansible-tmp-1449615824.69-82085663620220/file", line 372, in main
    open(path, 'w').close()
IOError: [Errno 2] No such file or directory: '/user/home/c123456/tools/vmwaretools-lib-1.0.8-SNAPSHOT/lib/insecure_private_key'
OpenSSH_5.3p1, OpenSSL 1.0.1e-fips 11 Feb 2013
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Applying options for *
debug1: auto-mux: Trying existing master
debug1: mux_client_request_session: master session id: 2
debug1: mux_client_request_session: master session id: 2
Shared connection to server01.project.jenkins closed.

As per the error above, the file it's trying for variable item is /user/home/c123456/tools/vmwaretools-lib-1.0.8-SNAPSHOT/lib/insecure_private_key but there's no such file inside my user ID's home directory. But, this file does exist for user confman's home directory.

i.e. the following file exists.

/user/home/confman/tools/vmwaretools-lib-1.0.7-SNAPSHOT/lib/insecure_private_key
/user/home/confman/tools/vmwaretools-lib-1.0.7/lib/insecure_private_key
/user/home/confman/tools/vmwaretools-lib-1.0.8-SNAPSHOT/lib/insecure_private_key

All, I want is to iterate of these files in ~confman/tools/vmwaretools-lib-*/.. location containing the private key file and change the permission but using "with_fileglob" become_user to set the user during an action is NOT working.

If I comment out the with_fileglob section and use/uncomment with_items section in the tasks/main.yml, then it (become_user) works fine and picks ~confman (instead of ~c123456) and gives the following output:

TASK: [build | Set private key file access] ***********************************
changed: [server01.project.jenkins] => (item=~/tools/vmwaretools/lib/insecure_private_key)

One strange thing I found is, there is no user c123456 on the target machine (server01.project.jenkins) and that's telling me that with_fileglob is using the source/local/master Ansible machine (where I'm running ansible-playbook command) to find the GLOB Pattern (instead of finding / running it over SSH on server01.project.jenkins server), It's true that on local/source Ansible machine, I'm logged in as c123456. Strange thing is, in the OUTPUT, it still shows the target machine but pattern path is coming from source machine as per the output above.

failed: [server01.project.jenkins]

Any idea! what I'm missing here? Thanks.

PS: - I don't want to set tools_dir: "~{{ build_user }}/tools" or hardcode it as a user can pass tools_dir variable at command line (while running ansible-playbook command using -e / --extra-vars "tools_dir=/production/slave/tools"

  • Further researching it, I found with_fileglob is for List of local files to iterate over, described using shell fileglob notation (e.g., /playbooks/files/fooapp/*) then, what should I use to iterate over on target/remote server (server01.project.jenkins in my case) using pattern match (fileglob)?

Solution

  • Using with_fileglob, it'll always run on the local/source/master machine where you are running ansible-playbook/ansible. Ansible docs for Loops doesn't clarifies this info (http://docs.ansible.com/ansible/playbooks_loops.html#id4) but I found this clarification here: https://github.com/lorin/ansible-quickref

    Thus, while looking for the pattern, it's picking the ~ for user c123456.

    Console output is showing [server01.project.jenkins] as it's a different processing/step to read what's there in the inventory/hosts file.

    I tried to use with_lines as well as per this post: ansible: Is there something like with_fileglobs for files on remote machine?

    But, when I tried the following, it still didn't work i.e. read the pattern on local machine instead of target machine (Ansible docs tells with_items doesn't run on local machine but on the controlling machine):

      file: path="{{ item }}" .... 
      with_items: ls -1 {{ tools_dir }}/vmwaretools-lib-*/lib/insecure_private_key 
      become_user: {{ build_user }}
    

    Finally to solve the issue, I just went on the plain OS command round using shell (again, this might not be a very good solution if the target env is not a Linux type OS) but for now I'm good.

    - name: Set private key file access
      shell: "chmod 0400 {{ tools_dir }}/vmtools-lib-*/lib/insecure_private_key"
      become_user: "{{ build_user }}"
      tags:
        - koba