2

Trying to only copy an Nginx config file if the destination file does not have a string in it.

I thought this would work:

- name: Copy nginx config file
  template:
    src: templates/nginx.conf
    dest: /etc/nginx/sites-enabled/default
    validate: grep -l 'managed by Certbot' %s

But this task fails if "managed by Certbot" isn't in the file and stops the playbook run.

How can I just skip the template copy if the destination file already has that pattern? Maybe there's a better way to get the same result?

Zeitounator
  • 38,476
  • 7
  • 53
  • 66
croceldon
  • 4,511
  • 11
  • 57
  • 92

2 Answers2

4

Inspired from this other answer

You can check for the presence of a content in a file using the lineinfile module in check mode. Then you can use the result as a condition to your template task. The default in the condition is to cope with the case when the file does not exists and the found attribute is not in the registered result.

---
- name: Check for presence of "managed by Certbot" in file
  lineinfile:
    path: /etc/nginx/sites-enabled/default
    regexp: ".*# managed by Certbot.*"
    state: absent
  check_mode: yes
  changed_when: false
  register: certbot_managed

- name: Copy nginx config file when not certbot managed
  template:
    src: templates/nginx.conf
    dest: /etc/nginx/sites-enabled/default
  when: certbot_managed.found | default(0) == 0
croceldon
  • 4,511
  • 11
  • 57
  • 92
Zeitounator
  • 38,476
  • 7
  • 53
  • 66
0

You could use the failed_when condition and base it on the fail message that validate generate — failed to validate — to act upon:

- name: Copy nginx config file
  template:
    src: templates/nginx.conf
    dest: /etc/nginx/sites-enabled/default
    validate: grep -l 'managed by Certbot' %s
  failed_when: 
    - copy_config_file.failed
    - copy_config_file.msg != 'failed to validate'
  register: copy_config_file

Note: in when and *_when, having a list of conditions is like doing list.0 and list.1 and ...


Given the playbook:

- hosts: all
  gather_facts: no

  tasks:
    - copy:
        dest: templates/nginx.conf
        content: "{{ content | default('some random content') }}"

    - copy:
        dest: /etc/nginx/sites-enabled/default
        content: "blank"

    - template:
        src: templates/nginx.conf
        dest: /etc/nginx/sites-enabled/default
        validate: grep -l 'managed by Certbot' %s
      failed_when: 
        - copy_config_file.failed
        - copy_config_file.msg != 'failed to validate'
      register: copy_config_file

    - shell: cat templates/nginx.conf
      register: template_content
      failed_when: false

    - shell: cat /etc/nginx/sites-enabled/default
      register: file_content
      failed_when: false

    - debug:
        var: template_content.stdout
    
    - debug:
        var: file_content.stdout
  1. When run via:
    ansible-playbook play.yml
    
    It gives:
    PLAY [all] *******************************************************************************************************
    
    TASK [copy] ******************************************************************************************************
    changed: [localhost]
    
    TASK [copy] ******************************************************************************************************
    changed: [localhost]
    
    TASK [template] **************************************************************************************************
    ok: [localhost]
    
    TASK [shell] *****************************************************************************************************
    changed: [localhost]
    
    TASK [shell] *****************************************************************************************************
    changed: [localhost]
    
    TASK [debug] *****************************************************************************************************
    ok: [localhost] => {
        "template_content.stdout": "some random content"
    }
    
    TASK [debug] *****************************************************************************************************
    ok: [localhost] => {
        "file_content.stdout": "blank"
    }
    
    PLAY RECAP *******************************************************************************************************
    localhost                  : ok=7    changed=4    unreachable=0    failed=0     skipped=0    rescued=0    ignored=0   
    
  2. Now, when run with
    ansible-playbook play.yml -e "content='managed by Certbot\nsome other content'"
    
    With an extra parameter to modify the content of the template, it gives:
    PLAY [all] *******************************************************************************************************
    
    TASK [copy] ******************************************************************************************************
    ok: [localhost]
    
    TASK [copy] ******************************************************************************************************
    changed: [localhost]
    
    TASK [template] **************************************************************************************************
    changed: [localhost]
    
    TASK [shell] *****************************************************************************************************
    changed: [localhost]
    
    TASK [shell] *****************************************************************************************************
    changed: [localhost]
    
    TASK [debug] *****************************************************************************************************
    ok: [localhost] => {
        "template_content.stdout": "managed by Certbot\nsome other content"
    }
    
    TASK [debug] *****************************************************************************************************
    ok: [localhost] => {
        "file_content.stdout": "managed by Certbot\nsome other content"
    }
    
    PLAY RECAP *******************************************************************************************************
    localhost                  : ok=7    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    
β.εηοιτ.βε
  • 33,893
  • 13
  • 69
  • 83