# copy files based on descending precedence

**URL:** <https://forum.ansible.com/t/copy-files-based-on-descending-precedence/37899>\
**Category:** Ansible Project\
**Created:** [April 18, 2023, 3:09pm UTC](https://forum.ansible.com/t/copy-files-based-on-descending-precedence/37899 "2023-04-18T15:09:36Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![mdidomenico](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@mdidomenico](https://forum.ansible.com/u/mdidomenico)\
**Post date:** [April 18, 2023, 3:09pm UTC](https://forum.ansible.com/t/copy-files-based-on-descending-precedence/37899/1 "2023-04-18T15:09:36Z")

</div>

the below block is an example block i use in a few places to copy in  
config files and select a host specific file if it exists. not sure  
if it's the best way, but it works for now. what i'd like to do is  
add in group selection as well. ie if there's group file look for  
that first

so above line 5 you could have  
"files/{{ansible\_local.baseos.ver}}/{{item.src}}\_AG{{group}}" but  
clearly that wont work because there likely is more then on group  
attached to a host. so i need to try all the groups of a host and see  
if there's a matching file. the only way i can think to do it is to  
create a second task that looks in the repository for a matching group  
file and then registers a variable which i can include in the below  
block above line 5

is there a better way?

&nbsp;&nbsp;1 ---  
&nbsp;&nbsp;2 - name: copy pam etc/security/access.conf file  
&nbsp;&nbsp;3 vars:  
&nbsp;&nbsp;4 findme:  
&nbsp;&nbsp;5 - "files/{{item.src}}\_AH{{ansible\_hostname}}"  
&nbsp;&nbsp;6 - "files/{{item.src}}"  
&nbsp;&nbsp;7 ansible.builtin.copy:  
&nbsp;&nbsp;8 src: "{{ lookup('ansible.builtin.first\_found', findme) }}"  
&nbsp;&nbsp;9 dest: "/{{item.src}}"  
10 owner: "{{item.owner}}"  
11 group: "{{item.group}}"  
12 mode: "{{item.mode}}"  
13 with\_items:  
14 - { src: "etc/security/access.conf", owner: "root", group:  
"root", mode: "0644" }

---

<div class="post-metadata">

**Author:** ![mdidomenico](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@mdidomenico](https://forum.ansible.com/u/mdidomenico)\
**Post date:** [April 18, 2023, 3:39pm UTC](https://forum.ansible.com/t/copy-files-based-on-descending-precedence/37899/2 "2023-04-18T15:39:23Z")

</div>

i managed to come up with this, but seems like it could be cleaner

---

<div class="post-metadata">

**Author:** ![Walter\_Rowe](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/walter_rowe/32/4506_2.png) [@Walter\_Rowe](https://forum.ansible.com/u/Walter_Rowe)\
**Post date:** [April 18, 2023, 4:38pm UTC](https://forum.ansible.com/t/copy-files-based-on-descending-precedence/37899/3 "2023-04-18T16:38:31Z")

</div>

I’m not sure what value the with\_items adds to this. Its all hardcoded values so why not hard code them into the parameters of the task?

> ansible.builtin.copy:  
> src: “{{ lookup(‘ansible.builtin.first\_found’, findme) }}”  
> dest: “/etc/security/access.conf”

> owner: “root”

> group: “root”

> mode: “0644”

Very clever use of first\_found and your find\_me vars definition.

Walter

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [April 18, 2023, 4:56pm UTC](https://forum.ansible.com/t/copy-files-based-on-descending-precedence/37899/4 "2023-04-18T16:56:18Z")

</div>

It seems to me that you’re re-implementing variable precedence, but only for one variable.  
What if, in group\_vars/all, you define  
access\_conf\_src\_file: access.conf  
Then in your group\_vars/_whatever_ (for relevant groups of course, for which the other one isn’t specific enough), you define  
access\_conf\_src\_file: access.conf\_AG_whatever_  
Finally, if you have any hosts which need even more specificity, you define in your host\_vars/_snowflake1_.your.dom  
access\_conf\_src\_file: access.conf\_AH_snowflake_  
Then your copy task can just use “{{ access\_conf\_src\_file }}” without invoking magical expressions.

Admittedly, the appeal of having the Right Thing happen just by creating the appropriately named src file is compelling. But it isn’t the way the rest of your playbook variables work, so, hmm.

But next, I start to wonder if the right answer isn’t to put all the logic and magic in a template and use ansible.builtin.template instead of ansible.builtin.copy.

---

<div class="post-metadata">

**Author:** ![Walter\_Rowe](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/walter_rowe/32/4506_2.png) [@Walter\_Rowe](https://forum.ansible.com/u/Walter_Rowe)\
**Post date:** [April 18, 2023, 5:14pm UTC](https://forum.ansible.com/t/copy-files-based-on-descending-precedence/37899/5 "2023-04-18T17:14:24Z")

</div>

My sense is they are searching from most specific to least specific file. The first one they find they use. The remaining params are hardcoded. We do a similar thing when looking for vars files. We might search for RedHat8, then RedHat, then Linux.

- name: Add OS specific variables for {{ ansible\_os\_family }} family  
include\_vars: “{{ loop\_vars }}”  
with\_first\_found:
- files:
- “{{ ansible\_distribution }}-{{ ansible\_distribution\_version }}.yml”
- “{{ ansible\_distribution }}-{{ ansible\_distribution\_major\_version }}.yml”
- “{{ ansible\_distribution }}.yml”
- “{{ ansible\_os\_family }}-{{ ansible\_distribution\_version }}-family.yml”
- “{{ ansible\_os\_family }}-{{ ansible\_distribution\_major\_version }}-family.yml”
- “{{ ansible\_os\_family }}-family.yml”
- “{{ ansible\_system }}.yml”
- “defaults.yml”  
paths:
- “vars”  
loop\_control:  
loop\_var: loop\_vars

Walter
