with_items and register in a role/main.yml

Hi,

I’ve created a small demo below which demonstrates my problem.
I can’t seem to invoke the with_items and call {{item}} later on. What am I doing wrong? I’ve tried searching obviously but I can’t find the direct answer, sorry for the newbie question.

My playbook invokes a role, and below is my role:

  • name: Mytest to register a variable

find: paths=“/tmp/demo/” patterns=“*.txt”
register: r

  • name: mytest to show my results
    debug: msg=“{{item}}”
    with_items: r

The above doesn’t give the desired result. When i change my task mytest into

  • name: mytest
    debug: msg={{r.files.0.path}}

then i do get the first .txt file found, I can’t seem to make it dynamically.

Ultimately I’m trying to create a loop true a directory, and based on the file extension I want to invoke a certain action. For example, if the file extension is .sh, then invoke shell. If it’s .sql, then invoke sqlplus, and more extensions. If the extension is not listed then copy the file. Perhaps my whole approach is wrong in the first place, I’m trying to take it step by step of course, which might lead me in a wrong direction?

Again, thanks so much.

r is avariable after registering.
So i think you sgould use "{{ r }}"

I've created a small demo below which demonstrates my problem.
I can't seem to invoke the with_items and call {{item}} later on. What am I
doing wrong? I've tried searching obviously but I can't find the direct
answer, sorry for the newbie question.

My playbook invokes a role, and below is my role:
  - name: Mytest to register a variable
    find: paths="/tmp/demo/" patterns="*.txt"
    register: r

  - name: mytest to show my results
    debug: msg="{{item}}"
    with_items: r

The above doesn't give the desired result. When i change my task mytest
into
  - name: mytest
    debug: msg={{r.files.0.path}}
then i do get the first .txt file found, I can't seem to make it
dynamically.

- name: mytest to show my results
   debug: msg="{{ item.path }}"
   with_items: r.files

Ultimately I'm trying to create a loop true a directory, and based on the
file extension I want to invoke a certain action. For example, if the file
extension is .sh, then invoke shell. If it's .sql, then invoke sqlplus, and
more extensions. If the extension is not listed then copy the file. Perhaps
my whole approach is wrong in the first place, I'm trying to take it step
by step of course, which might lead me in a wrong direction?

It sounds like a wrong approach, but that doesn't mean that is wrong.
But there may be better ways reach your objective.

You could try explaining what you are trying to achieve and maybe someone on the list could help you toward a more correct direction.

Hi,

Thanks for your reply, what I’m trying to do is a simple copy and paste (deploy a release).
Specifically, I want to list thru the directory and copy all files that are not in the ./ins directory.

problem one: I couldn’t figure that out with the copy command, so i used "command: "find ./demo_deploy -type f ! -path ‘./demo_deploy/ins/*’ "

problem two: i cant seem to figure out how to execute the above in a with_items, so i thought to place the result in an register. As followed:

  • name: Register - Copy files

command: “find ./demo_deploy -type f ! -path ‘./demo_deploy/ins/’ ! -path './demo_deploy/roles/’ ! -path ‘./demo_deploy/host_vars/*’”
register: copy_files

  • name: Copy files

command: cp {{ item }} /tmp/bb/
with_items:

  • “{{copy_files.stdout_lines}}”
    tags:
  • copy_release

This works fine… however, if I place them in a role, then my register isnt loaded when i run my plabook with --copy_release tag.

I guess I’m getting lost here, where the original challenge is simple: copy all files except 1 directory.

Any help is appreciated!

Hi Stewart,

First: including only "copy_release" tag makes ansible skip the first task, as it's tagged only with "copy_files".

Second: you can also use with_filetree<https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/lookup/filetree.py&gt; lookup (introduced in Ansible 2.2) or with_fileglob<http://docs.ansible.com/ansible/playbooks_loops.html#id4&gt; (if you don't need to iterate a directory recursively).
Then use separate tasks for different actions/extensions with 'when' directive.
This way you'll skip the register task.
Note that these lookups return different data structures for {{ item }}.
fileglob's item is a string containing the file/directory absolute path, while filetree's item is a dict.
Some "documentation" can be found in original pull request<https://github.com/ansible/ansible/pull/14332&gt;&#39;s description.

When executed as "with_filetree: /tmp", it looks like this for a file (or a link with "state":"link"):
    "item": {
        "ctime": 1479723235.151,
        "gid": 501,
        "group": "xxx",
        "mode": "0664",
        "mtime": 1479723235.151,
        "owner": "xxx",
        "path": "ansible-debug.log",
        "root": "/tmp",
        "selevel": "s0",
        "serole": "object_r",
        "setype": "user_tmp_t",
        "seuser": "unconfined_u",
        "size": 4104,
        "src": "/tmp/ansible-debug.log",
        "state": "file",
        "uid": 501
    }
And like this for a directory (there's no "src"):
    "item": {
        "ctime": 1479810261.0929983,
        "gid": 501,
        "group": "xxx",
        "mode": "0775",
        "mtime": 1479810261.0929983,
        "owner": "xxx",
        "path": "test",
        "root": "/tmp",
        "selevel": "s0",
        "serole": "object_r",
        "setype": "user_tmp_t",
        "seuser": "unconfined_u",
        "size": 4096,
        "state": "directory",
        "uid": 501
    }

This example copies files only:

  - name: Copy files
    command: cp {{ item.src }} /tmp/bb/{{ item.path }}
    with_filetree: ./demo_deploy
    when: item.state == 'file' and item.path.split('/')[0] not in ['ins', 'roles', 'host_vars']
    tags:
      - copy_release
if you need to preserve the same directory structure, then add this before the task above:
  - name: Create directories
    file:
      dest: /tmp/bb/{{ item.path }}
      state: directory
    with_filetree: ./demo_deploy
    when: item.state == 'directory' and item.path.split('/')[0] not in ['ins', 'roles', 'host_vars']
    tags:
      - copy_release

Cheers,
Marko