Search code examples
ansibleansible-inventoryansible-facts

Copying local directories to remote hosts with the same directory name


I have three local directories with the following structure:

$ tree .
|_ inventory
|_ deploy.yml
|_ key
    |_ node1
    |   |_ ...  # several files, like id_rsa.pub etc
    |_ node2 
    |   |_ ...  # several files, like id_rsa.pub etc
    |_ node3 
        |_ ...  # several files, like id_rsa.pub etc

My inventory file is down bellow:

[remote_cluster]
node1 ansible_host=192.168.100.100
node2 ansible_host=192.168.100.101
node3 ansible_host=192.168.100.102

What I want to do is to copy the directory from my local machine to remote machine whose hostname is same with the directory name, for example, copy node1 to the remote machine named node1. I don't really want to hard-code this feature in that the amount of remote_cluster nodes is not always three. It may increase or decrease in the future.

I have googled some examples, but nove of them fit my goal. And I have made some attempts,but also without success:

- hosts: remote_cluster
  name: copy local directories to related nodes
  gather_facts: False
  tasks:
  - name: copy task
    ansible.builtin.copy:
      src:  '{{ item.src }}'
      dest: '{{ item.dest }}'
    with_items:
      - { src: 'key/{{hostvar}}/', dest: '~/.ssh/'}
    tags:
      - copy

It seems to me that ansible might be able to identify which remote host is currently executing a task by some variable or something. But I didn't figure out what the name of this magic variable is. To make things clear, I'm temporarily replacing that variable name with hostvar.

Can anyone help? Thanks in advance!


Solution

  • You are taking this the wrong way. Your play already loops on each machine in your group. You don't need a loop here (unless you only want a subset of files inside your source dir).

    The copy module is able to copy an entire tree but will have very poor performance if you have a lot of files. If that's the case, have a look at the syncrhonize module which is better suited for that.

    My feeling is that you are missing a bit of knowledge on internal ansible variables you can use during your play. As a first introduction, I suggest you read the documentation section on magic variables. The one I will use below (as already reported in @JBone comment) is inventory_hostname

    Here is your fixed playbook (from what I understood and untested). Please note the ending / in the src: value and read the corresponding description in the documentation

    If path is a directory, it is copied recursively. In this case, if path ends with "/", only inside contents of that directory are copied to destination. Otherwise, if it does not end with "/", the directory itself with all contents is copied.

    ---
    - hosts: remote_cluster
      name: copy local directories to related nodes
      gather_facts: false
    
      tasks:
        - name: copy task
          ansible.builtin.copy:
            src:  'key/{{ inventory_hostname }}/'
            dest: '~/.ssh/'
          tags:
            - copy