I have a role task which executes a script to install a systemd user (systemctl --user) service. I want to add a when condition to only execute the script when the service is not already installed.
I’m looking for the best solution to do it.
What I’ve tried:
check with service
become: yes
become_user: user
ansible.builtin.service:
name: my_service
check_mode: true
register: service_exist
[...]
when: not (service_exist is defined and service_exist | length > 0)
but it doesn’t work, service_exist is always a dict with a lot of information even when the service doesn’t exist and I don’t clearly see what property is different between an existing service and a non-existing one
check with systemd_service and scope: user
become: yes
become_user: user
ansible.builtin.systemd_service:
name: service
state: started
scope: user
check_mode: true
register: systemd_exist
[...]
when: systemd_exist
but this module fails when the service do not exist
fatal: [debian-12]: FAILED! => {"changed": false, "msg": "Could not find the requested service my_fake_service: host"}
Of course, i could simply test the existence of ~$user/.config/systemd/$service.service file but I would like to do it properly (and not need to retrieve the home directory before testing this)
You could also try using the block/rescue construct, it works like a try/except in Python. Something like:
block:
- become: yes
become_user: user
ansible.builtin.systemd_service:
name: service
state: started
scope: user
check_mode: true
rescue:
# You can use `ansible_failed_result` to parse the error message from the task, no need to `register` (unless you use it elsewhere)
- name: run the script to install the service
# whatever you use for that
@wayt@russoz I find those solutions a little bit ‘hacky’, the idea of try/except doesn’t looks fine for me in such situations where I only want to test a condition and get a true/false result.
It seems that Ansible doesn’t provide a proper solution, but then I prefer to use a less-than-ideal-one (see below)
(edit: not that hacky, because ignore_errors is configurable by task)
@bcoca I think those facts only works with systemd services on system scope, not on user one.
I think the best (in my case) solutions are:
verify the existence of the service systemd definition file, like ~/.config/systemd/$service.service
verify the real execution of the service with something a ps | grep with become_user. Not sure if I need to use ansible.builtin.shell or ansible.builtin.command but I’ll look and try
Hi @daks you’re absolutely right, and as you pointed out that service_facts does not handle “user” services, I am thinking of taking a look at the code and see if we can add it. Would be willing to do the honours and submit the contribution yourself? I 'd be more than happy to help.