From 3e8c14e36211801569439d260a31e2367dddbb1b Mon Sep 17 00:00:00 2001 From: Michal Sekletar Date: Wed, 28 Jun 2023 12:23:30 +0200 Subject: [PATCH] Initial import of systemd role content --- LICENSE | 2 +- README.md | 129 ++++++----- defaults/main.yml | 17 +- examples/foo.service.j2 | 1 + examples/simple.yml | 9 +- library/__init__.py | 0 library/systemd_units.py | 124 +++++++++++ meta/main.yml | 70 ++---- tasks/main.yml | 112 ++++++++-- tasks/set_vars.yml | 21 -- templates/foo.conf.j2 | 9 - .../defaults | 0 .../handlers | 0 .../roles/linux-system-roles.systemd/library | 1 + .../meta | 0 .../tasks | 0 .../templates | 0 .../vars | 0 tests/setup-snapshot.yml | 14 -- tests/tasks/check_header.yml | 16 -- tests/templates/foo.service.conf.j2 | 4 + tests/templates/foo.service.j2 | 7 + tests/templates/get_ansible_managed.j2 | 1 - tests/tests_basic.yml | 202 ++++++++++++++++++ tests/tests_default.yml | 14 +- tests/tests_facts.yml | 37 ++++ tests/tests_include_vars_from_parent.yml | 46 ---- vars/CentOS_7.yml | 7 - vars/CentOS_8.yml | 7 - vars/CentOS_9.yml | 7 - vars/Fedora.yml | 7 - vars/RedHat_7.yml | 7 - vars/RedHat_8.yml | 7 - vars/RedHat_9.yml | 7 - vars/main.yml | 22 +- 35 files changed, 582 insertions(+), 325 deletions(-) create mode 120000 examples/foo.service.j2 create mode 100644 library/__init__.py create mode 100644 library/systemd_units.py delete mode 100644 tasks/set_vars.yml delete mode 100644 templates/foo.conf.j2 rename tests/roles/{linux-system-roles.template => linux-system-roles.systemd}/defaults (100%) rename tests/roles/{linux-system-roles.template => linux-system-roles.systemd}/handlers (100%) create mode 120000 tests/roles/linux-system-roles.systemd/library rename tests/roles/{linux-system-roles.template => linux-system-roles.systemd}/meta (100%) rename tests/roles/{linux-system-roles.template => linux-system-roles.systemd}/tasks (100%) rename tests/roles/{linux-system-roles.template => linux-system-roles.systemd}/templates (100%) rename tests/roles/{linux-system-roles.template => linux-system-roles.systemd}/vars (100%) delete mode 100644 tests/setup-snapshot.yml delete mode 100644 tests/tasks/check_header.yml create mode 100644 tests/templates/foo.service.conf.j2 create mode 100644 tests/templates/foo.service.j2 delete mode 100644 tests/templates/get_ansible_managed.j2 create mode 100644 tests/tests_basic.yml create mode 100644 tests/tests_facts.yml delete mode 100644 tests/tests_include_vars_from_parent.yml delete mode 100644 vars/CentOS_7.yml delete mode 100644 vars/CentOS_8.yml delete mode 100644 vars/CentOS_9.yml delete mode 100644 vars/Fedora.yml delete mode 100644 vars/RedHat_7.yml delete mode 100644 vars/RedHat_8.yml delete mode 100644 vars/RedHat_9.yml diff --git a/LICENSE b/LICENSE index 5c025d1..8b86978 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright +Copyright 2023 Michal Sekletar Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index b5325fd..a9e8fac 100644 --- a/README.md +++ b/README.md @@ -1,75 +1,88 @@ -# Role Name +# systemd -![template](https://github.com/linux-system-roles/template/workflows/tox/badge.svg) +![template](https://github.com/linux-system-roles/systemd/workflows/tox/badge.svg) -A template for an ansible role that configures some GNU/Linux subsystem or -service. A brief description of the role goes here. +Ansible role that can be used to deploy unit files and manage systemd units. Role is a convenience +wrapper around systemd and template Ansible Core modules. -## Requirements +## Role Variables -Any prerequisites that may not be covered by Ansible itself or the role should -be mentioned here. This includes platform dependencies not managed by the -role, hardware requirements, external collections, etc. There should be a -distinction between *control node* requirements (like collections) and -*managed node* requirements (like special hardware, platform provisioning). +List of variables consumed by the role follows, note that none of them is mandatory. +### systemd_unit_files -### Collection requirements +List of systemd unit file names that should be deployed to managed nodes. -For instance, if the role depends on some collections and -has a `meta/collection-requirements.yml` file for installing those -dependencies, it should be mentioned here that the user should run +### systemd_unit_file_templates -``` -ansible-galaxy collection install -vv -r meta/collection-requirements.yml -``` +List of systemd unit file names that should be deployed to managed nodes. Each name should +correspond to Jinja template file that will be templated out to managed nodes, e.g. for unit +`foo.service` the respective `foo.service.j2` will be templated and copied over to managed +nodes. -on the *control node* before using the role. +### systemd_dropins -## Role Variables +List of systemd drop in files that will be templated out to managed hosts and will extend +respective systemd unit files. Name of the unit file that given entry extends is encoded in +the name of the entry itself. For example, for entry `foo.service.conf` it is expected that +`foo.service.conf.j2` Jinja template exists and resulting dropin file will extend `foo.service` +unit file. + +### systemd_started_units + +List of unit names that shall be started via systemd. + +### systemd_stopped_units + +List of unit names that shall be stopped via systemd. + +### systemd_restarted_units -A description of all input variables (i.e. variables that are defined in -`defaults/main.yml`) for the role should go here as these form an API of the -role. Each variable should have its own section e.g. +List of unit names that shall be restarted via systemd. -### template_foo +### systemd_reloaded_units -This variable is required. It is a string that lists the foo of the role. -There is no default value. +List of unit names that shall be reloaded via systemd. -### template_bar +### systemd_enabled_units -This variable is optional. It is a boolean that tells the role to disable bar. -The default value is `true`. +List of unit files that shall be enabled via systemd. -Variables that are not intended as input, like variables defined in -`vars/main.yml`, variables that are read from other roles and/or the global -scope (ie. hostvars, group vars, etc.) can be also mentioned here but keep in -mind that as these are probably not part of the role API they may change during -the lifetime. +### systemd_disabled_units + +List of unit files that shall be disabled via systemd. + +### systemd_masked_units + +List of unit files that shall be masked via systemd. + +### systemd_unmasked_units + +List of unit files that shall be unmasked via systemd. Example of setting the variables: ```yaml -template_foo: "oof" -template_bar: false +systemd_unit_files: + - foo.service + - bar.service +systemd_dropins: + - cups.service.conf.j2 + - avahi-daemon.service.conf.j2 +systemd_started_units: + - foo.service + - bar.service +systemd_enabled_units: + - foo.service + - bar.service ``` ## Variables Exported by the Role -This section is optional. Some roles may export variables for playbooks to -use later. These are analogous to "return values" in Ansible modules. For -example, if a role performs some action that will require a system reboot, but -the user wants to defer the reboot, the role might set a variable like -`template_reboot_needed: true` that the playbook can use to reboot at a more -convenient time. - -Example: +### `systemd_units` -### template_reboot_needed - -Default `false` - if `true`, this means a reboot is needed to apply the changes -made by the role +Variable shall contain a list of dictionaries where each entry describes state of one systemd unit +present on the managed host. ## Example Playbook @@ -77,23 +90,23 @@ Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too: ```yaml -- name: Manage the template subsystem +- name: Deploy and start systemd unit hosts: all vars: - template_foo: "foo foo!" - template_bar: false + systemd_unit_files: + - foo.service + systemd_started_units: + - foo.service + systemd_enabled_units: + - foo.service roles: - - linux-system-roles.template + - linux-system-roles.systemd ``` -More examples can be provided in the [`examples/`](examples) directory. These -can be useful, especially for documentation. - ## License -Whenever possible, please prefer MIT. +MIT -## Author Information +## Author -An optional section for the role authors to include contact information, or a -website (HTML is not allowed). +Michal Sekletar diff --git a/defaults/main.yml b/defaults/main.yml index 6944529..a35f9ec 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,8 +1,13 @@ # SPDX-License-Identifier: MIT --- -# Here is the right place to put the role's input variables. -# This file also serves as a documentation for such a variables. - -# Examples of role input variables: -template_foo: foo -template_bar: true +systemd_unit_files: [] +systemd_unit_file_templates: [] +systemd_dropins: [] +systemd_started_units: [] +systemd_stopped_units: [] +systemd_restarted_units: [] +systemd_reloaded_units: [] +systemd_enabled_units: [] +systemd_disabled_units: [] +systemd_masked_units: [] +systemd_unmasked_units: [] diff --git a/examples/foo.service.j2 b/examples/foo.service.j2 new file mode 120000 index 0000000..623dc9a --- /dev/null +++ b/examples/foo.service.j2 @@ -0,0 +1 @@ +../tests/templates/foo.service.j2 \ No newline at end of file diff --git a/examples/simple.yml b/examples/simple.yml index 4f1456e..21732a2 100644 --- a/examples/simple.yml +++ b/examples/simple.yml @@ -1,9 +1,10 @@ # SPDX-License-Identifier: MIT --- -- name: Example template role invocation +- name: Deploy and start systemd unit hosts: all vars: - template_foo: example variable value - template_bar: false + systemd_unit_files: ['foo.service'] + systemd_started_units: ['foo.service'] + systemd_enabled_units: ['foo.service'] roles: - - linux-system-roles.template + - linux-system-roles.systemd diff --git a/library/__init__.py b/library/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/library/systemd_units.py b/library/systemd_units.py new file mode 100644 index 0000000..74399e2 --- /dev/null +++ b/library/systemd_units.py @@ -0,0 +1,124 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# SPDX-License-Identifier: GPL-3.0-or-later + +# Get state of systemd units and export it as facts data +# Copyright (C) 2023 Michal Sekletar + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + + +DOCUMENTATION = r""" +--- +module: systemd_units +author: Michal Sekletar (@msekletar) +short_description: Return systemd units status as fact data +requirements: [systemd] +description: + - This module gathers state of systemd units and exposes it as facts data +options: {} +""" + +RETURN = r""" +--- +ansible_facts: + description: Facts about systemd units + returned: always + type: complex + contains: + systemd_units: + type: list + elements: dict + description: State of systemd units + returned: always + contains: + name: + description: Name of the unit. + returned: always + type: str + sample: cups.service + load_state: + description: Load state of the unit file. + returned: always + type: str + sample: loaded + active_state: + description: Main active state of the unit. + returned: always + type: str + sample: active + sub_state: + description: Sub state of the unit. + returned: always + type: str + sample: listening + description: + description: Description of the unit. + returned: always + type: str + sample: Journal Service +""" + +EXAMPLES = r""" +--- +- hosts: all + name: Gather systemd_units facts + roles: + - linux-system-roles.systemd + tasks: + - name: Print units facts + debug: + msg: "{{ systemd_units }}" +""" + +from ansible.module_utils.basic import AnsibleModule + + +class SystemdUnitsFacts: + def __init__(self, module): + self.module = module + + def units(self): + systemctl = self.module.get_bin_path("systemctl", opt_dirs=["/usr/bin", "/usr/local/bin"]) + + units = {} + rc, stdout, stderr = self.module.run_command("%s list-units --no-pager --no-legend" % systemctl, use_unsafe_shell=True) + if rc != 0: + self.module.warn("Could not list units: %s" % stderr) + return {} + + for line in stdout.splitlines(): + f = line.split() + if len(f) >= 5: + units[f[0]] = {"name": f[0], "load_state": f[1], "active_state": f[2], "sub_state": f[3], "description": " ".join(f[4:])} + + return units + + +def main(): + module = AnsibleModule(argument_spec={}, supports_check_mode=True) + systemd_facts_module = SystemdUnitsFacts(module) + + units = systemd_facts_module.units() + + results = dict(ansible_facts={"systemd_units": units}) + module.exit_json(**results) + + +if __name__ == '__main__': + main() diff --git a/meta/main.yml b/meta/main.yml index 0862691..87098d4 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -1,68 +1,26 @@ # SPDX-License-Identifier: MIT --- galaxy_info: - # Replace with role's author name: - author: John Doe - # Replace with the real description of what is role's purpose: - description: Basic template for Linux system roles - # Replace with the company the role's author is member of: - company: John Doe, Inc. - - # If the issue tracker for your role is not on github, uncomment the next - # line and provide a value - # issue_tracker_url: http://example.com/issue/tracker - - # Some suggested licenses: - # - BSD (default) - # - MIT - # - GPLv2 - # - GPLv3 - # - Apache - # - CC-BY + author: Michal Sekletar + description: Deploy and control systemd units + galaxy_tags: + - system + - systemd + - service + - rhel + - fedora + - centos + company: Red Hat, Inc. license: MIT - min_ansible_version: "2.9" - - # Optionally specify the branch Galaxy will use when accessing the GitHub - # repo for this role. During role install, if no tags are available, Galaxy - # will use this branch. During import Galaxy will access files on this - # branch. If Travis integration is configured, only notifications for this - # branch will be accepted. Otherwise, in all cases, the repo's default branch - # (usually main) will be used. - # github_branch: - - # - # platforms is a list of platforms, and each platform has a name and a list - # of versions. - # - # platforms: - # - name: Fedora - # versions: - # - all - # - "25" - # - name: SomePlatform - # versions: - # - all - # - "1.0" - # - "7" - # - "99.99" platforms: - # Replace the below with your platform list: - name: Fedora versions: - all - name: EL versions: - - all - - galaxy_tags: [] - # List tags for your role here, one per line. A tag is a keyword that - # describes and categorizes the role. Users find roles by searching for tags. - # Be sure to remove the '[]' above, if you add tags to this list. - # - # NOTE: A tag is limited to a single word comprised of alphanumeric - # characters. Maximum 20 tags per role. + - "7" + - "8" + - "9" -dependencies: [] -# List your role dependencies here, one per line. Be sure to remove the '[]' -# above, if you add dependencies to this list. +allow_duplicates: true diff --git a/tasks/main.yml b/tasks/main.yml index 6b6a808..aa51a28 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,25 +1,107 @@ # SPDX-License-Identifier: MIT --- -- name: Set platform/version specific variables - include_tasks: tasks/set_vars.yml - -# Examples of some tasks: - name: Ensure required packages are installed package: - name: "{{ __template_packages }}" + name: "{{ __systemd_packages }}" state: present -- name: Ensure required services are enabled and started - service: +- name: Deploy unit files + copy: + src: "{{ item }}" + dest: "{{ __admin_units_dir }}/{{ item }}" + owner: root + group: root + mode: '0644' + loop: "{{ systemd_unit_files }}" + register: __systemd_unit_files_result + +- name: Deploy unit file templates + template: + src: "{{ item }}.j2" + dest: "{{ __admin_units_dir }}/{{ item }}" + owner: root + group: root + mode: '0644' + loop: "{{ systemd_unit_file_templates }}" + register: __systemd_unit_file_templates_result + +- name: Create drop-in directories + file: + path: "{{ __admin_units_dir }}/{{ '.'.join(item.split('.')[:-1]) }}.d/" + state: directory + owner: root + group: root + mode: '0755' + loop: "{{ systemd_dropins }}" + +- name: Deploy systemd drop in config + template: + src: "{{ item }}.j2" + dest: "{{ __admin_units_dir }}/\ + {{ '.'.join(item.split('.')[:-1]) }}.d/\ + 99-override.conf" + owner: root + group: root + mode: '0644' + loop: "{{ systemd_dropins }}" + register: __systemd_dropins_result + +- name: Reload systemd + systemd: + daemon_reload: true + when: > + __systemd_unit_files_result is changed or + __systemd_unit_file_templates_result is changed or + __systemd_dropins_result is changed + +- name: Ensure required units are started + systemd: name: "{{ item }}" state: started + loop: "{{ systemd_started_units }}" + +- name: Ensure required units are stopped + systemd: + name: "{{ item }}" + state: stopped + loop: "{{ systemd_stopped_units }}" + +- name: Ensure required units are restarted + systemd: + name: "{{ item }}" + state: restarted + loop: "{{ systemd_restarted_units }}" + +- name: Ensure required units are reloaded + systemd: + name: "{{ item }}" + state: reloaded + loop: "{{ systemd_reloaded_units }}" + +- name: Ensure required units are enabled + systemd: + name: "{{ item }}" enabled: true - loop: "{{ __template_services }}" + loop: "{{ systemd_enabled_units }}" -- name: Generate /etc/{{ __template_foo_config }} - template: - src: "{{ __template_foo_config }}.j2" - dest: /etc/{{ __template_foo_config }} - backup: true - mode: 0400 - notify: Handler for template to restart services +- name: Ensure required units are disabled + systemd: + name: "{{ item }}" + enabled: false + loop: "{{ systemd_disabled_units }}" + +- name: Ensure required units are masked + systemd: + name: "{{ item }}" + masked: true + loop: "{{ systemd_masked_units }}" + +- name: Ensure required units are unmasked + systemd: + name: "{{ item }}" + masked: false + loop: "{{ systemd_unmasked_units }}" + +- name: Gather systemd units state + systemd_units: + register: systemd_units diff --git a/tasks/set_vars.yml b/tasks/set_vars.yml deleted file mode 100644 index 605c9f7..0000000 --- a/tasks/set_vars.yml +++ /dev/null @@ -1,21 +0,0 @@ ---- -- name: Ensure ansible_facts used by role - setup: - gather_subset: "{{ __systemd_required_facts_subsets }}" - when: __systemd_required_facts | - difference(ansible_facts.keys() | list) | length > 0 - -- name: Set platform/version specific variables - include_vars: "{{ __vars_file }}" - loop: - - "{{ ansible_facts['os_family'] }}.yml" - - "{{ ansible_facts['distribution'] }}.yml" - - >- - {{ ansible_facts['distribution'] ~ '_' ~ - ansible_facts['distribution_major_version'] }}.yml - - >- - {{ ansible_facts['distribution'] ~ '_' ~ - ansible_facts['distribution_version'] }}.yml - vars: - __vars_file: "{{ role_path }}/vars/{{ item }}" - when: __vars_file is file diff --git a/templates/foo.conf.j2 b/templates/foo.conf.j2 deleted file mode 100644 index 5fc204b..0000000 --- a/templates/foo.conf.j2 +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: MIT -# -# Example of a template of configuration file -# -{{ ansible_managed | comment }} -{{ "system_role:template" | comment(prefix="", postfix="") }} -[foo] -foo = {{ template_foo }} -bar = {{ template_bar }} diff --git a/tests/roles/linux-system-roles.template/defaults b/tests/roles/linux-system-roles.systemd/defaults similarity index 100% rename from tests/roles/linux-system-roles.template/defaults rename to tests/roles/linux-system-roles.systemd/defaults diff --git a/tests/roles/linux-system-roles.template/handlers b/tests/roles/linux-system-roles.systemd/handlers similarity index 100% rename from tests/roles/linux-system-roles.template/handlers rename to tests/roles/linux-system-roles.systemd/handlers diff --git a/tests/roles/linux-system-roles.systemd/library b/tests/roles/linux-system-roles.systemd/library new file mode 120000 index 0000000..ba40d2f --- /dev/null +++ b/tests/roles/linux-system-roles.systemd/library @@ -0,0 +1 @@ +../../../library \ No newline at end of file diff --git a/tests/roles/linux-system-roles.template/meta b/tests/roles/linux-system-roles.systemd/meta similarity index 100% rename from tests/roles/linux-system-roles.template/meta rename to tests/roles/linux-system-roles.systemd/meta diff --git a/tests/roles/linux-system-roles.template/tasks b/tests/roles/linux-system-roles.systemd/tasks similarity index 100% rename from tests/roles/linux-system-roles.template/tasks rename to tests/roles/linux-system-roles.systemd/tasks diff --git a/tests/roles/linux-system-roles.template/templates b/tests/roles/linux-system-roles.systemd/templates similarity index 100% rename from tests/roles/linux-system-roles.template/templates rename to tests/roles/linux-system-roles.systemd/templates diff --git a/tests/roles/linux-system-roles.template/vars b/tests/roles/linux-system-roles.systemd/vars similarity index 100% rename from tests/roles/linux-system-roles.template/vars rename to tests/roles/linux-system-roles.systemd/vars diff --git a/tests/setup-snapshot.yml b/tests/setup-snapshot.yml deleted file mode 100644 index a7704df..0000000 --- a/tests/setup-snapshot.yml +++ /dev/null @@ -1,14 +0,0 @@ ---- -- name: Setup snapshot - hosts: all - tasks: - - name: Set platform/version specific variables - include_role: - name: linux-system-roles.template - tasks_from: set_vars.yml - public: true - - - name: Install test packages - package: - name: "{{ __template_packages }}" - state: present diff --git a/tests/tasks/check_header.yml b/tests/tasks/check_header.yml deleted file mode 100644 index 607320f..0000000 --- a/tests/tasks/check_header.yml +++ /dev/null @@ -1,16 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -- name: Get file - slurp: - path: "{{ __file }}" - register: __content - when: not __file_content is defined - -- name: Check for presence of ansible managed header, fingerprint - assert: - that: - - ansible_managed in content - - __fingerprint in content - vars: - content: "{{ (__file_content | d(__content)).content | b64decode }}" - ansible_managed: "{{ lookup('template', 'get_ansible_managed.j2') }}" diff --git a/tests/templates/foo.service.conf.j2 b/tests/templates/foo.service.conf.j2 new file mode 100644 index 0000000..5f54457 --- /dev/null +++ b/tests/templates/foo.service.conf.j2 @@ -0,0 +1,4 @@ +{{ ansible_managed | comment }} + +[Service] +PrivateTmp=yes diff --git a/tests/templates/foo.service.j2 b/tests/templates/foo.service.j2 new file mode 100644 index 0000000..63fc17f --- /dev/null +++ b/tests/templates/foo.service.j2 @@ -0,0 +1,7 @@ +{{ ansible_managed | comment }} +[Service] +ExecStart=/bin/sleep 3600 +ExecReload=/bin/touch /tmp/foo-reloaded + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/tests/templates/get_ansible_managed.j2 b/tests/templates/get_ansible_managed.j2 deleted file mode 100644 index c690cfa..0000000 --- a/tests/templates/get_ansible_managed.j2 +++ /dev/null @@ -1 +0,0 @@ -{{ ansible_managed | comment(__comment_type | d("plain")) }} diff --git a/tests/tests_basic.yml b/tests/tests_basic.yml new file mode 100644 index 0000000..f693b8a --- /dev/null +++ b/tests/tests_basic.yml @@ -0,0 +1,202 @@ +# SPDX-License-Identifier: MIT +--- +- hosts: all + name: Ensure that deploying unit files work correctly + gather_facts: false + vars: + systemd_unit_file_templates: ['foo.service'] + roles: + - linux-system-roles.systemd + tasks: + - name: Verify that unit file was deployed + stat: + path: /etc/systemd/system/foo.service + +- hosts: all + name: Ensure that deploying unit file dropins work correctly + gather_facts: false + vars: + systemd_dropins: ['foo.service.conf'] + roles: + - linux-system-roles.systemd + tasks: + - name: Stat the dropin directory path + stat: + path: /etc/systemd/system/foo.service.d + register: dropin + + - name: Check that drop in directory exists + assert: + that: + - dropin.stat.isdir | d(false) + + - name: Verify that dropin file was deployed + stat: + path: /etc/systemd/system/foo.service.d/99-override.conf + +- hosts: all + name: Ensure that we can start units using the role + gather_facts: false + vars: + systemd_started_units: ['foo.service'] + roles: + - linux-system-roles.systemd + tasks: + - name: Make sure that foo.service main state is active + assert: + that: + - >- + ansible_facts['systemd_units'] + ['foo.service'] + ['active_state'] == "active" + - >- + ansible_facts['systemd_units'] + ['foo.service'] + ['sub_state'] == "running" + +- hosts: all + name: Ensure that we can restart units using the role + gather_facts: false + vars: + systemd_restarted_units: ['foo.service'] + roles: + - linux-system-roles.systemd + pre_tasks: + - name: Save MainPID of foo.service before restart + # noqa command-instead-of-module + command: systemctl show -p MainPID foo.service + register: pid_before_restart + changed_when: false + tasks: + - name: Get MainPID of foo.service + # noqa command-instead-of-module + command: systemctl show -p MainPID foo.service + register: pid_after_restart + changed_when: false + + - name: Check that service was restarted by looking at MainPID + assert: + that: + - pid_before_restart.stdout != pid_after_restart.stdout + +- hosts: all + name: Ensure that we can reload units + gather_facts: false + vars: + systemd_reloaded_units: ['foo.service'] + roles: + - linux-system-roles.systemd + pre_tasks: + - name: Delete reload flag file + file: + path: /tmp/foo-service-reloaded + state: absent + tasks: + - name: Reload operation should created flag file + stat: + path: /tmp/foo-service-reloaded + +- hosts: all + name: Ensure that we can enable unit files + gather_facts: false + vars: + systemd_enabled_units: ['foo.service'] + roles: + - linux-system-roles.systemd + pre_tasks: + - name: Save UnitFileState before calling role + # noqa command-instead-of-module + command: systemctl show -p UnitFileState foo.service + register: unit_file_state_before + changed_when: false + tasks: + - name: Get UnitFileState= + # noqa command-instead-of-module + command: systemctl show -p UnitFileState foo.service + register: unit_file_state_after + changed_when: false + + - name: Check that unit file was enabled + assert: + that: + - unit_file_state_before.stdout == "UnitFileState=disabled" + - unit_file_state_after.stdout == "UnitFileState=enabled" + +- hosts: all + name: Ensure that we can disable unit files + gather_facts: false + vars: + systemd_disabled_units: ['foo.service'] + roles: + - linux-system-roles.systemd + tasks: + - name: Get UnitFileState= + # noqa command-instead-of-module + command: systemctl show -p UnitFileState foo.service + register: unit_file_state_now + changed_when: false + + - name: Check that foo.service is disabled + assert: + that: + - unit_file_state_now.stdout == "UnitFileState=disabled" + +- hosts: all + name: Ensure that we can mask unit files + gather_facts: false + vars: + # It is not possible to mask admin units files in /etc/systemd/system. + systemd_masked_units: ['sshd.service'] + roles: + - linux-system-roles.systemd + pre_tasks: + - name: Save UnitFileState before calling role + # noqa command-instead-of-module + command: systemctl show -p UnitFileState sshd.service + register: sshd_state_before + changed_when: false + tasks: + - name: Get UnitFileState= + # noqa command-instead-of-module + command: systemctl show -p UnitFileState sshd.service + register: sshd_state_after + changed_when: false + + - name: Check that sshd is masked + assert: + that: + - sshd_state_before.stdout == "UnitFileState=enabled" + - >- + sshd_state_after.stdout == "UnitFileState=masked" or + sshd_state_after.stdout == "UnitFileState=bad" + +- hosts: all + name: Ensure that we can unmask unit files + gather_facts: false + vars: + systemd_unmasked_units: ['sshd.service'] + roles: + - linux-system-roles.systemd + tasks: + - name: Get UnitFileState= + # noqa command-instead-of-module + command: systemctl show -p UnitFileState sshd.service + register: sshd_state_now + changed_when: false + + - name: Check that sshd was correctly unmasked + assert: + that: + - sshd_state_now.stdout == "UnitFileState=enabled" + +- hosts: all + name: Ensure that we can stop units + gather_facts: false + vars: + systemd_stopped_units: ['foo.service'] + roles: + - linux-system-roles.systemd + tasks: + - name: Foo.service shouldn't be in systemd_units + fail: + when: ansible_facts['systemd_units']['foo.service'] is defined diff --git a/tests/tests_default.yml b/tests/tests_default.yml index 4457422..bb6337c 100644 --- a/tests/tests_default.yml +++ b/tests/tests_default.yml @@ -1,13 +1,7 @@ # SPDX-License-Identifier: MIT --- -- name: Ensure that the role runs with default parameters - hosts: all - gather_facts: false # test that role works in this case +- hosts: all + name: Ensure that the role runs with no arguments + gather_facts: false roles: - - linux-system-roles.template - tasks: - - name: Check header for ansible_managed, fingerprint - include_tasks: tasks/check_header.yml - vars: - __file: /etc/foo.conf - __fingerprint: system_role:template + - linux-system-roles.systemd diff --git a/tests/tests_facts.yml b/tests/tests_facts.yml new file mode 100644 index 0000000..a5594e3 --- /dev/null +++ b/tests/tests_facts.yml @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: MIT +--- +- hosts: all + name: Ensure that basic features of role work correctly + roles: + - linux-system-roles.systemd + tasks: + - name: Print units facts + debug: + msg: "{{ systemd_units }}" + + - name: Check that unit state object has required fields + assert: + that: + - >- + ansible_facts["systemd_units"] + ["sshd.service"] + ["name"] == "sshd.service" + - >- + ansible_facts["systemd_units"] + ["sshd.service"] + ["active_state"] == "active" + + - >- + ansible_facts["systemd_units"] + ["sshd.service"] + ["sub_state"] == "running" + + - >- + ansible_facts["systemd_units"] + ["sshd.service"] + ["load_state"] == "loaded" + + - >- + ansible_facts["systemd_units"] + ["sshd.service"] + ["description"] | length > 0 diff --git a/tests/tests_include_vars_from_parent.yml b/tests/tests_include_vars_from_parent.yml deleted file mode 100644 index 2c0405d..0000000 --- a/tests/tests_include_vars_from_parent.yml +++ /dev/null @@ -1,46 +0,0 @@ ---- -- name: Test role variable override - hosts: all - gather_facts: true - tasks: - - name: Create var file in caller that can override the one in called role - delegate_to: localhost - copy: - # usually the fake file will cause the called role to crash of - # overriding happens, but if not, set a variable that will - # allow to detect the bug - content: "__caller_override: true" - # XXX ugly, self-modifying code - changes the "caller" role on - # the controller - dest: "{{ playbook_dir }}/roles/caller/vars/{{ item }}.yml" - mode: preserve - loop: "{{ varfiles | unique }}" - # In case the playbook is executed against multiple hosts, use - # only the first one. Otherwise the hosts would stomp on each - # other since they are changing files on the controller. - when: inventory_hostname == ansible_play_hosts_all[0] - vars: - # change to hostvars['localhost']['ansible_facts'] to use the - # information for localhost - facts: "{{ ansible_facts }}" - versions: - - "{{ facts['distribution_version'] }}" - - "{{ facts['distribution_major_version'] }}" - separators: ["-", "_"] - # create all variants like CentOS, CentOS_8.1, CentOS-8.1, - # CentOS-8, CentOS-8.1 - # more formally: - # {{ ansible_distribution }}-{{ ansible_distribution_version }} - # {{ ansible_distribution }}-{{ ansible_distribution_major_version }} - # {{ ansible_distribution }} - # {{ ansible_os_family }} - # and the same for _ as separator. - varfiles: "{{ [facts['distribution']] | product(separators) | - map('join') | product(versions) | map('join') | list + - [facts['distribution'], facts['os_family']] }}" - - - name: Import role - import_role: - name: caller - vars: - roletoinclude: linux-system-roles.template diff --git a/vars/CentOS_7.yml b/vars/CentOS_7.yml deleted file mode 100644 index 24448bc..0000000 --- a/vars/CentOS_7.yml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -# Put internal variables here with CentOS 7 specific values. - -# Example: -__template_packages: [] -__template_services: [] diff --git a/vars/CentOS_8.yml b/vars/CentOS_8.yml deleted file mode 100644 index 0fb6af8..0000000 --- a/vars/CentOS_8.yml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -# Put internal variables here with CentOS 8 specific values. - -# Example: -__template_packages: [] -__template_services: [] diff --git a/vars/CentOS_9.yml b/vars/CentOS_9.yml deleted file mode 100644 index 7c25b3c..0000000 --- a/vars/CentOS_9.yml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -# Put internal variables here with CentOS 9 specific values. - -# Example: -__template_packages: [] -__template_services: [] diff --git a/vars/Fedora.yml b/vars/Fedora.yml deleted file mode 100644 index a783f79..0000000 --- a/vars/Fedora.yml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -# Put internal variables here with Fedora specific values. - -# Example: -__template_packages: [] -__template_services: [] diff --git a/vars/RedHat_7.yml b/vars/RedHat_7.yml deleted file mode 100644 index 3815df4..0000000 --- a/vars/RedHat_7.yml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -# Put internal variables here with Red Hat Enterprise Linux 7 specific values. - -# Example: -__template_packages: [] -__template_services: [] diff --git a/vars/RedHat_8.yml b/vars/RedHat_8.yml deleted file mode 100644 index 954bf90..0000000 --- a/vars/RedHat_8.yml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -# Put internal variables here with Red Hat Enterprise Linux 8 specific values. - -# Example: -__template_packages: [] -__template_services: [] diff --git a/vars/RedHat_9.yml b/vars/RedHat_9.yml deleted file mode 100644 index b367bff..0000000 --- a/vars/RedHat_9.yml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -# Put internal variables here with Red Hat Enterprise Linux 9 specific values. - -# Example: -__template_packages: [] -__template_services: [] diff --git a/vars/main.yml b/vars/main.yml index 32f924d..6b34ff6 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -1,21 +1,5 @@ # SPDX-License-Identifier: MIT --- -# Put the role's internal variables here that are not distribution specific. -# You can override these by defining the same variable with a different -# value in a platform/version specific file in vars/ - -# Examples of non-distribution specific (generic) internal variables: -__template_foo_config: foo.conf -__template_packages: [] -__template_services: [] -# ansible_facts required by the role -__systemd_required_facts: - - distribution - - distribution_major_version - - distribution_version - - os_family -# the subsets of ansible_facts that need to be gathered in case any of the -# facts in required_facts is missing; see the documentation of -# the 'gather_subset' parameter of the 'setup' module -__systemd_required_facts_subsets: "{{ ['!all', '!min'] + - __systemd_required_facts }}" +__systemd_packages: + - systemd +__admin_units_dir: /etc/systemd/system