Ansible.builtin.copy not doing what I expect, what am I doing wrong?

I have tried to configure a simple task to:-
1/ install postfix
2/ save a copy of the default configuration file as ‘asinstalled’
3/ download a preconfigured configuration file from our configuration server.

what I am seeing is the downloaded configuration file is being saved as the asinstalled, and the original configuration file is remaining untouched, i.e remains as postfix/main.cf.

ansible version installed is: ansible-7.7.0-1.el9.noarch

I have tried splitting the stanzas into separate playbooks, but the end result is the same whatever.

I have separate sections for RedHat/Ubuntu as we use a monolithic Linux playbook.

Here are the postfix install/confugre sections of my playbooks:-

   - name: Install the latest version of postfix on RedHat
     ansible.builtin.yum:
       name: postfix
       state: latest
     when: ansible_distribution == 'RedHat'

   - name: Install the latest version of postfix on Ubuntu
     ansible.builtin.apt:
       name: postfix
       state: latest
     when: ansible_distribution == 'Ubuntu'


   - name: ansible copy main.cf to asinstalled RedHat
     ansible.builtin.copy:
       src: /etc/postfix/main.cf
       dest: /etc/postfix/main.cf.asinstalled
       force: false
     when: ansible_distribution == 'RedHat'

   - name: ansible copy main.cf.debian to postfix Ubuntu
     ansible.builtin.copy:
       src: /usr/share/postfix/main.cf.debian
       dest: /etc/postfix/main.cf.asinstalled
       force: false
       remote_src: true
     when: ansible_distribution == 'Ubuntu'

   - name: ansible copy master.cf to asinstalled
     ansible.builtin.copy:
       src: /etc/postfix/master.cf
       dest: /etc/postfix/master.cf.asinstalled
       force: false


   - name: Download main.cf RedHat
     ansible.builtin.get_url:
       url: http://servername.domain/ks/etc/postfix/main.cf.redhat8
       dest: /etc/postfix/main.cf
       validate_certs: false
     when: ansible_distribution == 'RedHat'

   - name: Download main.cf Ubuntu
     ansible.builtin.get_url:
       url: http://servername.domain/ks/etc/postfix/main.cf.ubuntu22
       dest: /etc/postfix/main.cf
       validate_certs: false
     when: ansible_distribution == 'Ubuntu'

where am I going wrong ?

thanks in advance…

Copies of files on the remote system need to have remote_src: true, otherwise ansible.builtin.copy assumes the source file is on the Ansible controller.

4 Likes

thanks, Kevin, that’s got me further, the main.cf.asinstalled is now being created as desired.

however the file copy from configuration server now isn’t working, the task reports ‘ok:’ but isn’t downloading.

I don’t see any ‘configuration server’ in the snippet you pasted; do you mean the Ansible controller (where the playbook is being executed)?

From what it looks like you’re trying to do, you want to backup the original config files “as installed” by the postfix package. Then you want to download your own config file from a server and use that instead.

If that’s the case, you appear to have some typos in some of your sources. Not to mention that you would overwrite the originally installed main.cf.asinstalled file with your modified main.cf on subsequent runs.

That said, I would try this more agnostic approach:

# Use 'state: latest' for patching playbooks
# Use 'state: present' for configuration playbooks
  - name: Install the postfix
    ansible.builtin.package: # use this when package names are the same across distros
      name: postfix
      state: present

   - name: Backup original main.cf
     ansible.builtin.command:
       cmd: cp  /etc/postfix/main.cf /etc/postfix/main.cf.asinstalled
       # cmd: cp  /etc/postfix/main.cf /etc/postfix/main.cf.orig # < this is my preference for backing up original config files
       creates: /etc/postfix/main.cf.asinstalled # only do this if the backup doesn't exist

# Use ansible vars in the url to dynamically grab the right file for the OS
# Enforcing permissions on modified files is also good practice
   - name: Download main.cf
     ansible.builtin.get_url:
       url: "http://servername.domain/ks/etc/postfix/main.cf.{{ ansible_distribution | lower }}{{ ansible_distribution_major_version }}"
       dest: /etc/postfix/main.cf
       validate_certs: false
       mode: "644"
       owner: root
       group: root

Similarly, you could also use a jinja2 template file of main.cf and make it work for both RedHat/Ubuntu hosts, and copy that from your control node instead of downloading it from a server.

3 Likes

That would indicate the dest: already contains the correct content. You’ll have to provide more information to convince me otherwise. I’m easily swayed, though.:slight_smile:

3 Likes

Kevin - the configuration server is denoted by ‘servername.domain’ in my code sample.

Denney-tech - great, I have confirmed your code does exactly what I want, beautiful/aspirational bit of coding, nice one, Thanks.

Todd, thanks, I over assumed there would be some file comparison going on, but looks like it is satisfied with a not exist only.

1 Like

weird the ‘ansible.builtin.get_url’ downloaded the file to .asinstalled though, definitely not desired state on that.
maybe a bug, but as my code was wrong in the first place, probs not worth flagging it

I don’t think that get_url: was saving to .asinstalled, it would be copy: rewriting it on subsequent runs.

Edit: you also had a copy step that is specifically copying the .debian file over .asinstalled, so there’s that too.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.