Synchronize from localhost to another host which is not the playbook host - ansible

I'm running an Ansible playbook for host_a. Some tasks I delegate to host_b.
Now I would like to use the synchronize module to copy a directory from localhost to host_b. But delegate_to is the wrong option here, since this results in copying from host_b to host_a.
Is there a possibility to do that?
- hosts: host_a
tasks:
- name: rsync directory from localhost to host_b
synchronize:
# files on localhost
src: files/directory
dest: /directory/on/host_b
# delegate_to does not work here
# delegate_to: host_b
The only solution I can think of is deleting the target directory and then using a recursive copy with the copy module.
I couldn't find anything in the module documentation.
(Using ansible 2.4.2.0)
Doing this task in its own play for host_b is also not really an option because the variables I need for this task depend on host_a.

The easiest solution in this case is to use rsync command with local_action, i.e
- hosts: cache1
tasks:
- name: rsync directory from localhost to host_b
local_action: command rsync -az "{{ playbook_dir }}/files/directory" "{{ hostvars['host_b']['ansible_host'] }}:/directory/on/host_b"
{{ playbook_dir }} helps by not hardcoding paths on local system.

Related

ansible copy in different host

I write a simple playbook to copy some configuration files on a certain machine.
I need to copy this file in a different host too for backup. Is possible to declare different host in the same playbook?
I need this cause my "backup host" can be different and I retrieve it from the hostname I use.
I tried both copy and raw module and nothing seems to work
here the example of playbook
- name: find file
find:
file_type: directory
paths: /prd/viv/dat/repository/
patterns: "{{inventory_hostname}}"
recurse: yes
register: find
delegate_to: localhost
- name: Copy MASTER
raw: echo xmonit$(echo {{find.files[0].path}} | cut -d "/" -f7 )
delegate_to: localhost
register: xmonit
- debug:
msg: "{{xmonit.stdout}}"
- name: Copy MASTER raw
raw: sshpass -p "mypass" scp {{find.files[0].path}}/master.cfg myuser#{{xmonit.stdout}}:/prd
delegate_to: localhost
#- name: Copy MASTER
#copy:
#src: "{{find.files[0].path}}/master.cfg"
#dest: /prd/cnf/dat/{{inventory_hostname}}/
edit: if I use the copy module the destination remains that of the main host while the goal is to copy to a third host.
I need to declare a different host for this single task
- name: Copy MASTER
copy:
src: "{{find.files[0].path}}/master.cfg"
dest: /prd/cnf/dat/{{inventory_hostname}}/
Like Zeitounator told me in the comments copy module are the best way to act.
like this it work for me
- name: Copy MASTER
copy:
src: "{{find.files[0].path}}/master.cfg"
dest: /prd/cnf/dat/{{inventory_hostname}}/
delegate_to: xmonit.stdout_lines[0]

Fail task/play when host not reachable Ansible

I have written a playbook which copies a file from source to destination on multiple hosts. The playbook works if all hosts are reachable but it doesn't fail if one of the host is unreachable.
ansible-playbook -i "10.11.12.13,10.11.12.14," -e "hostid=12345" test.yml
.e.g. if the host "10.11.12.13" is not reachable task execution skips the unreachable host and move onto the next host.
Sample playbook
- hosts: localhost
gather_facts: no
tasks:
- debug: msg="backup_restore.py file not found"
- name: Copy file
hosts: all
remote_user: test
gather_facts: no
vars:
srcFolder: "/home/test"
destFolder: "/opt/config"
tasks:
- block:
- name: Copy file to node
copy:
src: '{{srcFolder}}/self.config'
dest: '{{destFolder}}/self.config'
Is there a way to fail the task if the any of the hosts are not reachable. I am using ansible 2.6.1. Thank you in advance.
Brute force solution is any_errors_fatal
- name: Copy file
hosts: all
any_errors_fatal: true
Overview of other options is in Abort execution of remaining task if certain condition is failed.

Ansible: Limit a task in a playbook to localhost

I want to restrict an Ansible play to a specific host
Here's a cut down version of what I want:
- hosts some_host_group
tasks:
- name: Remove existing server files
hosts: 127.0.0.1
file:
dest: /tmp/test_file
state: present
- name: DO some other stuff
file:
...
I want to (as an early task), remove a local directory (I've created a file in the example as it's a more easily observed test). I was under the impression that I could limit a play to a set of hosts with the "hosts" parameter to the task -
but I get this error:
ERROR! 'hosts' is not a valid attribute for a Task
$ansible --version
ansible 2.3.1.0
Thanks.
PS I could wrap the ansible in a shell fragment, but that's ugly.
You should use delegate_to or local_action and tell Ansible to run the task only once (otherwise it will try to delete the directory as many times as target hosts in your play, although it won't be a problem).
You should also use absent not present if you want to remove directory, as you stated.
- name: Remove existing server files
delegate_to: 127.0.0.1
run_once: true
file:
dest: /tmp/test_file
state: absent
There are syntax errors in your playbook, have a look at Ansible Intro, Local Playbooks and Delegation.
- hosts: some_host_group
tasks:
- name: Remove existing server files
- hosts: localhost
tasks:
- file:
dest: /tmp/test_file
state: present
- name: DO some other stuff
file:

how to use synchronize module to copy file to many servers

I tried to find an example where I can pull a file from a serverA to a group of servers.
mygroup consists of 10 servers. need to copy that file over to those 10 servers.
here is what I have but its not working exactly. I can do one to one copy no problem without the handlers part.
- hosts: serverA
tasks:
- name: Transfer file from serverA to mygroup
synchronize:
src: /tmp/file.txt
dest: /tmp/file.txt
mode: pull
handlers:
- name: to many servers
delegate_to: $item
with_items: ${groups.mygroup}
You should carefully read the documentation about how ansible works (what is host pattern, what is strategy, what is handler...).
Here's the answer to your question:
---
# Push mode (connect to xenial1 and rsync-push to other hosts)
- hosts: xenial-group:!xenial1
gather_facts: no
tasks:
- synchronize:
src: /tmp/hello.txt
dest: /tmp/hello.txt
delegate_to: xenial1
# Pull mode (connect to other hosts and rsync-pull from xenial1)
- hosts: xenial1
gather_facts: no
tasks:
- synchronize:
src: /tmp/hello.txt
dest: /tmp/hello.txt
mode: pull
delegate_to: "{{ item }}"
with_inventory_hostnames: xenial-group:!xenial1
Inventory:
[xenial-group]
xenial1 ansible_ssh_host=192.168.168.186 ansible_user=ubuntu ansible_ssh_extra_args='-o ForwardAgent=yes'
xenial2 ansible_ssh_host=192.168.168.187 ansible_user=ubuntu ansible_ssh_extra_args='-o ForwardAgent=yes'
xenial3 ansible_ssh_host=192.168.168.188 ansible_user=ubuntu ansible_ssh_extra_args='-o ForwardAgent=yes'
Keep in mind that synchronize is a wrapper for rsync, so for this setup to work, there must be ssh-connectivity between target hosts (usually you have ssh connection between control-host and target hosts). I use agent forwarding for this.

Copying files from the specified hosts to others in ansible

I have three hosts available in my inventory file
[controller]
1.1.1.1
2.2.2.2
3.3.3.3
i have a variable in group_var folder which specifies the master node
master=1.1.1.1
sql.conf is available in my home directory (/home/ubuntu/sql.conf) of all 3 controller hosts.
Now, i need to copy the file (test.txt) from master to others . Is there any way in ansible to copy the files from one specific server to others.
i am trying like this but couldnt achieve though.
- hosts: all
sudo: yes
tasks:
- name: copy files
local_action: command rsync -a /home/ubuntu/test.txt {{ master }}:///home/ubuntu/test.txt
One option is to use the fetch module to copy the file from the master node to your local node, and then use the copy module normally to distribute that file to other nodes. Something like:
- hosts: master
tasks:
- fetch:
src: /path/to/myfile.txt
dest: tmp/
- hosts: all:!master
tasks:
- copy:
src: tmp/master/myfile.txt
dest: /path/to/myfile.txt

Resources