2

I have a role that is imported as a dependency by multiple other roles that results in them all needing to append to the same line or create that line if it doesn't exist yet (i.e. the first role creates the line and all subsequent roles append to it).

Specifically the line eventually looks like

post-hook = systemctl restart <service1> <service2> ... <serviceN>

where <service1> ... <serviceN> are the names of services to be restarted.

The process is something like

  • Initially the line doesn't exist
  • When the first role is processed it looks like post-hook = systemctl restart apache2
  • When the second role is processed it looks like post-hook = systemctl restart apache2 postfix
  • Repeat for each additional role.

I know I can initially add the line using the lineinfile module, but the line is then replaced every time another role is processed leaving only the latest service in the list.

E.g.

- name: 'Update service when new certificate installed'
  become: true
  lineinfile:
    path: '/etc/letsencrypt/cli.ini'
    regex: 'post-hook = systemctl restart*'
    line: 'post-hook = systemctl restart {{ service }}'
    state: 'present'

I can append to the already existing line using regex's, backrefs and negative lookaheads, but this won't create the line initially because when backrefs are used if the regex does not match, the file will be left unchanged.

E.g.

- name: 'Update service when new certificate installed'
  become: true
  lineinfile:
    path: '/etc/letsencrypt/cli.ini'
    backrefs: true
    regex: '^(post-hook = systemctl restart(?!.*\b{{ service }}\b).*)$'
    line: '\1 {{ service }}'
    state: 'present'

There are obviously several ways to do this if I hard code the list of services I want to restart, but I'm really hoping to find a way that allows me to add new roles without having to edit the depended upon role.

Hugh Powell
  • 317
  • 2
  • 11

1 Answers1

1

I would do it a little bit different. Every role just puts a line into a new file, like:

- name: 'Add service'
  become: true
  lineinfile:
    path: '/etc/letsencrypt/.restart.list'
    regex: "^{{ service }}"
    line: "{{ service }}"
    create: true

Of course, then there a multiple line.

I asume, you have a different role or task, where letsencrypt after all is called. And at that situation it is possible, your slurp or cat all lines into a var and make a single lineinfile task with that list, like

- name: "Read restat list"
  command: "cat /etc/letsencrypt/.restart.list"
  changed_when: false
  register: restartList

- name: 'Update service when new certificate installed'
  become: true
  lineinfile:
    path: '/etc/letsencrypt/cli.ini'
    backrefs: true
    regex: '^post-hook = systemctl restart'
    line: 'post-hook = systemctl restart {{ restartList.stdout_lines | join(" ") }}'
    state: 'present'

It's not nice, but maybe easier to read then the regex, backref example

Hugh Powell
  • 317
  • 2
  • 11
TRW
  • 876
  • 7
  • 23