I'm trying to make loop with 2 lookup(fileglob) in my task
---
- hosts: localhost
become: yes
become_user: root
tasks:
- name: Loop with 2 lookup
copy:
src: '{{ item.src }}'
dest: '{{ item.dest }}'
loop:
- { src: "{{ lookup('fileglob', 'custom_scripts/*', wantlist=True) }}", dest: /var/custom_scripts/ }
- { src: "{{ lookup('fileglob','certs/*', wantlist=True) }}", dest: /var/custom_certs/ }
When i try to run this i get Could not find or access "path to files" in error log ansible is seeing all this files, because is listing all files which can't access. Permissions for all folders and files are set on 777
This logic to copy files seems to be flawed, and most likely causing this issue. item.src as you are trying to access, is a list (wantlist=True). In effect, you are passing a list of files to the src parameter of copy, and not 1 file.
Also, the copy module supports copying entire directories. So there should be no need to actually get the list of files.
A task such as below should do it:
- name: Loop with 2 lookup
copy:
src: '{{ item.src }}'
dest: '{{ item.dest }}'
loop:
- { src: 'custom_scripts/', dest: '/var/custom_scripts' }
- { src: 'certs/', dest: '/var/custom_certs' }
Related
I'm trying to copy the content of my directories (located on my bastion) on a server but it doesn't work.
I tried with "with_fileglob:", "with_items:" but each times, I had the error :
"'item' is undefined"
I don't understand why.
Ths is my code which doesn't work:
tasks:
- name: Copy directories...
copy:
src: "{{ item }}"
dest: "{{ dir_dest }}/"
owner: "{{ dir_owner }}"
group: "{{ dir_group }}"
mode: '0755'
with_fileglob:
- /home/ansible/delivery/my_dir/*
whereas this one works :
tasks:
- name: Copy directories...
copy:
src: "/home/ansible/delivery/my_dir/"
dest: "{{ dir_dest }}/"
owner: "{{ dir_owner }}"
group: "{{ dir_group }}"
mode: '0755'
But I can't use this 2nd solution because I have a lot a directories to copy.
Thank for your help.
tasks:
- name: Copy directories...
copy:
src: "{{ item }}"
dest: "{{ dir_dest }}/"
owner: "{{ dir_owner }}"
group: "{{ dir_group }}"
mode: '0755'
with_fileglob:
- /home/ansible/delivery/my_dir/*
Try this.
Here is my specifications in Ansible Play-Book, to make symlinks:
---
- hosts: DEVSRV
become: yes
tasks:
- name: symlink deploy_config scripts
file:
src: "{{ item }}"
dest: "/usr/local/bin/"
state: link
loop:
- "/home/foo/bar/deploy/config/dev_deploy_config.sh"
- "/home/foo/bar/deploy/config/int_deploy_config.sh"
- "/home/foo/bar/deploy/config/prod_deploy_config.sh"
In src: it iterates over the path and filenames within loop: which is good. However, how can I use just filenames for dest: without the path?
this task should do it, and its pretty self-explanatory:
- name: symlink deploy_config scripts
file:
src: "{{ item }}"
dest: "/usr/local/bin/{{ item.split('/') | last }}"
state: link
loop:
- "/home/foo/bar/deploy/config/dev_deploy_config.sh"
- "/home/foo/bar/deploy/config/int_deploy_config.sh"
- "/home/foo/bar/deploy/config/prod_deploy_config.sh"
hope it helps!
When I run the command remote_src: true I get the error
ERROR! 'remote_src' is not a valid attribute for a Task
I was wondering if there is a better way to write the code or if this is a bug
Tried to remove the offending line of code, however, the files exist on the remote host so I'm unable to copy the files into the correct location
- hosts: openvpn_server
vars:
file_vars:
- { name: ca }
- { name: server }
tasks:
- name: check if ca.crt and server.crt exists
stat:
path: /tmp/{{ item.name }}.crt
with_items: "{{ file_vars }}"
register: ensure_ca_crt_exists
- name: copying server.crt and ca.crt
become: true
copy: src={{ item.src }} dest={{ item.dest }}
with_items:
- { src: '/tmp/server.crt' , dest: '/etc/openvpn/server.crt' }
- { src: '/tmp/ca.crt' , dest: '/etc/openvpn/ca.crt' }
remote_src: true
when: ensure_ca_crt_exists.results
- name: creating Diffie-Hellman key to use during key exchange
shell: ./easyrsa gen-dh
args:
chdir: ~/EasyRSA-v3.0.6/
- name: Generating HMAC signature to strengthen servers TLS integrity
shell: openvpn --genkey --secret ta.key
- name: copying ta.key and dh.pem to /etc/openvpn
become: true
copy: src={{ item.src }} dest={{ item.dest }}
with_items:
- { src: '/home/dc/EasyRSA-v3.0.6/ta.key' , dest: '/etc/openvpn/ta.key' }
- { src: '/home/dc/EasyRSA-v3.0.6/dh.pem' , dest: '/etc/openvpn/dh.pem' }
I should be able to copy the file from the tmp folder to /etc/openvpn folder
via the remote_src command, apologizes for the badly configured register I'm fairly new to ansible
ERROR! 'remote_src' is not a valid attribute for a Task
Indentation is wrong
- name: copying server.crt and ca.crt
become: true
copy: src={{ item.src }} dest={{ item.dest }}
with_items:
- { src: '/tmp/server.crt' , dest: '/etc/openvpn/server.crt' }
- { src: '/tmp/ca.crt' , dest: '/etc/openvpn/ca.crt' }
remote_src: true
Correct
- name: copying server.crt and ca.crt
copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
remote_src: true
loop:
- {src: '/tmp/server.crt', dest: '/etc/openvpn/server.crt'}
- {src: '/tmp/ca.crt', dest: '/etc/openvpn/ca.crt'}
become: true
How do i loop using "with_fileglob". I am trying to copy files matching wildcard, but with different permissions at the destination.
- hosts: myhost
gather_facts: no
tasks:
- name: Ansible copy test
copy:
src: "{{ item.origin }}"
dest: /home/user1/tmps/
owner: user1
mode: "{{item.mode}}"
with_fileglob:
- { origin: '/tmp/hello*', mode: '640'}
- { origin: '/tmp/hi*', mode: '600'}
It throws error as below:
An exception occurred during task execution. To see the full traceback, use
-vvv. The error was: AttributeError: 'dict' object has no attribute 'rfind'
I think the cleanest way is to implement this, would be a nested loop with include_tasks.
Where you main playbook file contains:
...
vars:
my_patterns:
- origin: "/tmp/hello*"
mode: "0640"
- origin: "/tmp/hi*"
mode: "0600"
tasks:
- include_tasks: "my_glob.yml"
with_items: "{{ my_patterns }}"
loop_control:
loop_var: my_pattern
...
and a subordinate my_glob.yml-tasks file:
---
- name: Ansible copy test
copy:
src: "{{ item }}"
dest: /home/user1/tmps/
owner: user1
mode: "{{ my_pattern.mode }}"
with_fileglob: "{{ my_pattern.origin }}"
Alternative method
Using Jinja2 to populate a list of objects { 'path': '...', 'mode': '...' }' based on fileglob-lookup plugin results.
vars:
my_patterns:
- origin: '/tmp/hello*'
mode: '0640'
- origin: '/tmp/hi*'
mode: '0600'
tasks:
- copy:
src: "{{ item.paht }}"
dest: /home/user1/tmps/
owner: user1
mode: "{{ item.mode }}"
with_items: "[{% for match in my_patterns %}{% for file in lookup('fileglob', match.origin, wantlist=True) %}{ 'path':'{{ file }}','mode':'{{ match.mode }}'}{% if not loop.last %},{% endif %}{% endfor %}{% if not loop.last %},{% endif %}{% endfor %}]"
The above works if patterns are matched, you'd need to add checks if the results are not empty.
according to the documentation, you cant pass to the fileglob a dictionary variable, adding the desired file permissions after copy as you have attempted (i mean the declaration { origin: '/tmp/hello*', mode: '640'}).
simple module call that will work for you:
- hosts: localhost
gather_facts: no
tasks:
- name: Ansible copy test
copy:
src: "{{ item }}"
dest: /SAMBA_ROOT/TEMP/
owner: root
with_fileglob:
- '/tmp/hello*'
- '/tmp/hi*'
if you want to have each of the file group have different file permissions, i suggest you use 2 different calls where the mode is "hardcoded", for example:
- hosts: localhost
gather_facts: no
tasks:
- name: copy hello files
copy:
src: "{{ item }}"
dest: /SAMBA_ROOT/TEMP/
owner: root
mode: 0640
with_fileglob:
- '/tmp/hello*'
- name: copy hi files
copy:
src: "{{ item }}"
dest: /SAMBA_ROOT/TEMP/
owner: root
mode: 0600
with_fileglob:
- '/tmp/hi*'
I believe the Ansible copy module can take a whole bunch of "files" and copy them in one hit. This I believe can be achieved by copying a directory recursively.
Can the Ansible template module take a whole bunch of "templates" and deploy them in one hit? Is there such a thing as deploying a folder of templates and applying them recursively?
The template module itself runs the action on a single file, but you can use with_filetree to loop recursively over a specified path:
- name: Ensure directory structure exists
ansible.builtin.file:
path: '{{ templates_destination }}/{{ item.path }}'
state: directory
with_community.general.filetree: '{{ templates_source }}'
when: item.state == 'directory'
- name: Ensure files are populated from templates
ansible.builtin.template:
src: '{{ item.src }}'
dest: '{{ templates_destination }}/{{ item.path }}'
with_community.general.filetree: '{{ templates_source }}'
when: item.state == 'file'
And for templates in a single directory you can use with_fileglob.
This answer provides a working example of the approach laid down by #techraf
with_fileglob expects only files to live within the templates folder - see https://serverfault.com/questions/578544/deploying-a-folder-of-template-files-using-ansible
with_fileglob will only parse files in the templates folder
with_filetree maintains the directory structure when moving the template files to dest. It auto creates those directories for you at dest.
with_filetree will parse all files in the templates folder and nested directories
- name: Approve certs server directories
file:
state: directory
dest: '~/{{ item.path }}'
with_filetree: '../templates'
when: item.state == 'directory'
- name: Approve certs server files
template:
src: '{{ item.src }}'
dest: '~/{{ item.path }}'
with_filetree: '../templates'
when: item.state == 'file'
Essentially, think of this approach as copying and pasting a directory and all its contents from A to B and whilst doing so, parsing all templates.
I could not manage to do it with the other answers. This is what worked for me:
- name: Template all the templates and place them in the corresponding path
template:
src: "{{ item.src }}"
dest: "{{ destination_path }}/{{ item.path | regex_replace('\\.j2$', '') }}"
force: yes
with_filetree: '{{ role_path }}/templates'
when: item.state == 'file'
In my case folder contain both files and jinja2 templates.
- name: copy all directories recursively
file: dest={{templates_dest_path}}/{{ item|replace(templates_src_path+'/', '') }} state=directory
with_items: "{{ lookup('pipe', 'find '+ templates_src_path +'/ -type d').split('\n') }}"
- name: copy all files recursively
copy: src={{ item }} dest={{templates_dest_path}}/{{ item|replace(templates_src_path+'/', '') }}
with_items: "{{ lookup('pipe', 'find '+ templates_src_path +'/ -type f -not -name *.j2 ').split('\n') }}"
- name: copy templates files recursively
template: src={{ item }} dest={{templates_dest_path}}/{{ item|replace(templates_src_path+'/', '')|replace('.j2', '') }}
with_items: "{{ lookup('pipe', 'find '+ templates_src_path +'/*.j2 -type f').split('\n') }}"
I did it and it worked. \o/
- name: "Create file template"
template:
src: "{{ item.src }}"
dest: "{{ your_dir_remoto }}/{{ item.dest }}"
loop:
- { src: '../templates/file1.yaml.j2', dest: 'file1.yaml' }
- { src: '../templates/file2.yaml.j2', dest: 'file2.yaml' }