shibumi / ansible-systemd-conf

Ansible role to setup systemd configs, networkd, timers and more
Other
2 stars 5 forks source link

Use variables for systemd_conf_service + systemd_conf_timer #2

Open jkirk opened 2 years ago

jkirk commented 2 years ago

I'd like to name systemd-timer and service via a variable: I have an ansible role restic_backup_generic which depends on shibumi.systemd-conf and we set restic_backup_generic_backup_name as the backup job name. This is what we tried in restic_backup_generic/meta/main.yml:

---
dependencies:
  - role: shibumi.systemd-conf
    systemd_conf_service:
      "restic-backup-{{ restic_backup_generic_backup_name }}":
        - Unit:
          - Description: "Generic restic backup {{ restic_backup_generic_backup_name }}"
        - Service:
          - Type: "oneshot"
          - ExecStart: "/usr/local/sbin/restic-backup-{{ restic_backup_generic_backup_name }}"
    systemd_conf_timer:
      "restic-backup-{{ restic_backup_generic_backup_name }}":
        - Unit:
          - Description: "Daily generic restic backup {{ restic_backup_generic_backup_name }}"
        - Timer:
          - OnCalendar: "*-*-* 21:00"
          - Persistent: "True"
        - Install:
          - WantedBy: "timers.target"

My playbook.yml looks something like this:

---
- hosts: hostname.example.com
  become: yes
  roles:
    - role: restic_backup_generic
      restic_backup_generic_backup_name: samba-data
      restic_backup_generic_backup_path:
        - "/srv/samba/data01"

Unfortunately the systemd service and timer are literally called restic-backup-{{ restic_backup_generic_backup_name }}.*. The variable does not get expanded. Any idea how to solve this?

Thx for your help and support this role!

shibumi commented 2 years ago

Hi, I think this won't work that way, because the template injection happens only once:

https://github.com/shibumi/ansible-systemd-conf/blob/d14355e02655e964c7527b4aa5aeb35c27ccdc5a/templates/systemd_conf.j2#L9L12

To be honest, I have no idea how to implement your desired functionality. If you have an idea, a PR is welcome :)

jkirk commented 2 years ago

It took me a while to get back into this. But after reviewing this, I think the problem seems to be {{ item.key }} in here: https://github.com/shibumi/ansible-systemd-conf/blob/d14355e02655e964c7527b4aa5aeb35c27ccdc5a/tasks/main.yml#L47-L52

So in my case "restic-backup-{{ restic_backup_generic_backup_name }}" "just" needs to be expanded (via dict2items) but this does not seem to happen.

I tried to adapt my meta/main.yml like this:

  - role: shibumi.systemd-conf
    systemd_conf_service: 
      name: "restic-backup-{{ restic_backup_generic_backup_name }}"
        - Unit:
          - Description: "Generic restic backup {{ restic_backup_generic_backup_name }}"
        - Service:
          - Type: "oneshot"
          - ExecStart: "/usr/local/sbin/restic-backup-{{ restic_backup_generic_backup_name }}"

and your code like this:

- name: copy .service profiles
  template:
    src: "systemd_conf.j2"
    dest: "/etc/systemd/system/{{ item.key.value }}.service"
    mode: 0644

But obviously I do not know what I am doing and this fails with this error:

ERROR! We were unable to read either as JSON nor YAML, these are the errors we got from each:
JSON: Expecting value: line 1 column 1 (char 0)

Syntax Error while loading YAML.
  did not find expected key

The error appears to be in '/home/jkirk/projects/synpro/pmt-ansible/roles/restic_backup_generic/meta/main.yml': line 7, column 9, but may
be elsewhere in the file depending on the exact syntax problem.                

The offending line appears to be:

      name: "restic-backup-{{ restic_backup_generic_backup_name }}"
        - Unit:          
        ^ here

I will keep looking but if you can help or give some advice with this I would be very grateful! Thx!

jkirk commented 2 years ago

I completely forgot to update this issue with my findings.

I (think I) got it working by introducing (optional) *_name variables. E.g. restic_backup_generic/meta/main.yml:

---
dependencies:
  - role: shibumi.systemd-conf
    systemd_conf_service_name: "restic-backup-{{ restic_backup_generic_backup_name }}"
    systemd_conf_service:
      restic-backup-generic:
        - Unit:
          - Description: "Generic restic backup {{ restic_backup_generic_backup_name }}"
        - Service:
          - Type: "oneshot"
          - ExecStart: "/usr/local/sbin/restic-backup-{{ restic_backup_generic_backup_name }}"
    systemd_conf_timer_name: "restic-backup-{{ restic_backup_generic_backup_name }}"
    systemd_conf_timer:
      restic-backup-generic:
        - Unit:
          - Description: "Daily generic restic backup {{ restic_backup_generic_backup_name }}"
        - Timer:
          - OnCalendar: "*-*-* 21:00"
          - Persistent: "True"
        - Install:
          - WantedBy: "timers.target"

And my playbook.yml:

---
- hosts: hostname.example.com
  become: yes
  roles:
    - role: restic_backup_generic
      restic_backup_generic_backup_name: samba-data
      restic_backup_generic_backup_path:
        - "/srv/samba/data01"

tasks/main.yml was updated like this:

- name: copy .service profiles
  template:
    src: "systemd_conf.j2"
    dest: "/etc/systemd/system/{{ systemd_conf_service_name|default(item.key) }}.service"
    mode: 0644
  loop: "{{ systemd_conf_service | dict2items }}"
  notify:
    - daemon-reload

- name: copy .timer profiles
  template:    
    src: "systemd_conf.j2"
    dest: "/etc/systemd/system/{{ systemd_conf_timer_name|default(item.key) }}.timer"
    mode: 0644 
  loop: "{{ systemd_conf_timer | dict2items }}"
  notify:      
    - daemon-reload

Setting the _name variable is optional (so item.key can still be used) but makes it possible to set the name by an external variable. item.key is not used in that case and can have any name.

I replaced with_dict with loop, because it is "recommend it for most use cases", see: https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html Ansible 2.5 (or later) is needed though, so min_ansible_version needs to be set to '2.5' in meta/main.yml.

What do you think? Would you accept a PR which implements this feature? If yes, I would implement an optional _name variable for all profiles and would hand it over to you for review.

(I accidentally hit Alt-Enter and published the unfinished comment a few moments before. I deleted it afterwards, so please do not be confused, if this comment looks different than the mail notification you have received.)

Thx!