Home > other >  Can I copy text from remote to local with Ansible playbook?
Can I copy text from remote to local with Ansible playbook?

Time:12-14

I know the Ansible fetch-module can copy a file from remote to local, but what if I only need the contents (in my case a tmp file holding the ip address) appended into a local file?

Fetch module does this:

- name: Store file into /tmp/fetched/
  ansible.builtin.fetch:
    src: /tmp/somefile
    dest: /tmp/fetched

I need it to do something like this:

- name: Store file into /tmp/fetched/
  ansible.builtin.fetch:
    src: /tmp/somefile.txt
    dest: cat src >> /tmp/fetched.txt

CodePudding user response:

In a nutshell:

- name: Get remote file content
  ansible.builtin.slurp:
    src: /tmp/somefile.txt
  register: somefile

- name: Append remote file content to a local file
  vars:
    target_file: /tmp/fetched.txt
  ansible.builtin.copy:
    content: |-
      {{ lookup('file', target_file) }}
      {{ somefile.content | b64decode }}
    dest: "{{ target_file }}"
  # Fix write concurrency when running on multiple targets
  throttle: 1
  delegate_to: localhost

Notes:

  • the second task isn't idempotent (will modify the file on each run even with the same content to append)
  • this will work for small target files. If that file becomes huge and you experience high execution times / memory consumptions, you might want to switch to shell for the second task:
- name: Append remote file content to a local file
  ansible.builtin.shell:
    cmd: echo "{{ somefile.content | b64decode }}" > /tmp/fetched
  # You might still want to avoid concurrency with multiple targets
  throttle: 1
  delegate_to: localhost

Alternatively, you could write all contents from all fetched files from all your targets in one go to avoid the concurrency problem and gain some time.

# Copy solution
- name: Append remote files contents to a local file
  vars:
    target_file: /tmp/fetched.txt
    fetched_content: "{{ ansible_play_hosts
      | map('extract', hostvars, 'somefile.content') 
      | map('b64decode')
      | join('\n') }}"
  ansible.builtin.copy:
    content: |-
      {{ lookup('file', target_file) }}
      {{ fetched_content }}
    dest: "{{ target_file }}"
  delegate_to: localhost
  run_once: true

# Shell solution
- name: Append remote files contents to a local file
  vars:
    fetched_content: "{{ ansible_play_hosts
      | map('extract', hostvars, 'somefile.content') 
      | map('b64decode')
      | join('\n') }}"
  ansible.builtin.shell:
    cmd: echo "{{ fetched_content }}" > /tmp/fetched
  delegate_to: localhost
  run_once: true
  • Related