Add tests to the service role

* Document the optionality in the defaults
* validate the input in the tasks before it's templated
* Standardize on the exec(starts,stops,reloads} interface
* Update the readme
* Add functional test

Change-Id: Icae36f970178b1cc79d069a94321afb1732a8c5c
Signed-off-by: Kevin Carter <kevin.carter@rackspace.com>
This commit is contained in:
Kevin Carter 2018-03-21 12:39:38 -05:00
parent 134c6f7f24
commit 7745439f35
No known key found for this signature in database
GPG Key ID: 9443251A787B9FB3
10 changed files with 228 additions and 172 deletions

View File

@ -18,84 +18,6 @@ You can also use the ``ansible-galaxy`` command on the ``ansible-role-requiremen
----
###### Defaults (See actual role for more details)
``` yaml
# This is the default path for a given service. Set this for general service lookups or
# define "program_override" option in the systemd_services dictionary.
systemd_bin_path: /usr/local/bin
systemd_user_name: root
systemd_group_name: root
systemd_slice_name: system
systemd_lock_path: /var/lock
# This is the prefix used for all temp files of a given type.
systemd_tempd_prefix: tempd
# Give a reasonable amount of time for the server to start up/shut down
systemd_TimeoutSec: 120
systemd_Restart: on-failure
systemd_RestartSec: 2
# Accounting options
systemd_CPUAccounting: true
systemd_BlockIOAccounting: true
systemd_MemoryAccounting: true
systemd_TasksAccounting: true
# Sandboxing options
systemd_PrivateTmp: true
systemd_PrivateDevices: false
systemd_PrivateNetwork: true
systemd_PrivateUsers: true
# Start service after a given target. This is here because we want to define common
# after targets used on most services. This can be overridden or agumented using
# the "systemd_services" dictionary option "init_config_overrides".
systemd_after_targets:
- syslog.target
- network.target
# Set the service enabled state. Valid options are: [yes, no]
systemd_service_enabled: yes
# Set global service overrides used within the service unit file.
systemd_service_config_overrides: {}
# The systemd services dictionary is a set of services that will be created. The dictionary
# can contain the following options:
# `service_name` -- (required) used to define the name of the service. This is typically the name of the executable.
# `init_config_overrides` -- (optional) This allows any section or key=value pair to be set within the systemd unit file.
# `program_config_options` -- (optional) Provides the ability to pass in flags to a given service for execution.
# `program_override` -- (optional) sets the full path to the executable that will be run by the service file.
# `enabled` -- (optional) Set the enabled state of the service.
# `state` -- (optional) Set the running state of the service.
# Examples:
# systemd_services:
# ServiceW:
# service_name: ServiceW
# init_config_overrides: {} # This is used to add in arbitratry unit file options
# ServiceX:
# service_name: ServiceX
# init_config_overrides: {} # This is used to add in arbitratry unit file options
# program_config_options: '--flag1 things --flag2 other'
# ServiceY:
# service_name: ServiceY
# init_config_overrides: {} # This is used to add in arbitratry unit file options
# program_override: '/usr/bin/ServiceY'
# ServiceZ:
# service_name: ServiceZ
# init_config_overrides: {} # This is used to add in arbitratry unit file options
# enabled: no
# state: stopped
systemd_services: {}
```
----
###### Example playbook
``` yaml
@ -105,9 +27,9 @@ systemd_services: {}
roles:
- role: "systemd_service"
systemd_services:
service_name: ServiceX
init_config_overrides: {}
program_config_options: '--flag1 things --flag2 other'
- service_name: ServiceX
execstarts:
- /path/ServiceX --flag1
tags:
- servicex-init

View File

@ -13,14 +13,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# This is the default path for a given service. Set this for general service lookups or
# define "program_override" option in the systemd_services dictionary.
systemd_bin_path: /usr/local/bin
systemd_user_name: root
systemd_group_name: root
systemd_slice_name: system
systemd_lock_path: /var/lock
# This is the prefix used for all temp files of a given type.
systemd_tempd_prefix: tempd
@ -44,7 +39,7 @@ systemd_PrivateUsers: true
# Start service after a given target. This is here because we want to define common
# after targets used on most services. This can be overridden or agumented using
# the "systemd_services" dictionary option "init_config_overrides".
# the "systemd_services" dictionary option "config_overrides".
systemd_after_targets:
- syslog.target
- network.target
@ -62,41 +57,48 @@ systemd_default_service_type: simple
# The systemd services dictionary is a set of services that will be created. The dictionary
# can contain the following options:
# `service_name` -- (required) used to define the name of the service. This is typically the name of the executable.
# `init_config_overrides` -- (optional) This allows any section or key=value pair to be set within the systemd unit file.
# `program_config_options` -- (optional) Provides the ability to pass in flags to a given service for execution.
# `program_override` -- (optional) sets the full path to the executable that will be run by the service file.
# `service_type` -- (optional) Set the service type, default is "simple".
# `execstarts` -- (required) Set the program to start, when the service is simple the list has a max length of 1.
# `execstops` -- (optional) Set the program to stop, when the service is simple the list has a max length of 1.
# `config_overrides` -- (optional) This allows any section or key=value pair to be set within the systemd unit file.
# `program_sandboxing` -- (optional) Case sensitive Key=Value pairs for service Sandboxing
# `program_accounting` -- (optional) Case sensitive Key=Value pairs for service Accounting
# `enabled` -- (optional) Set the enabled state of the service.
# `state` -- (optional) Set the running state of the service.
# Examples:
# systemd_services:
# ServiceW:
# service_name: ServiceW
# init_config_overrides: {} # This is used to add in arbitratry unit file options
# ServiceX:
# service_name: ServiceX
# init_config_overrides: {} # This is used to add in arbitratry unit file options
# program_config_options: '--flag1 things --flag2 other'
# - service_name: ServiceW
# config_overrides: {} # This is used to add in arbitratry unit file options
# execstarts:
# - ServiceW
#
# - service_name: ServiceX
# config_overrides: {} # This is used to add in arbitratry unit file options
# execstarts:
# - ServiceX
# program_sandboxing:
# PrivateTmp: true
# program_accounting:
# CPUAccounting: true
# ServiceY:
# service_name: ServiceY
# init_config_overrides: {} # This is used to add in arbitratry unit file options
# program_override: '/usr/bin/ServiceY'
# program_stop: '/usr/bin/stopcmd'
# ServiceZ:
# service_name: ServiceZ
# init_config_overrides: {} # This is used to add in arbitratry unit file options
#
# - service_name: ServiceY
# config_overrides: {} # This is used to add in arbitratry unit file options
# execstarts:
# - '/usr/bin/ServiceY'
# execstarts:
# - '/usr/bin/stopcmd'
#
# - service_name: ServiceZ
# config_overrides: {} # This is used to add in arbitratry unit file options
# enabled: no
# state: stopped
# service_type: oneshot
# program_execstarts:
# execstarts:
# - /usr/bin/startcmd1
# - /usr/bin/startcmd2
# program_execstops
# execstops
# - /usr/bin/stopcmd1
# - /usr/bin/stopcmd2
systemd_services: {}
systemd_services: []

View File

@ -6,8 +6,5 @@
roles:
- role: "systemd_service"
systemd_services:
service_name: ServiceX
init_config_overrides: {}
program_config_options: '--flag1 things --flag2 other'
tags:
- servicex-init
- service_name: ServiceX
config_overrides: {}

View File

@ -253,7 +253,7 @@ ga('send', 'pageview');
<span class="c1"># Start service after a given target. This is here because we want to define common</span>
<span class="c1"># after targets used on most services. This can be overridden or agumented using</span>
<span class="c1"># the &quot;systemd_services&quot; dictionary option &quot;init_config_overrides&quot;.</span>
<span class="c1"># the &quot;systemd_services&quot; dictionary option &quot;config_overrides&quot;.</span>
<span class="l l-Scalar l-Scalar-Plain">systemd_after_targets</span><span class="p p-Indicator">:</span>
<span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">syslog.target</span>
<span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">network.target</span>
@ -267,7 +267,7 @@ ga('send', 'pageview');
<span class="c1"># The systemd services dictionary is a set of services that will be created. The dictionary</span>
<span class="c1"># can contain the following options:</span>
<span class="c1"># `service_name` -- (required) used to define the name of the service. This is typically the name of the executable.</span>
<span class="c1"># `init_config_overrides` -- (optional) This allows any section or key=value pair to be set within the systemd unit file.</span>
<span class="c1"># `config_overrides` -- (optional) This allows any section or key=value pair to be set within the systemd unit file.</span>
<span class="c1"># `program_config_options` -- (optional) Provides the ability to pass in flags to a given service for execution.</span>
<span class="c1"># `program_override` -- (optional) sets the full path to the executable that will be run by the service file.</span>
<span class="c1"># `enabled` -- (optional) Set the enabled state of the service.</span>
@ -277,18 +277,18 @@ ga('send', 'pageview');
<span class="c1"># systemd_services:</span>
<span class="c1"># ServiceW:</span>
<span class="c1"># service_name: ServiceW</span>
<span class="c1"># init_config_overrides: {} # This is used to add in arbitratry unit file options</span>
<span class="c1"># config_overrides: {} # This is used to add in arbitratry unit file options</span>
<span class="c1"># ServiceX:</span>
<span class="c1"># service_name: ServiceX</span>
<span class="c1"># init_config_overrides: {} # This is used to add in arbitratry unit file options</span>
<span class="c1"># config_overrides: {} # This is used to add in arbitratry unit file options</span>
<span class="c1"># program_config_options: &#39;--flag1 things --flag2 other&#39;</span>
<span class="c1"># ServiceY:</span>
<span class="c1"># service_name: ServiceY</span>
<span class="c1"># init_config_overrides: {} # This is used to add in arbitratry unit file options</span>
<span class="c1"># config_overrides: {} # This is used to add in arbitratry unit file options</span>
<span class="c1"># program_override: &#39;/usr/bin/ServiceY&#39;</span>
<span class="c1"># ServiceZ:</span>
<span class="c1"># service_name: ServiceZ</span>
<span class="c1"># init_config_overrides: {} # This is used to add in arbitratry unit file options</span>
<span class="c1"># config_overrides: {} # This is used to add in arbitratry unit file options</span>
<span class="c1"># enabled: no</span>
<span class="c1"># state: stopped</span>
@ -307,7 +307,7 @@ ga('send', 'pageview');
<span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">role</span><span class="p p-Indicator">:</span> <span class="s">&quot;systemd_service&quot;</span>
<span class="l l-Scalar l-Scalar-Plain">systemd_services</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">service_name</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">ServiceX</span>
<span class="l l-Scalar l-Scalar-Plain">init_config_overrides</span><span class="p p-Indicator">:</span> <span class="p p-Indicator">{}</span>
<span class="l l-Scalar l-Scalar-Plain">config_overrides</span><span class="p p-Indicator">:</span> <span class="p p-Indicator">{}</span>
<span class="l l-Scalar l-Scalar-Plain">program_config_options</span><span class="p p-Indicator">:</span> <span class="s">&#39;--flag1</span><span class="nv"> </span><span class="s">things</span><span class="nv"> </span><span class="s">--flag2</span><span class="nv"> </span><span class="s">other&#39;</span>
<span class="l l-Scalar l-Scalar-Plain">tags</span><span class="p p-Indicator">:</span>
<span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">servicex-init</span>

View File

@ -15,66 +15,116 @@
- name: Create TEMP run dir
file:
path: "/var/run/{{ item.service_name }}"
path: "/var/run/{{ item.service_name | replace(' ', '_') }}"
state: directory
owner: "{{ systemd_user_name }}"
group: "{{ systemd_group_name }}"
owner: "{{ item.systemd_user_name | default(systemd_user_name) }}"
group: "{{ item.systemd_group_name | default(systemd_group_name) }}"
mode: "02755"
with_items: "{{ systemd_services }}"
tags:
- systemd-init
- name: Create TEMP lock dir
- name: Create TEMP service lock dir
file:
path: "/var/lock/{{ item.service_name }}"
path: "/var/lock/{{ item.service_name | replace(' ', '_') }}"
state: directory
owner: "{{ systemd_user_name }}"
group: "{{ systemd_group_name }}"
owner: "{{ item.systemd_user_name | default(systemd_user_name) }}"
group: "{{ item.systemd_group_name | default(systemd_group_name) }}"
mode: "02755"
with_items: "{{ systemd_services }}"
tags:
- systemd-init
- name: Create TEMP defined lock dir
file:
path: "{{ item.systemd_lock_path }}"
state: directory
owner: "{{ item.systemd_user_name | default(systemd_user_name) }}"
group: "{{ item.systemd_group_name | default(systemd_group_name) }}"
mode: "02755"
when:
- item.systemd_lock_path is defined
with_items: "{{ systemd_services }}"
tags:
- systemd-service
- name: Create tmpfiles.d entry
template:
src: "systemd-tmpfiles.j2"
dest: "/etc/tmpfiles.d/{{ systemd_tempd_prefix }}-{{ item.service_name }}.conf"
dest: "/etc/tmpfiles.d/{{ item.systemd_tempd_prefix | default(systemd_tempd_prefix) }}-{{ item.service_name | replace(' ', '_') }}.conf"
mode: "0644"
owner: "root"
group: "root"
when:
- item.systemd_lock_path is defined
with_items: "{{ systemd_services }}"
tags:
- systemd-init
- systemd-service
- name: Create tmpfiles.d entry
template:
src: "systemd-tmpfiles-lock.j2"
dest: "/etc/tmpfiles.d/{{ systemd_tempd_prefix }}-{{ systemd_lock_path.strip('/') | replace('/', '-') }}-lock.conf"
mode: "0644"
owner: "root"
group: "root"
- name: Check ExecStarts
fail:
msg: >-
When the service type is "simple" only ONE command can be started. Check
The list of execstarts and limit it to a single command per service or
consider using the "oneshot" service type. Defined ExecStart commands
"{{ item.execstarts }}".
when:
- item.execstarts is not string
- item.execstarts | length > 1
- item.service_type | default(systemd_default_service_type) != 'oneshot'
with_items: "{{ systemd_services }}"
tags:
- systemd-init
- systemd-service
- name: Place the systemd init script
- name: Check ExecStops
fail:
msg: >-
When the service type is "simple" only ONE command can be stopped. Check
The list of execstops and limit it to a single command per service or
consider using the "oneshot" service type. Defined ExecStop commands
"{{ item.execstops }}".
when:
- item.execstops is not string
- item.execstops | default([]) | length > 1
- item.service_type | default(systemd_default_service_type) != 'oneshot'
with_items: "{{ systemd_services }}"
tags:
- systemd-service
- name: Check ExecReloads
fail:
msg: >-
When the service type is "simple" only ONE command can be reloaded. Check
The list of execreloads and limit it to a single command per service or
consider using the "oneshot" service type. Defined ExecStop commands
"{{ item.execreloads }}".
when:
- item.execreloads is not string
- item.execreloads | default([]) | length > 1
- item.service_type | default(systemd_default_service_type) != 'oneshot'
with_items: "{{ systemd_services }}"
tags:
- systemd-service
- name: Place the systemd service
config_template:
src: "systemd-service.j2"
dest: "/etc/systemd/system/{{ item.service_name }}.service"
dest: "/etc/systemd/system/{{ item.service_name | replace(' ', '_') }}.service"
mode: "0644"
owner: "root"
group: "root"
config_overrides: "{{ item.init_config_overrides | default(systemd_service_config_overrides) }}"
config_overrides: "{{ item.config_overrides | default(systemd_service_config_overrides) }}"
config_type: "ini"
with_items: "{{ systemd_services }}"
tags:
- systemd-init
- systemd-service
- name: Load service
systemd:
name: "{{ item.service_name }}"
name: "{{ item.service_name | replace(' ', '_') }}"
daemon_reload: yes
enabled: "{{ item.enabled | default(systemd_service_enabled) }}"
state: "{{ item.state | default(omit) }}"
with_items: "{{ systemd_services }}"
tags:
- systemd-init
- systemd-service

View File

@ -12,7 +12,7 @@ Type={{ service_type }}
User={{ systemd_user_name }}
Group={{ systemd_group_name }}
{% set _execstarts = item.execstarts | default(systemd_default_execstarts) %}
{% set _execstarts = item.execstarts %}
{% if _execstarts is string %}
{% set _execstarts = [_execstarts] %}
{% endif %}
@ -20,7 +20,7 @@ Group={{ systemd_group_name }}
ExecStart={{ execstart }}
{% endfor %}
{% set _execreloads = item.execreloads | default(systemd_default_execreloads) %}
{% set _execreloads = item.execreloads | default((service_type == 'simple') | ternary(['/bin/kill -HUP $MAINPID'], [])) %}
{% if _execreloads is string %}
{% set _execreloads = [_execreloads] %}
{% endif %}
@ -28,7 +28,7 @@ ExecStart={{ execstart }}
ExecReload={{ execreload }}
{% endfor %}
{% set _execstops = item.execstops | default(systemd_default_execstops) %}
{% set _execstops = item.execstops | default([]) %}
{% if _execstops is string %}
{% set _execstops = [_execstops] %}
{% endif %}

View File

@ -1,3 +0,0 @@
# {{ ansible_managed }}
D {{ systemd_lock_path }} 2755 {{ systemd_user_name }} {{ systemd_group_name }}

View File

@ -1,4 +1,7 @@
# {{ ansible_managed }}
D /var/lock/{{ item.service_name }} 2755 {{ systemd_user_name }} {{ systemd_group_name }}
D /var/run/{{ item.service_name }} 2755 {{ systemd_user_name }} {{ systemd_group_name }}
{% if item.systemd_lock_path is defined %}
D {{ item.systemd_lock_path }} 2755 {{ item.systemd_user_name | default(systemd_user_name) }} {{ item.systemd_group_name | default(systemd_group_name) }}
{% endif %}
D /var/lock/{{ item.service_name | replace(' ', '_') }} 2755 {{ item.systemd_user_name | default(systemd_user_name) }} {{ item.systemd_group_name | default(systemd_group_name) }}
D /var/run/{{ item.service_name | replace(' ', '_') }} 2755 {{ item.systemd_user_name | default(systemd_user_name) }} {{ item.systemd_group_name | default(systemd_group_name) }}

View File

@ -21,3 +21,109 @@
become: true
roles:
- role: "systemd_service"
systemd_services:
- service_name: "test simple service0"
execstarts: "/bin/bash -c 'while true; do sleep 2 && echo test simple service; done'"
enabled: yes
state: started
- service_name: "test oneshot service0"
config_overrides:
Unit:
Description: Test oneshot service
After: network-online.target
Wants: network-online.target
Service:
RemainAfterExit: yes
service_type: oneshot
execstarts:
- "/bin/bash -c 'echo start1'"
- "/bin/bash -c 'echo start2'"
execstops:
- "/bin/bash -c 'echo stop1'"
- "/bin/bash -c 'echo stop2'"
enabled: yes
state: started
systemd_tempd_prefix: openstack
systemd_lock_path: /var/lock/networking
post_tasks:
- name: Check Services
command: systemctl status "{{ item }}"
changed_when: false
with_items:
- test_simple_service0
- test_oneshot_service0
tags:
- skip_ansible_lint
- name: Test failure condition
block:
- name: Run the systemd service role
include_role:
name: systemd_service
private: true
vars:
systemd_services:
- service_name: "test simple service1"
execstarts:
- "/bin/bash -c 'while true; do sleep 2 && echo test simple service1; done'"
- "/bin/bash -c 'while true; do sleep 2 && echo test simple service2; done'"
rescue:
- name: Set negative service test pass fact
set_fact:
systemd_service_execstarts_test: true
- name: Test failure condition
block:
- name: Run the systemd service role
include_role:
name: systemd_service
private: true
vars:
systemd_services:
- service_name: "test simple service2"
execstarts: "/bin/bash -c 'while true; do sleep 2 && echo test simple service; done'"
execstops:
- /bin/true
- /bin/true
rescue:
- name: Set negative service test pass fact
set_fact:
systemd_service_execstops_test: true
- name: Test failure condition
block:
- name: Run the systemd service role
include_role:
name: systemd_service
private: true
vars:
systemd_services:
- service_name: "test simple service3"
execstarts: "/bin/true"
execreloads:
- /bin/true
- /bin/true
rescue:
- name: Set negative service test pass fact
set_fact:
systemd_service_execreloads_test: true
- name: Check negative service testing
fail:
msg: >-
Failed negative service testing. Results --
systemd_service_execstarts_test: {{ systemd_service_execstarts_test }},
systemd_service_execstops_test: {{ systemd_service_execstops_test }},
systemd_service_execreloads_test: {{ systemd_service_execreloads_test }}
when:
- (not systemd_service_execstarts_test | bool) or
(not systemd_service_execstops_test | bool) or
(not systemd_service_execreloads_test | bool)
- name: Notify tests passed
debug:
msg: All tests have passed
vars:
systemd_service_execstarts_test: false
systemd_service_execstops_test: false
systemd_service_execreloads_test: false

View File

@ -1,21 +0,0 @@
---
# Copyright 2018, Logan Vig <logan2211@gmail.com>
#
# 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.
systemd_default_execstarts:
- "{{ item.program_override | default(systemd_bin_path ~ '/' ~ item.service_name) }} {{ item.program_config_options | default('') }}"
systemd_default_execreloads:
- '/bin/kill -HUP $MAINPID'
systemd_default_execstops: "{{ item.program_stop | default([]) }}"