From 1f7091a11cfdcad885443c23e00d8ab85b0783a6 Mon Sep 17 00:00:00 2001 From: Dmitriy Rabotyagov Date: Wed, 3 Nov 2021 18:19:22 +0200 Subject: [PATCH] Add ability to create templated services This functionality is pretty neat and used widely if you need to pass specific argument to the unit service, but rest of the parameters can be left intact. Change-Id: I6eb80ac0f9f0257402697a255518bb2c66d0dfd5 --- defaults/main.yml | 12 ++++++ handlers/main.yml | 16 ++++---- handlers/systemd_restart.yml | 22 +++++++++++ .../templated_service-f31e4515c2fd75ab.yaml | 7 ++++ tasks/main.yml | 23 ++--------- tasks/systemd_load.yml | 39 +++++++++++++++++++ tests/test.yml | 9 +++++ 7 files changed, 101 insertions(+), 27 deletions(-) create mode 100644 handlers/systemd_restart.yml create mode 100644 releasenotes/notes/templated_service-f31e4515c2fd75ab.yaml create mode 100644 tasks/systemd_load.yml diff --git a/defaults/main.yml b/defaults/main.yml index 7c9669c..8c2fc3a 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -114,6 +114,10 @@ systemd_environment: {} # `environment` -- (optional) set additional environment settings, this option is a hash of strings. # `environment_file` -- (optional) set additional environment settings through a given file. this option is a string. # `dynamic_user` -- (optional) Dynamically set a UNIX user and group when the unit is started; only works if systemd >= 235. +# `template_arguments` -- (optional) List of arguments that would be enabled/started in case service is a template. +# For that to work properly, service_name should end with `@`, ie `dhcpcd@` +# Systemd service template documentation can be found by the link: +# https://www.freedesktop.org/software/systemd/man/systemd.service.html#Service%20Templates # `state_directory` -- (optional) Relative path the state directory; only works if systemd >= 235. # `systemd_overrides` -- (optional) Dictionary that may contain custom structure in config_overrides format that # will be used to generate systemd overrides in /etc/systemd/system/service_name.service.d/overrides.conf @@ -238,4 +242,12 @@ systemd_environment: {} # - ServiceZ # - ServiceY # restart_changed: no +# +# Example below will result in creating 2 templated services: Templated@arg1 and Templated@arg2 +# - service_name: Templated@ +# execstarts: +# - /tmp/script %i +# template_arguments: +# - arg1 +# - arg2 systemd_services: [] diff --git a/handlers/main.yml b/handlers/main.yml index 495b029..d66d2f0 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -14,15 +14,15 @@ # limitations under the License. - name: Restart changed services - systemd: - name: "{{ item.item.service_name | replace(' ', '_') }}.{{ (item.item.timer is defined) | ternary('timer', 'service') }}" - state: restarted + include_tasks: handlers/systemd_restart.yml listen: systemd service changed - with_items: "{{ systemd_services_result.results }}" when: - - 'item.item.restart_changed | default(systemd_service_restart_changed) | bool' - - 'item.item.state is not defined' - - 'item.item.enabled | default(systemd_service_enabled) | bool' - - 'item is changed' + - 'services_results.item.restart_changed | default(systemd_service_restart_changed) | bool' + - 'services_results.item.state is not defined' + - 'services_results.item.enabled | default(systemd_service_enabled) | bool' + - 'services_results is changed' + loop: "{{ systemd_services_result.results }}" + loop_control: + loop_var: services_results tags: - systemd-service diff --git a/handlers/systemd_restart.yml b/handlers/systemd_restart.yml new file mode 100644 index 0000000..05f38f6 --- /dev/null +++ b/handlers/systemd_restart.yml @@ -0,0 +1,22 @@ +--- +# Copyright 2021, City Network International AB. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +- name: "Restart service {{ services_results.item.service_name | replace(' ', '_') }}" + systemd: + name: "{{ services_results.item.service_name | replace(' ', '_') }}{{ template_argument }}.{{ (services_results.item.timer is defined) | ternary('timer', 'service') }}" + state: restarted + loop: "{{ services_results.item.template_arguments | default(['']) }}" + loop_control: + loop_var: template_argument diff --git a/releasenotes/notes/templated_service-f31e4515c2fd75ab.yaml b/releasenotes/notes/templated_service-f31e4515c2fd75ab.yaml new file mode 100644 index 0000000..f021bb4 --- /dev/null +++ b/releasenotes/notes/templated_service-f31e4515c2fd75ab.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + Allow to create `templated services `_ + Now for systemd_services you are allowed to provide template_arguments, + which can contain a list of arguments with which templated services + would be created. diff --git a/tasks/main.yml b/tasks/main.yml index b4f2070..62080cb 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -140,25 +140,10 @@ when: - (systemd_services_result is changed) or (systemd_timer_result is changed) or ('true' in systemd_socket.results | map(attribute='changed') | list ) -- name: Load service - systemd: - name: "{{ item.service_name | replace(' ', '_') }}.service" - enabled: "{{ item.enabled | default(systemd_service_enabled) }}" - state: "{{ (item.timer is defined) | ternary(omit, (item.state | default(omit))) }}" - with_items: "{{ systemd_services }}" - when: - - item.load | default(True) - tags: - - systemd-service - -- name: Load timer - systemd: - name: "{{ item.service_name | replace(' ', '_') }}.timer" - enabled: "{{ item.enabled | default(systemd_service_enabled) }}" - state: "{{ item.timer.state | default(omit) }}" - when: - - item.timer is defined - with_items: "{{ systemd_services }}" +- include_tasks: systemd_load.yml + loop: "{{ systemd_services }}" + loop_control: + loop_var: service tags: - systemd-service diff --git a/tasks/systemd_load.yml b/tasks/systemd_load.yml new file mode 100644 index 0000000..be80558 --- /dev/null +++ b/tasks/systemd_load.yml @@ -0,0 +1,39 @@ +--- +# Copyright 2021, City Network International AB. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# NOTE(noonedeadpunk): If we don't have template_arguments set, we just iterate over list with +# empty string as element. This won't have any effect on the results, but +# we reduce code duplication +- name: "Load service {{ service.service_name | replace(' ', '_') }}" + systemd: + name: "{{ service.service_name | replace(' ', '_') }}{{ template_argument }}.service" + enabled: "{{ service.enabled | default(systemd_service_enabled) }}" + state: "{{ (service.timer is defined) | ternary(omit, (service.state | default(omit))) }}" + when: + - service.load | default(True) + loop: "{{ service.template_arguments | default(['']) }}" + loop_control: + loop_var: template_argument + +- name: "Load timer {{ service.service_name | replace(' ', '_') }}" + systemd: + name: "{{ service.service_name | replace(' ', '_') }}{{ template_argument }}.timer" + enabled: "{{ service.enabled | default(systemd_service_enabled) }}" + state: "{{ service.timer.state | default(omit) }}" + when: + - service.timer is defined + with_items: "{{ service.template_arguments | default(['']) }}" + loop_control: + loop_var: template_argument diff --git a/tests/test.yml b/tests/test.yml index a391ca1..b597e8d 100644 --- a/tests/test.yml +++ b/tests/test.yml @@ -64,6 +64,15 @@ state: "started" cron_minute: 30 cron_hour: 1 + - service_name: "test_templated_service@" + service_type: oneshot + execstarts: + - "/bin/bash -c 'echo %i'" + template_arguments: + - 1 + - 2 + enabled: yes + state: started post_tasks: - name: Check Services