mirror of
https://github.com/containers/ansible-podman-collections.git
synced 2026-02-04 07:11:49 +00:00
Add systemd generation for pods (#299)
This commit is contained in:
parent
24329ce5d3
commit
5d37e1ee22
7 changed files with 187 additions and 61 deletions
|
|
@ -4,6 +4,7 @@
|
|||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
|
||||
|
|
@ -21,6 +22,63 @@ def run_podman_command(module, executable='podman', args=None, expected_rc=0, ig
|
|||
return rc, out, err
|
||||
|
||||
|
||||
def generate_systemd(module, module_params, name):
|
||||
"""Generate systemd unit file."""
|
||||
command = [module_params['executable'], 'generate', 'systemd',
|
||||
name, '--format', 'json']
|
||||
sysconf = module_params['generate_systemd']
|
||||
empty = {}
|
||||
if sysconf.get('restart_policy'):
|
||||
if sysconf.get('restart_policy') not in [
|
||||
"no", "on-success", "on-failure", "on-abnormal", "on-watchdog",
|
||||
"on-abort", "always"]:
|
||||
module.fail_json(
|
||||
'Restart policy for systemd unit file is "%s" and must be one of: '
|
||||
'"no", "on-success", "on-failure", "on-abnormal", "on-watchdog", "on-abort", or "always"' %
|
||||
sysconf.get('restart_policy'))
|
||||
command.extend([
|
||||
'--restart-policy',
|
||||
sysconf['restart_policy']])
|
||||
if sysconf.get('time'):
|
||||
command.extend(['--time', str(sysconf['time'])])
|
||||
if sysconf.get('no_header'):
|
||||
command.extend(['--no-header'])
|
||||
if sysconf.get('names', True):
|
||||
command.extend(['--name'])
|
||||
if sysconf.get('container_prefix'):
|
||||
command.extend(['--container-prefix=%s' % sysconf['container_prefix']])
|
||||
if sysconf.get('pod_prefix'):
|
||||
command.extend(['--pod-prefix=%s' % sysconf['pod_prefix']])
|
||||
if sysconf.get('separator'):
|
||||
command.extend(['--separator=%s' % sysconf['separator']])
|
||||
if module.params['debug'] or module_params['debug']:
|
||||
module.log("PODMAN-CONTAINER-DEBUG: systemd command: %s" %
|
||||
" ".join(command))
|
||||
rc, systemd, err = module.run_command(command)
|
||||
if rc != 0:
|
||||
module.log(
|
||||
"PODMAN-CONTAINER-DEBUG: Error generating systemd: %s" % err)
|
||||
return empty
|
||||
else:
|
||||
try:
|
||||
data = json.loads(systemd)
|
||||
if sysconf.get('path'):
|
||||
if not os.path.exists(sysconf['path']):
|
||||
os.makedirs(sysconf['path'])
|
||||
if not os.path.isdir(sysconf['path']):
|
||||
module.fail_json("Path %s is not a directory! "
|
||||
"Can not save systemd unit files there!"
|
||||
% sysconf['path'])
|
||||
for k, v in data.items():
|
||||
with open(os.path.join(sysconf['path'], k), 'w') as f:
|
||||
f.write(v)
|
||||
return data
|
||||
except Exception as e:
|
||||
module.log(
|
||||
"PODMAN-CONTAINER-DEBUG: Error writing systemd: %s" % e)
|
||||
return empty
|
||||
|
||||
|
||||
def lower_keys(x):
|
||||
if isinstance(x, list):
|
||||
return [lower_keys(v) for v in x]
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ from distutils.version import LooseVersion # noqa: F402
|
|||
|
||||
from ansible.module_utils._text import to_bytes, to_native # noqa: F402
|
||||
from ansible_collections.containers.podman.plugins.module_utils.podman.common import lower_keys
|
||||
from ansible_collections.containers.podman.plugins.module_utils.podman.common import generate_systemd
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
|
|
@ -1511,56 +1512,6 @@ class PodmanManager:
|
|||
self.container = PodmanContainer(
|
||||
self.module, self.name, self.module_params)
|
||||
|
||||
def generate_systemd(self):
|
||||
"""Generate systemd unit file."""
|
||||
command = [self.module_params['executable'], 'generate', 'systemd',
|
||||
self.name, '--format', 'json']
|
||||
sysconf = self.module_params['generate_systemd']
|
||||
empty = {'name': '', 'text': ''}
|
||||
if sysconf.get('restart_policy'):
|
||||
if sysconf.get('restart_policy') not in [
|
||||
"no", "on-success", "on-failure", "on-abnormal", "on-watchdog",
|
||||
"on-abort", "always"]:
|
||||
self.module.fail_json(
|
||||
'Restart policy for systemd unit file is "%s" and must be one of: '
|
||||
'"no", "on-success", "on-failure", "on-abnormal", "on-watchdog", "on-abort", or "always"' %
|
||||
sysconf.get('restart_policy'))
|
||||
command.extend([
|
||||
'--restart-policy',
|
||||
sysconf['restart_policy']])
|
||||
if sysconf.get('time'):
|
||||
command.extend(['--time', str(sysconf['time'])])
|
||||
if sysconf.get('no_header'):
|
||||
command.extend(['--no-header'])
|
||||
if sysconf.get('names', True):
|
||||
command.extend(['--name'])
|
||||
if sysconf.get('container_prefix'):
|
||||
command.extend(['--container-prefix=%s' % sysconf['container_prefix']])
|
||||
if sysconf.get('pod_prefix'):
|
||||
command.extend(['--pod-prefix=%s' % sysconf['pod_prefix']])
|
||||
if sysconf.get('separator'):
|
||||
command.extend(['--separator=%s' % sysconf['separator']])
|
||||
if self.module.params['debug'] or self.module_params['debug']:
|
||||
self.module.log("PODMAN-CONTAINER-DEBUG: systemd command: %s" % " ".join(command))
|
||||
rc, systemd, err = self.module.run_command(command)
|
||||
if rc != 0:
|
||||
self.module.log(
|
||||
"PODMAN-CONTAINER-DEBUG: Error generating systemd: %s" % err)
|
||||
return empty
|
||||
else:
|
||||
try:
|
||||
systemd_text = list(json.loads(systemd).values())[0]
|
||||
systemd_name = list(json.loads(systemd).keys())[0]
|
||||
if sysconf.get('file'):
|
||||
with open(sysconf['file'], 'w') as f:
|
||||
f.write(systemd_text)
|
||||
return {'name': systemd_name,
|
||||
'text': systemd_text}
|
||||
except Exception as e:
|
||||
self.module.log(
|
||||
"PODMAN-CONTAINER-DEBUG: Error writing systemd: %s" % e)
|
||||
return empty
|
||||
|
||||
def update_container_result(self, changed=True):
|
||||
"""Inspect the current container, update results with last info, exit.
|
||||
|
||||
|
|
@ -1578,7 +1529,7 @@ class PodmanManager:
|
|||
if self.module.params['debug'] or self.module_params['debug']:
|
||||
self.results.update({'podman_version': self.container.version})
|
||||
self.results.update(
|
||||
{'podman_systemd': self.generate_systemd()})
|
||||
{'podman_systemd': generate_systemd(self.module, self.module_params, self.name)})
|
||||
|
||||
def make_started(self):
|
||||
"""Run actions if desired state is 'started'."""
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ from distutils.version import LooseVersion
|
|||
from ansible.module_utils._text import to_bytes, to_native
|
||||
|
||||
from ansible_collections.containers.podman.plugins.module_utils.podman.common import lower_keys
|
||||
from ansible_collections.containers.podman.plugins.module_utils.podman.common import generate_systemd
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
|
|
@ -28,6 +29,7 @@ ARGUMENTS_SPEC_POD = dict(
|
|||
dns=dict(type='list', elements='str', required=False),
|
||||
dns_opt=dict(type='list', elements='str', required=False),
|
||||
dns_search=dict(type='list', elements='str', required=False),
|
||||
generate_systemd=dict(type='dict', default={}),
|
||||
hostname=dict(type='str', required=False),
|
||||
infra=dict(type='bool', required=False),
|
||||
infra_conmon_pidfile=dict(type='str', required=False),
|
||||
|
|
@ -162,7 +164,7 @@ class PodmanPodModuleParams:
|
|||
def addparam_label(self, c):
|
||||
for label in self.params['label'].items():
|
||||
c += ['--label', b'='.join(
|
||||
[to_bytes(l, errors='surrogate_or_strict') for l in label])]
|
||||
[to_bytes(i, errors='surrogate_or_strict') for i in label])]
|
||||
return c
|
||||
|
||||
def addparam_label_file(self, c):
|
||||
|
|
@ -644,6 +646,8 @@ class PodmanPodManager:
|
|||
self.results.update({'diff': self.pod.diff})
|
||||
if self.module.params['debug'] or self.module_params['debug']:
|
||||
self.results.update({'podman_version': self.pod.version})
|
||||
self.results.update(
|
||||
{'podman_systemd': generate_systemd(self.module, self.module_params, self.name)})
|
||||
|
||||
def execute(self):
|
||||
"""Execute the desired action according to map of actions & states."""
|
||||
|
|
|
|||
|
|
@ -299,7 +299,8 @@ options:
|
|||
suboptions:
|
||||
file:
|
||||
description:
|
||||
- Specify a path to the service file to be generated.
|
||||
- Specify a path to the directory where unit files will be generated.
|
||||
If it doesn't exist, the directory will be created.
|
||||
type: str
|
||||
required: false
|
||||
restart_policy:
|
||||
|
|
|
|||
|
|
@ -71,6 +71,66 @@ options:
|
|||
type: list
|
||||
elements: str
|
||||
required: false
|
||||
generate_systemd:
|
||||
description:
|
||||
- Generate systemd unit file for container.
|
||||
type: dict
|
||||
default: {}
|
||||
suboptions:
|
||||
file:
|
||||
description:
|
||||
- Specify a path to the directory where unit files will be generated.
|
||||
If it doesn't exist, the directory will be created.
|
||||
type: str
|
||||
required: false
|
||||
restart_policy:
|
||||
description:
|
||||
- Specify a restart policy for the service. The restart-policy must be one of
|
||||
"no", "on-success", "on-failure", "on-abnormal", "on-watchdog", "on-abort", or "always".
|
||||
The default policy is "on-failure".
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- 'no'
|
||||
- 'on-success'
|
||||
- 'on-failure'
|
||||
- 'on-abnormal'
|
||||
- 'on-watchdog'
|
||||
- 'on-abort'
|
||||
- 'always'
|
||||
time:
|
||||
description:
|
||||
- Override the default stop timeout for the container with the given value.
|
||||
type: int
|
||||
required: false
|
||||
no_header:
|
||||
description:
|
||||
- Do not generate the header including meta data such as the Podman version and the timestamp.
|
||||
From podman version 3.1.0.
|
||||
type: bool
|
||||
default: false
|
||||
names:
|
||||
description:
|
||||
- Use names of the containers for the start, stop, and description in the unit file.
|
||||
Default is true.
|
||||
type: bool
|
||||
default: true
|
||||
container_prefix:
|
||||
description:
|
||||
- Set the systemd unit name prefix for containers. The default is "container".
|
||||
type: str
|
||||
required: false
|
||||
pod_prefix:
|
||||
description:
|
||||
- Set the systemd unit name prefix for pods. The default is "pod".
|
||||
type: str
|
||||
required: false
|
||||
separator:
|
||||
description:
|
||||
- Set the systemd unit name separator between the name/id of a
|
||||
container/pod and the prefix. The default is "-" (dash).
|
||||
type: str
|
||||
required: false
|
||||
hostname:
|
||||
description:
|
||||
- Set a hostname to the pod
|
||||
|
|
|
|||
|
|
@ -533,8 +533,8 @@
|
|||
assert:
|
||||
that:
|
||||
- idem4 is changed
|
||||
- idem4.podman_systemd.name != ''
|
||||
- idem4.podman_systemd.text != ''
|
||||
- idem4.podman_systemd.keys() | list | length > 0
|
||||
- idem4.podman_systemd.values() | list | length > 0
|
||||
|
||||
- name: Run container with systemd generation parameters
|
||||
containers.podman.podman_container:
|
||||
|
|
@ -553,14 +553,14 @@
|
|||
container_prefix: contain
|
||||
register: system1
|
||||
|
||||
- name: Check that container is recreated when changed
|
||||
- name: Check that container has correct systemd output
|
||||
assert:
|
||||
that:
|
||||
- system1.podman_systemd.name == 'containzzzzcontainer1'
|
||||
- system1.podman_systemd.text != ''
|
||||
- "'stop -t 120 container1' in system1.podman_systemd.text"
|
||||
- "'Restart=always' in system1.podman_systemd.text"
|
||||
- "'autogenerated by Podman' not in system1.podman_systemd.text"
|
||||
- system1.podman_systemd.keys() | list | first == 'containzzzzcontainer1'
|
||||
- system1.podman_systemd.values() | list | length > 0
|
||||
- "'stop -t 120 container1' in system1.podman_systemd.values() | list | first"
|
||||
- "'Restart=always' in system1.podman_systemd.values() | list | first"
|
||||
- "'autogenerated by Podman' not in system1.podman_systemd.values() | list | first"
|
||||
|
||||
always:
|
||||
|
||||
|
|
|
|||
|
|
@ -639,6 +639,50 @@
|
|||
that:
|
||||
- pod35_info is not changed
|
||||
|
||||
- name: Start pod2 with default settings
|
||||
containers.podman.podman_pod:
|
||||
name: pod2
|
||||
state: created
|
||||
register: pod36_info
|
||||
|
||||
- name: Run container1 in pod
|
||||
containers.podman.podman_container:
|
||||
name: container1
|
||||
image: alpine
|
||||
command: top
|
||||
pod: pod2
|
||||
state: started
|
||||
|
||||
- name: Run container2 in pod
|
||||
containers.podman.podman_container:
|
||||
name: container2
|
||||
image: alpine
|
||||
command: top
|
||||
pod: pod2
|
||||
state: started
|
||||
|
||||
- name: Start pod2
|
||||
containers.podman.podman_pod:
|
||||
name: pod2
|
||||
state: started
|
||||
generate_systemd:
|
||||
file: /tmp/dir1
|
||||
restart_policy: always
|
||||
time: 120
|
||||
no_header: true
|
||||
names: true
|
||||
pod_prefix: poditto
|
||||
container_prefix: ainer
|
||||
register: system1
|
||||
|
||||
- name: Check that all settings from systemd are correct
|
||||
assert:
|
||||
that:
|
||||
- system1.podman_systemd.keys() | list | length == 3
|
||||
- "'stop -t 120 ' in system1.podman_systemd['poditto-pod2']"
|
||||
- "'Restart=always' in system1.podman_systemd['poditto-pod2']"
|
||||
- "'autogenerated by Podman' not in system1.podman_systemd['poditto-pod2']"
|
||||
|
||||
always:
|
||||
|
||||
- name: Delete all pods leftovers from tests
|
||||
|
|
@ -649,6 +693,14 @@
|
|||
- "pod1"
|
||||
- "pod2"
|
||||
|
||||
- name: Delete all container leftovers from tests
|
||||
containers.podman.podman_container:
|
||||
name: "{{ item }}"
|
||||
state: absent
|
||||
loop:
|
||||
- "container1"
|
||||
- "container2"
|
||||
|
||||
- name: Test idempotency for root pods
|
||||
include_tasks: root-pod.yml
|
||||
vars:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue