Skip to content

Commit

Permalink
Initial import of systemd role content
Browse files Browse the repository at this point in the history
  • Loading branch information
msekletar committed Jul 20, 2023
1 parent 3e5636a commit 0303225
Show file tree
Hide file tree
Showing 35 changed files with 571 additions and 325 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright <YEAR> <COPYRIGHT HOLDER>
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
Expand Down
129 changes: 71 additions & 58 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,99 +1,112 @@
# 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

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 <[email protected]>
17 changes: 11 additions & 6 deletions defaults/main.yml
Original file line number Diff line number Diff line change
@@ -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: []
1 change: 1 addition & 0 deletions examples/foo.service.j2
9 changes: 5 additions & 4 deletions examples/simple.yml
Original file line number Diff line number Diff line change
@@ -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
Empty file added library/__init__.py
Empty file.
124 changes: 124 additions & 0 deletions library/systemd_units.py
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.

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()
Loading

0 comments on commit 0303225

Please sign in to comment.