Ansible copying content from one remote system to another

Just a quick tip of you’re trying to do the same thing I was trying to do.

The Problem

I am generating some content on Server A. I want to replicate this content onto Servers B and C.

The Solution

TL;DR: Read files content from Server A. Write files on Servers B and C from those contents.

Ansible provides a couple modules that make this possible. The first one we’ll look at is the slurp module. This module allows you to read in contents of a file from a remote system. Here is an task to read the content, utilizing the run_once mechanism:

This will read each of those files in and save the results in the pki_certs variable. Ansible will only do this once, presumably on the host where this content was generated with a previous run_once task. However the variable data will be assigned to every host to make it easily accessible.

Next we need to write out the content on our other systems. There are a couple things to consider. First, because the files were read via a with_items loop, the registered content is in a list, specifically in pki_certs.results. This is easy enough to deal with because the results list is a list of dictionaries, and the name of the file is part of that dictionary. The filename resides in the item key, while the content resides in the content key. This allows us to template out both the path to be written as well as the content to be written at that path.

The next thing we need to consider is that the slurp module stores content in base 64 encoding. That means when we write it back out, we need to decode it from base 64, otherwise Ansible will happily write out some long strings that look nothing like your file. To decode from base 64, simply use the b64decode filter on the content variable.

The last thing to consider has to do with yaml and whitespace and ansible. This may not come into play with every file, but these files have multiple lines. A somewhat recent change in Ansible means that if the “short form” of task description is used (with key=value parameters) your written out file will have double linefeeds. The simple solution is to use “long form” task syntax as you’ll see below:

Because every host has access to the pki_certs variable this task can run across all of them. You might see a change registered for the first host in the loop, even though it was the source of the content, due to permissions or ownership changes, however subsequent runs will be nice and clean.

Hopefully this helps you out and saves you from spending an afternoon poking around at it like I just did!

7 thoughts on “Ansible copying content from one remote system to another”

  1. Can you please share fill playbook with hostnames.
    I am having some difficulty while registered variable(remote_files), can you help me to resolve this issue.
    Following is my play book:

    – hosts: host1
    user: root
    sudo: no
    gather_facts: False

    – name: Remote Read
    slurp: src={{ item }}
    – /root/z
    register: remote_files
    run_once: true

    – hosts: host2
    user: root
    sudo: no
    gather_facts: False

    – name: Remote Write
    dest: “{{ item.item }}”
    content: “{{ itme.content | b64decode }}”
    owner: root
    group: root
    mode: 700
    with_items: remote_files.results

    TASK: [Remote Write] **********************************************************
    fatal: [host2] => One or more undefined variables: ‘unicode object’ has no attribute ‘item’

    FATAL: all hosts have already failed — aborting

  2. just tried this. had to reference the source host for the destination host to see it. for example,

    – name: get the file
    slurp: src=/etc/issue
    register: issue
    when: inventory_hostname == “node1”
    – name: put the file
    dest: /root/issue
    content: “{{ hostvars.node1.issue.content | b64decode }}”
    when: inventory_hostname == “node2”

Leave a Reply