Idempotency for podman_container
Introduce partial idepmpotency for running podman_container - Replace all options by their defaults it they're not set - Force lower case on all podman inspection data - Add a class with methods for every parameter to check its value and compare it with module argument - Add check_mode support and podman_actions Change-Id: I1ae93dff1e10a1a696bb171996a75a0db6c34fa3
This commit is contained in:
parent
cb41764f05
commit
1212544a28
@ -23,6 +23,8 @@ __metaclass__ = type
|
||||
import json
|
||||
import yaml
|
||||
|
||||
from packaging import version
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, env_fallback
|
||||
from ansible.module_utils._text import to_bytes, to_native
|
||||
|
||||
@ -101,7 +103,7 @@ options:
|
||||
(Not available for remote commands) You can also override the default
|
||||
path of the authentication file by setting the ``REGISTRY_AUTH_FILE``
|
||||
environment variable. ``export REGISTRY_AUTH_FILE=path``
|
||||
type: str
|
||||
type: path
|
||||
blkio_weight:
|
||||
description:
|
||||
- Block IO weight (relative weight) accepts a weight value between 10 and
|
||||
@ -128,7 +130,22 @@ options:
|
||||
If the path is not absolute, the path is considered to be relative to
|
||||
the cgroups path of the init process. Cgroups will be created if they
|
||||
do not already exist.
|
||||
type: path
|
||||
cgroupns:
|
||||
description:
|
||||
- Path to cgroups under which the cgroup for the container will be
|
||||
created.
|
||||
type: str
|
||||
cgroups:
|
||||
description:
|
||||
- Determines whether the container will create CGroups.
|
||||
Valid values are enabled and disabled, which the default being enabled.
|
||||
The disabled option will force the container to not create CGroups,
|
||||
and thus conflicts with CGroup options cgroupns and cgroup-parent.
|
||||
type: str
|
||||
choices:
|
||||
- default
|
||||
- disabled
|
||||
cidfile:
|
||||
description:
|
||||
- Write the container ID to the file
|
||||
@ -154,9 +171,17 @@ options:
|
||||
description:
|
||||
- Limit the CPU real-time period in microseconds
|
||||
type: int
|
||||
cpu_rt_period:
|
||||
description:
|
||||
- Limit the CPU real-time period in microseconds.
|
||||
Limit the container's Real Time CPU usage. This flag tell the kernel to
|
||||
restrict the container's Real Time CPU usage to the period you specify.
|
||||
type: int
|
||||
cpu_rt_runtime:
|
||||
description:
|
||||
- Limit the CPU real-time runtime in microseconds
|
||||
- Limit the CPU real-time runtime in microseconds.
|
||||
This flag tells the kernel to limit the amount of time in a given CPU
|
||||
period Real Time tasks may consume.
|
||||
type: int
|
||||
cpu_shares:
|
||||
description:
|
||||
@ -180,6 +205,11 @@ options:
|
||||
- Run container in detach mode
|
||||
type: bool
|
||||
default: True
|
||||
debug:
|
||||
description:
|
||||
- Return additional information which can be helpful for investigations.
|
||||
type: bool
|
||||
default: False
|
||||
detach_keys:
|
||||
description:
|
||||
- Override the key sequence for detaching a container. Format is a single
|
||||
@ -190,27 +220,28 @@ options:
|
||||
- Add a host device to the container.
|
||||
The format is <device-on-host>[:<device-on-container>][:<permissions>]
|
||||
(e.g. device /dev/sdc:/dev/xvdc:rwm)
|
||||
type: str
|
||||
type: list
|
||||
elements: str
|
||||
device_read_bps:
|
||||
description:
|
||||
- Limit read rate (bytes per second) from a device
|
||||
(e.g. device-read-bps /dev/sda:1mb)
|
||||
type: str
|
||||
type: list
|
||||
device_read_iops:
|
||||
description:
|
||||
- Limit read rate (IO per second) from a device
|
||||
(e.g. device-read-iops /dev/sda:1000)
|
||||
type: str
|
||||
type: list
|
||||
device_write_bps:
|
||||
description:
|
||||
- Limit write rate (bytes per second) to a device
|
||||
(e.g. device-write-bps /dev/sda:1mb)
|
||||
type: str
|
||||
type: list
|
||||
device_write_iops:
|
||||
description:
|
||||
- Limit write rate (IO per second) to a device
|
||||
(e.g. device-write-iops /dev/sda:1000)
|
||||
type: str
|
||||
type: list
|
||||
dns:
|
||||
description:
|
||||
- Set custom DNS servers
|
||||
@ -240,6 +271,11 @@ options:
|
||||
description:
|
||||
- Read in a line delimited file of environment variables
|
||||
type: path
|
||||
env_host:
|
||||
description:
|
||||
- Use all current host environment variables in container.
|
||||
Defaults to false.
|
||||
type: bool
|
||||
etc_hosts:
|
||||
description:
|
||||
- Dict of host-to-IP mappings, where each host name is a key in the
|
||||
@ -271,7 +307,7 @@ options:
|
||||
group_add:
|
||||
description:
|
||||
- Add additional groups to run as
|
||||
type: str
|
||||
type: list
|
||||
healthcheck:
|
||||
description:
|
||||
- Set or alter a healthcheck command for a container.
|
||||
@ -356,6 +392,7 @@ options:
|
||||
description:
|
||||
- Kernel memory limit
|
||||
(format <number>[<unit>], where unit = b, k, m or g)
|
||||
Note - idempotency is supported for integers only.
|
||||
type: str
|
||||
label:
|
||||
description:
|
||||
@ -385,10 +422,12 @@ options:
|
||||
memory:
|
||||
description:
|
||||
- Memory limit (format 10k, where unit = b, k, m or g)
|
||||
Note - idempotency is supported for integers only.
|
||||
type: str
|
||||
memory_reservation:
|
||||
description:
|
||||
- Memory soft limit (format 100m, where unit = b, k, m or g)
|
||||
Note - idempotency is supported for integers only.
|
||||
type: str
|
||||
memory_swap:
|
||||
description:
|
||||
@ -396,6 +435,7 @@ options:
|
||||
(--memory) flag.
|
||||
The swap LIMIT should always be larger than -m (--memory) value.
|
||||
By default, the swap LIMIT will be set to double the value of --memory
|
||||
Note - idempotency is supported for integers only.
|
||||
type: str
|
||||
memory_swappiness:
|
||||
description:
|
||||
@ -419,7 +459,8 @@ options:
|
||||
* ns:<path> path to a network namespace to join
|
||||
* slirp4netns use slirp4netns to create a user network stack.
|
||||
This is the default for rootless containers
|
||||
type: str
|
||||
type: list
|
||||
elements: str
|
||||
aliases:
|
||||
- net
|
||||
no_hosts:
|
||||
@ -512,7 +553,8 @@ options:
|
||||
security_opt:
|
||||
description:
|
||||
- Security Options. For example security_opt "seccomp=unconfined"
|
||||
type: str
|
||||
type: list
|
||||
elements: str
|
||||
shm_size:
|
||||
description:
|
||||
- Size of /dev/shm. The format is <number><unit>. number must be greater
|
||||
@ -530,7 +572,7 @@ options:
|
||||
stop_signal:
|
||||
description:
|
||||
- Signal to stop a container. Default is SIGTERM.
|
||||
type: str
|
||||
type: int
|
||||
stop_timeout:
|
||||
description:
|
||||
- Timeout (in seconds) to stop a container. Default is 10.
|
||||
@ -813,9 +855,12 @@ class PodmanModuleParams:
|
||||
params {dict} -- dictionary of module parameters
|
||||
|
||||
"""
|
||||
def __init__(self, action, params):
|
||||
|
||||
def __init__(self, action, params, podman_version, module):
|
||||
self.params = params
|
||||
self.action = action
|
||||
self.podman_version = podman_version
|
||||
self.module = module
|
||||
|
||||
def construct_command_from_params(self):
|
||||
"""Create a podman command from given module parameters.
|
||||
@ -853,19 +898,26 @@ class PodmanModuleParams:
|
||||
cmd = ['rm', '-f', self.params['name']]
|
||||
return [to_bytes(i, errors='surrogate_or_strict') for i in cmd]
|
||||
|
||||
def addparam_detach(self, c):
|
||||
return c + ['--detach=%s' % self.params['detach']]
|
||||
|
||||
def addparam_etc_hosts(self, c):
|
||||
for host_ip in self.params['etc_hosts'].items():
|
||||
c += ['--add-host', ':'.join(host_ip)]
|
||||
return c
|
||||
def check_version(self, param, minv=None, maxv=None):
|
||||
if minv and version.parse(minv) > version.parse(
|
||||
self.podman_version):
|
||||
self.module.fail_json(msg="Parameter %s is supported from podman "
|
||||
"version %s only! Current version is %s" % (
|
||||
param, minv, self.podman_version))
|
||||
if maxv and version.parse(maxv) < version.parse(
|
||||
self.podman_version):
|
||||
self.module.fail_json(msg="Parameter %s is supported till podman "
|
||||
"version %s only! Current version is %s" % (
|
||||
param, minv, self.podman_version))
|
||||
|
||||
def addparam_annotation(self, c):
|
||||
for annotate in self.params['annotation'].items():
|
||||
c += ['--annotation', '='.join(annotate)]
|
||||
return c
|
||||
|
||||
def addparam_authfile(self, c):
|
||||
return c + ['--authfile', self.params['authfile']]
|
||||
|
||||
def addparam_blkio_weight(self, c):
|
||||
return c + ['--blkio-weight', self.params['blkio_weight']]
|
||||
|
||||
@ -884,6 +936,14 @@ class PodmanModuleParams:
|
||||
c += ['--cap-drop', cap_drop]
|
||||
return c
|
||||
|
||||
def addparam_cgroups(self, c):
|
||||
self.check_version('--cgroups', minv='1.6.0')
|
||||
return c + ['--cgroups=%s' % self.params['cgroups']]
|
||||
|
||||
def addparam_cgroupns(self, c):
|
||||
self.check_version('--cgroupns', minv='1.6.2')
|
||||
return c + ['--cgroupns=%s' % self.params['cgroupns']]
|
||||
|
||||
def addparam_cgroup_parent(self, c):
|
||||
return c + ['--cgroup-parent', self.params['cgroup_parent']]
|
||||
|
||||
@ -896,6 +956,9 @@ class PodmanModuleParams:
|
||||
def addparam_cpu_period(self, c):
|
||||
return c + ['--cpu-period', self.params['cpu_period']]
|
||||
|
||||
def addparam_cpu_rt_period(self, c):
|
||||
return c + ['--cpu-rt-period', self.params['cpu_rt_period']]
|
||||
|
||||
def addparam_cpu_rt_runtime(self, c):
|
||||
return c + ['--cpu-rt-runtime', self.params['cpu_rt_runtime']]
|
||||
|
||||
@ -911,23 +974,36 @@ class PodmanModuleParams:
|
||||
def addparam_cpuset_mems(self, c):
|
||||
return c + ['--cpuset-mems', self.params['cpuset_mems']]
|
||||
|
||||
def addparam_detach(self, c):
|
||||
return c + ['--detach=%s' % self.params['detach']]
|
||||
|
||||
def addparam_detach_keys(self, c):
|
||||
return c + ['--detach-keys', self.params['detach_keys']]
|
||||
|
||||
def addparam_device(self, c):
|
||||
return c + ['--device', self.params['device']]
|
||||
for dev in self.params['device']:
|
||||
c += ['--device', dev]
|
||||
return c
|
||||
|
||||
def addparam_device_read_bps(self, c):
|
||||
return c + ['--device-read-bps', self.params['device_read_bps']]
|
||||
for dev in self.params['device_read_bps']:
|
||||
c += ['--device-read-bps', dev]
|
||||
return c
|
||||
|
||||
def addparam_device_read_iops(self, c):
|
||||
return c + ['--device-read-iops', self.params['device_read_iops']]
|
||||
for dev in self.params['device_read_iops']:
|
||||
c += ['--device-read-iops', dev]
|
||||
return c
|
||||
|
||||
def addparam_device_write_bps(self, c):
|
||||
return c + ['--device-write-bps', self.params['device_write_bps']]
|
||||
for dev in self.params['device_write_bps']:
|
||||
c += ['--device-write-bps', dev]
|
||||
return c
|
||||
|
||||
def addparam_device_write_iops(self, c):
|
||||
return c + ['--device-write-iops', self.params['device_write_iops']]
|
||||
for dev in self.params['device_write_iops']:
|
||||
c += ['--device-write-iops', dev]
|
||||
return c
|
||||
|
||||
def addparam_dns(self, c):
|
||||
return c + ['--dns', ','.join(self.params['dns'])]
|
||||
@ -951,6 +1027,15 @@ class PodmanModuleParams:
|
||||
def addparam_env_file(self, c):
|
||||
return c + ['--env-file', self.params['env_file']]
|
||||
|
||||
def addparam_env_host(self, c):
|
||||
self.check_version('--env-host', minv='1.5.0')
|
||||
return c + ['--env-host=%s' % self.params['env_host']]
|
||||
|
||||
def addparam_etc_hosts(self, c):
|
||||
for host_ip in self.params['etc_hosts'].items():
|
||||
c += ['--add-host', ':'.join(host_ip)]
|
||||
return c
|
||||
|
||||
def addparam_expose(self, c):
|
||||
for exp in self.params['expose']:
|
||||
c += ['--expose', exp]
|
||||
@ -960,7 +1045,9 @@ class PodmanModuleParams:
|
||||
return c + ['--gidmap', self.params['gidmap']]
|
||||
|
||||
def addparam_group_add(self, c):
|
||||
return c + ['--group-add', self.params['group_add']]
|
||||
for g in self.params['group_add']:
|
||||
c += ['--group-add', g]
|
||||
return c
|
||||
|
||||
def addparam_healthcheck(self, c):
|
||||
return c + ['--healthcheck', self.params['healthcheck']]
|
||||
@ -1010,7 +1097,8 @@ class PodmanModuleParams:
|
||||
|
||||
def addparam_label(self, c):
|
||||
for label in self.params['label'].items():
|
||||
c += ['--label', '='.join(label)]
|
||||
c += ['--label', b'='.join([to_bytes(l, errors='surrogate_or_strict')
|
||||
for l in label])]
|
||||
return c
|
||||
|
||||
def addparam_label_file(self, c):
|
||||
@ -1038,7 +1126,7 @@ class PodmanModuleParams:
|
||||
return c + ['--mount', self.params['mount']]
|
||||
|
||||
def addparam_network(self, c):
|
||||
return c + ['--network', self.params['network']]
|
||||
return c + ['--network', ",".join(self.params['network'])]
|
||||
|
||||
def addparam_no_hosts(self, c):
|
||||
return c + ['--no-hosts=%s' % self.params['no_hosts']]
|
||||
@ -1085,7 +1173,9 @@ class PodmanModuleParams:
|
||||
return c + ['--rootfs=%s' % self.params['rootfs']]
|
||||
|
||||
def addparam_security_opt(self, c):
|
||||
return c + ['--security-opt', self.params['security_opt']]
|
||||
for secopt in self.params['security_opt']:
|
||||
c += ['--security-opt', secopt]
|
||||
return c
|
||||
|
||||
def addparam_shm_size(self, c):
|
||||
return c + ['--shm-size', self.params['shm_size']]
|
||||
@ -1161,6 +1251,507 @@ class PodmanModuleParams:
|
||||
return c + self.params['cmd_args']
|
||||
|
||||
|
||||
class PodmanDefaults:
|
||||
def __init__(self, module, podman_version):
|
||||
self.module = module
|
||||
self.version = podman_version
|
||||
self.defaults = {
|
||||
"annotation": [
|
||||
"io.container.manager",
|
||||
"io.kubernetes.cri-o.containertype",
|
||||
"io.kubernetes.cri-o.created",
|
||||
"io.kubernetes.cri-o.tty",
|
||||
"io.podman.annotations.autoremove",
|
||||
"io.podman.annotations.init",
|
||||
"io.podman.annotations.privileged",
|
||||
"io.podman.annotations.publish-all",
|
||||
"org.opencontainers.image.stopsignal",
|
||||
],
|
||||
"blkio_weight": 0,
|
||||
"cap_add": ['cap_audit_write',
|
||||
'cap_chown',
|
||||
'cap_dac_override',
|
||||
'cap_fowner',
|
||||
'cap_fsetid',
|
||||
'cap_kill',
|
||||
'cap_mknod',
|
||||
'cap_net_bind_service',
|
||||
'cap_net_raw',
|
||||
'cap_setfcap',
|
||||
'cap_setgid',
|
||||
'cap_setpcap',
|
||||
'cap_setuid',
|
||||
'cap_sys_chroot'],
|
||||
"cgroups": "default",
|
||||
"cgroup_parent": "",
|
||||
"cidfile": "",
|
||||
"cpus": 0.0,
|
||||
"cpu_shares": 0,
|
||||
"cpu_quota": 0,
|
||||
"cpu_period": 0,
|
||||
"cpu_rt_runtime": 0,
|
||||
"cpu_rt_period": 0,
|
||||
"cpuset_cpus": "",
|
||||
"cpuset_mems": "",
|
||||
"detach": True,
|
||||
"device": [],
|
||||
"env": [
|
||||
"path",
|
||||
"term",
|
||||
"hostname",
|
||||
"container",
|
||||
"home"
|
||||
],
|
||||
"env_host": False,
|
||||
"etc_hosts": [],
|
||||
"group_add": [],
|
||||
"ipc": "",
|
||||
"kernelmemory": "0",
|
||||
"log_driver": "k8s-file",
|
||||
"memory": "0",
|
||||
"memory_swap": "0",
|
||||
"memory_reservation": "0",
|
||||
# "memory_swappiness": -1,
|
||||
"no_hosts": False,
|
||||
"oom_score_adj": 0,
|
||||
"pid": "",
|
||||
"privileged": False,
|
||||
"rm": False,
|
||||
"security_opt": [],
|
||||
"stop_signal": 15,
|
||||
"tty": False,
|
||||
"user": "",
|
||||
"uts": "",
|
||||
"volume": [],
|
||||
"workdir": "/",
|
||||
}
|
||||
|
||||
def default_dict(self):
|
||||
# make here any changes to self.defaults related to podman version
|
||||
if version.parse(self.version) < version.parse("1.6.0"):
|
||||
self.defaults["env"] = [
|
||||
"path",
|
||||
"term",
|
||||
"hostname",
|
||||
"container",
|
||||
]
|
||||
return self.defaults
|
||||
|
||||
|
||||
class PodmanContainerDiff:
|
||||
def __init__(self, module, info, podman_version):
|
||||
self.module = module
|
||||
self.version = podman_version
|
||||
self.default_dict = None
|
||||
self.info = json.loads(json.dumps(info).lower())
|
||||
self.params = self.defaultize()
|
||||
self.diff = {'before': {}, 'after': {}}
|
||||
self.non_idempotent = {
|
||||
'env_file',
|
||||
'env_host',
|
||||
'stop_timeout',
|
||||
"network", # Issue in libpod
|
||||
"ulimit", # Defaults depend on user and platform, impossible to guess
|
||||
}
|
||||
self.all_caps = ['cap_audit_control',
|
||||
'cap_audit_read',
|
||||
'cap_audit_write',
|
||||
'cap_block_suspend',
|
||||
'cap_chown',
|
||||
'cap_dac_override',
|
||||
'cap_dac_read_search',
|
||||
'cap_fowner',
|
||||
'cap_fsetid',
|
||||
'cap_ipc_lock',
|
||||
'cap_ipc_owner',
|
||||
'cap_kill',
|
||||
'cap_lease',
|
||||
'cap_linux_immutable',
|
||||
'cap_mac_admin',
|
||||
'cap_mac_override',
|
||||
'cap_mknod',
|
||||
'cap_net_admin',
|
||||
'cap_net_bind_service',
|
||||
'cap_net_broadcast',
|
||||
'cap_net_raw',
|
||||
'cap_setfcap',
|
||||
'cap_setgid',
|
||||
'cap_setpcap',
|
||||
'cap_setuid',
|
||||
'cap_sys_admin',
|
||||
'cap_sys_boot',
|
||||
'cap_sys_chroot',
|
||||
'cap_sys_module',
|
||||
'cap_sys_nice',
|
||||
'cap_sys_pacct',
|
||||
'cap_sys_ptrace',
|
||||
'cap_sys_rawio',
|
||||
'cap_sys_resource',
|
||||
'cap_sys_time',
|
||||
'cap_sys_tty_config',
|
||||
'cap_syslog',
|
||||
'cap_wake_alarm']
|
||||
|
||||
def defaultize(self):
|
||||
params_with_defaults = {}
|
||||
self.default_dict = PodmanDefaults(
|
||||
self.module, self.version).default_dict()
|
||||
for p in self.module.params:
|
||||
if self.module.params[p] is None and p in self.default_dict:
|
||||
params_with_defaults[p] = self.default_dict[p]
|
||||
else:
|
||||
params_with_defaults[p] = self.module.params[p]
|
||||
return params_with_defaults
|
||||
|
||||
def _diff_update_and_compare(self, param_name, before, after):
|
||||
if before != after:
|
||||
self.diff['before'].update({param_name: before})
|
||||
self.diff['after'].update({param_name: after})
|
||||
return True
|
||||
return False
|
||||
|
||||
# def diffparam_annotation(self):
|
||||
# before = self.info['config']['annotations']
|
||||
# after = before.copy()
|
||||
# if (self.params['annotation'] and self.params['annotation'] != self.default_dict['annotation']):
|
||||
# after.update(self.params['annotation'])
|
||||
# for key in list(after):
|
||||
# if (key not in self.params['annotation'] and key not in self.default_dict['annotation']):
|
||||
# del after[key]
|
||||
# return self._diff_update_and_compare('annotation', before, after)
|
||||
|
||||
def diffparam_env_host(self):
|
||||
# It's impossible to get from inspest, recreate it if not default
|
||||
before = False
|
||||
after = self.params['env_host']
|
||||
return self._diff_update_and_compare('env_host', before, after)
|
||||
|
||||
def diffparam_blkio_weight(self):
|
||||
before = self.info['hostconfig']['blkioweight']
|
||||
after = self.params['blkio_weight']
|
||||
return self._diff_update_and_compare('blkio_weight', before, after)
|
||||
|
||||
def diffparam_blkio_weight_device(self):
|
||||
before = self.info['hostconfig']['blkioweightdevice']
|
||||
if before == [] and self.module.params['blkio_weight_device'] is None:
|
||||
after = []
|
||||
else:
|
||||
after = self.params['blkio_weight_device']
|
||||
return self._diff_update_and_compare('blkio_weight_device', before, after)
|
||||
|
||||
def diffparam_cap_add(self):
|
||||
before = self.info['effectivecaps']
|
||||
after = self.default_dict['cap_add']
|
||||
if self.module.params['cap_add'] is not None:
|
||||
after += ["cap_" + i.lower()
|
||||
for i in self.module.params['cap_add']]
|
||||
if self.params['privileged']:
|
||||
after = self.all_caps
|
||||
before, after = sorted(list(set(before))), sorted(list(set(after)))
|
||||
return self._diff_update_and_compare('cap_add', before, after)
|
||||
|
||||
def diffparam_cap_drop(self):
|
||||
before = self.info['effectivecaps']
|
||||
after = self.default_dict['cap_add']
|
||||
if self.module.params['cap_drop'] is not None:
|
||||
for c in ["cap_" + i.lower() for i in self.module.params['cap_drop']]:
|
||||
if c in after:
|
||||
after.remove(c)
|
||||
if self.params['privileged']:
|
||||
after = self.all_caps
|
||||
before, after = sorted(list(set(before))), sorted(list(set(after)))
|
||||
return self._diff_update_and_compare('cap_add', before, after)
|
||||
|
||||
def diffparam_cgroup_parent(self):
|
||||
before = self.info['hostconfig']['cgroupparent']
|
||||
after = self.params['cgroup_parent']
|
||||
return self._diff_update_and_compare('cgroup_parent', before, after)
|
||||
|
||||
def diffparam_cgroups(self):
|
||||
# Cgroups output is not supported in all versions
|
||||
if 'cgroups' in self.info['hostconfig']:
|
||||
before = self.info['hostconfig']['cgroups']
|
||||
after = self.params['cgroups']
|
||||
return self._diff_update_and_compare('cgroups', before, after)
|
||||
return False
|
||||
|
||||
def diffparam_cidfile(self):
|
||||
before = self.info['hostconfig']['containeridfile']
|
||||
after = self.params['cidfile']
|
||||
return self._diff_update_and_compare('cidfile', before, after)
|
||||
|
||||
def diffparam_command(self):
|
||||
before = self.info['config']['cmd']
|
||||
after = self.params['command']
|
||||
if isinstance(after, str):
|
||||
after = after.split()
|
||||
return self._diff_update_and_compare('command', before, after)
|
||||
|
||||
def diffparam_conmon_pidfile(self):
|
||||
before = self.info['conmonpidfile']
|
||||
if self.module.params['conmon_pidfile'] is None:
|
||||
after = before
|
||||
else:
|
||||
after = self.params['conmon_pidfile']
|
||||
return self._diff_update_and_compare('conmon_pidfile', before, after)
|
||||
|
||||
def diffparam_cpu_period(self):
|
||||
before = self.info['hostconfig']['cpuperiod']
|
||||
after = self.params['cpu_period']
|
||||
return self._diff_update_and_compare('cpu_period', before, after)
|
||||
|
||||
def diffparam_cpu_rt_period(self):
|
||||
before = self.info['hostconfig']['cpurealtimeperiod']
|
||||
after = self.params['cpu_rt_period']
|
||||
return self._diff_update_and_compare('cpu_rt_period', before, after)
|
||||
|
||||
def diffparam_cpu_rt_runtime(self):
|
||||
before = self.info['hostconfig']['cpurealtimeruntime']
|
||||
after = self.params['cpu_rt_runtime']
|
||||
return self._diff_update_and_compare('cpu_rt_runtime', before, after)
|
||||
|
||||
def diffparam_cpu_shares(self):
|
||||
before = self.info['hostconfig']['cpushares']
|
||||
after = self.params['cpu_shares']
|
||||
return self._diff_update_and_compare('cpu_shares', before, after)
|
||||
|
||||
def diffparam_cpus(self):
|
||||
before = int(self.info['hostconfig']['nanocpus']) / 1000000000
|
||||
after = self.params['cpus']
|
||||
return self._diff_update_and_compare('cpus', before, after)
|
||||
|
||||
def diffparam_cpuset_cpus(self):
|
||||
before = self.info['hostconfig']['cpusetcpus']
|
||||
after = self.params['cpuset_cpus']
|
||||
return self._diff_update_and_compare('cpuset_cpus', before, after)
|
||||
|
||||
def diffparam_cpuset_mems(self):
|
||||
before = self.info['hostconfig']['cpusetmems']
|
||||
after = self.params['cpuset_mems']
|
||||
return self._diff_update_and_compare('cpuset_mems', before, after)
|
||||
|
||||
def diffparam_device(self):
|
||||
before = [":".join([i['pathonhost'], i['pathincontainer']])
|
||||
for i in self.info['hostconfig']['devices']]
|
||||
after = [":".join(i.split(":")[:2]) for i in self.params['device']]
|
||||
before, after = sorted(list(set(before))), sorted(list(set(after)))
|
||||
return self._diff_update_and_compare('devices', before, after)
|
||||
|
||||
def diffparam_device_read_bps(self):
|
||||
before = self.info['hostconfig']['blkiodevicereadbps'] or []
|
||||
before = ["%s:%s" % (i['path'], i['rate']) for i in before]
|
||||
after = self.params['device_read_bps'] or []
|
||||
before, after = sorted(list(set(before))), sorted(list(set(after)))
|
||||
return self._diff_update_and_compare('device_read_bps', before, after)
|
||||
|
||||
def diffparam_device_read_iops(self):
|
||||
before = self.info['hostconfig']['blkiodevicereadiops'] or []
|
||||
before = ["%s:%s" % (i['path'], i['rate']) for i in before]
|
||||
after = self.params['device_read_iops'] or []
|
||||
before, after = sorted(list(set(before))), sorted(list(set(after)))
|
||||
return self._diff_update_and_compare('device_read_iops', before, after)
|
||||
|
||||
def diffparam_device_write_bps(self):
|
||||
before = self.info['hostconfig']['blkiodevicewritebps'] or []
|
||||
before = ["%s:%s" % (i['path'], i['rate']) for i in before]
|
||||
after = self.params['device_write_bps'] or []
|
||||
before, after = sorted(list(set(before))), sorted(list(set(after)))
|
||||
return self._diff_update_and_compare('device_write_bps', before, after)
|
||||
|
||||
def diffparam_device_write_iops(self):
|
||||
before = self.info['hostconfig']['blkiodevicewriteiops'] or []
|
||||
before = ["%s:%s" % (i['path'], i['rate']) for i in before]
|
||||
after = self.params['device_write_iops'] or []
|
||||
before, after = sorted(list(set(before))), sorted(list(set(after)))
|
||||
return self._diff_update_and_compare('device_write_iops', before, after)
|
||||
|
||||
# Limited idempotency, it can't guess default values
|
||||
def diffparam_env(self):
|
||||
keys = [i.split("=")[0] for i in self.info['config']['env']]
|
||||
if self.module.params['env'] is None:
|
||||
if sorted(keys) == sorted(self.default_dict['env']):
|
||||
before = after = self.info['config']['env']
|
||||
else:
|
||||
before = self.info['config']['env']
|
||||
after = ["=".join([i, "default"]) for i in self.default_dict['env']]
|
||||
return self._diff_update_and_compare('env', before, after)
|
||||
before = {i.split("=")[0]: i.split("=")[1] for i in self.info['config']['env']}
|
||||
after = {}
|
||||
for key in self.default_dict['env']:
|
||||
after[key] = before[key]
|
||||
for d_key in self.module.params['env']:
|
||||
after[d_key.lower()] = self.module.params['env'][d_key].lower()
|
||||
return self._diff_update_and_compare('env', before, after)
|
||||
|
||||
def diffparam_etc_hosts(self):
|
||||
if self.info['hostconfig']['extrahosts']:
|
||||
before = dict([i.split(":") for i in self.info['hostconfig']['extrahosts']])
|
||||
else:
|
||||
before = []
|
||||
after = self.params['etc_hosts']
|
||||
return self._diff_update_and_compare('etc_hosts', before, after)
|
||||
|
||||
def diffparam_group_add(self):
|
||||
before = self.info['hostconfig']['groupadd']
|
||||
after = self.params['group_add']
|
||||
return self._diff_update_and_compare('group_add', before, after)
|
||||
|
||||
# Because of hostname is random generated, this parameter has partial idempotency only.
|
||||
def diffparam_hostname(self):
|
||||
before = self.info['config']['hostname']
|
||||
after = self.params['hostname'] or before
|
||||
return self._diff_update_and_compare('hostname', before, after)
|
||||
|
||||
def diffparam_image(self):
|
||||
before = self.info['config']['image'].replace(
|
||||
"docker.io/library/", "").replace(
|
||||
"docker.io/", "").replace(
|
||||
":latest", "")
|
||||
after = self.params['image']
|
||||
return self._diff_update_and_compare('image', before, after)
|
||||
|
||||
def diffparam_ipc(self):
|
||||
before = self.info['hostconfig']['ipcmode']
|
||||
after = self.params['ipc']
|
||||
return self._diff_update_and_compare('ipc', before, after)
|
||||
|
||||
def diffparam_label(self):
|
||||
before = self.info['config']['labels']
|
||||
after = self.params['label'] if not self.params['label'] else {
|
||||
k: str(v) for k, v in self.params['label'].items()
|
||||
}
|
||||
return self._diff_update_and_compare('label', before, after)
|
||||
|
||||
def diffparam_log_driver(self):
|
||||
before = self.info['hostconfig']['logconfig']['type']
|
||||
after = self.params['log_driver']
|
||||
return self._diff_update_and_compare('log_driver', before, after)
|
||||
|
||||
# Parameter has limited idempotency, unable to guess the default log_path
|
||||
def diffparam_log_opt(self):
|
||||
before = self.info['logpath']
|
||||
if self.module.params['log_opt'] in [None, '']:
|
||||
after = before
|
||||
else:
|
||||
after = self.params['log_opt'].split("=")[1]
|
||||
return self._diff_update_and_compare('log_opt', before, after)
|
||||
|
||||
def diffparam_memory(self):
|
||||
before = str(self.info['hostconfig']['memory'])
|
||||
after = self.params['memory']
|
||||
return self._diff_update_and_compare('memory', before, after)
|
||||
|
||||
def diffparam_memory_swap(self):
|
||||
# By default it's twice memory parameter
|
||||
before = str(self.info['hostconfig']['memoryswap'])
|
||||
after = self.params['memory_swap']
|
||||
if (self.module.params['memory_swap'] is None and
|
||||
self.params['memory'] != 0 and
|
||||
self.params['memory'].isdigit()):
|
||||
after = str(int(self.params['memory']) * 2)
|
||||
return self._diff_update_and_compare('memory_swap', before, after)
|
||||
|
||||
def diffparam_memory_reservation(self):
|
||||
before = str(self.info['hostconfig']['memoryreservation'])
|
||||
after = self.params['memory_reservation']
|
||||
return self._diff_update_and_compare('memory_reservation', before, after)
|
||||
|
||||
def diffparam_no_hosts(self):
|
||||
before = not bool(self.info['hostspath'])
|
||||
after = self.params['no_hosts']
|
||||
return self._diff_update_and_compare('no_hosts', before, after)
|
||||
|
||||
def diffparam_oom_score_adj(self):
|
||||
before = self.info['hostconfig']['oomscoreadj']
|
||||
after = self.params['oom_score_adj']
|
||||
return self._diff_update_and_compare('oom_score_adj', before, after)
|
||||
|
||||
def diffparam_privileged(self):
|
||||
before = self.info['hostconfig']['privileged']
|
||||
after = self.params['privileged']
|
||||
return self._diff_update_and_compare('privileged', before, after)
|
||||
|
||||
def diffparam_pid(self):
|
||||
before = self.info['hostconfig']['pidmode']
|
||||
after = self.params['pid']
|
||||
return self._diff_update_and_compare('pid', before, after)
|
||||
|
||||
def diffparam_rm(self):
|
||||
before = self.info['hostconfig']['autoremove']
|
||||
after = self.params['rm']
|
||||
return self._diff_update_and_compare('rm', before, after)
|
||||
|
||||
def diffparam_security_opt(self):
|
||||
before = self.info['hostconfig']['securityopt']
|
||||
after = self.params['security_opt']
|
||||
before, after = sorted(list(set(before))), sorted(list(set(after)))
|
||||
return self._diff_update_and_compare('security_opt', before, after)
|
||||
|
||||
def diffparam_stop_signal(self):
|
||||
before = self.info['config']['stopsignal']
|
||||
after = self.params['stop_signal']
|
||||
return self._diff_update_and_compare('stop_signal', before, after)
|
||||
|
||||
def diffparam_tty(self):
|
||||
before = self.info['config']['tty']
|
||||
after = self.params['tty']
|
||||
return self._diff_update_and_compare('tty', before, after)
|
||||
|
||||
def diffparam_user(self):
|
||||
before = self.info['config']['user']
|
||||
after = self.params['user']
|
||||
return self._diff_update_and_compare('user', before, after)
|
||||
|
||||
def diffparam_uts(self):
|
||||
before = self.info['hostconfig']['utsmode']
|
||||
after = self.params['uts']
|
||||
return self._diff_update_and_compare('uts', before, after)
|
||||
|
||||
def diffparam_volume(self):
|
||||
before = self.info['mounts']
|
||||
if before:
|
||||
volumes = []
|
||||
for m in before:
|
||||
if m['type'] == 'volume':
|
||||
volumes.append([m['name'], m['destination']])
|
||||
else:
|
||||
volumes.append([m['source'], m['destination']])
|
||||
before = [":".join(v) for v in volumes]
|
||||
# Ignore volumes option for idempotency
|
||||
after = [":".join(v.split(":")[:2]) for v in self.params['volume']]
|
||||
before, after = sorted(list(set(before))), sorted(list(set(after)))
|
||||
return self._diff_update_and_compare('volume', before, after)
|
||||
|
||||
def diffparam_volumes_from(self):
|
||||
before = self.info['hostconfig']['volumesfrom']
|
||||
after = self.params['volumes_from']
|
||||
return self._diff_update_and_compare('volumes_from', before, after)
|
||||
|
||||
def diffparam_workdir(self):
|
||||
before = self.info['config']['workingdir']
|
||||
after = self.params['workdir']
|
||||
return self._diff_update_and_compare('workdir', before, after)
|
||||
|
||||
def is_different(self):
|
||||
diff_func_list = [func for func in dir(self)
|
||||
if callable(getattr(self, func)) and func.startswith(
|
||||
"diffparam")]
|
||||
fail_fast = not bool(self.module._diff)
|
||||
different = False
|
||||
for func_name in diff_func_list:
|
||||
dff_func = getattr(self, func_name)
|
||||
if dff_func():
|
||||
if fail_fast:
|
||||
return True
|
||||
else:
|
||||
different = True
|
||||
# Check non idempotent parameters
|
||||
for p in self.non_idempotent:
|
||||
if self.module.params[p] is not None and self.module.params[p] not in [{}, [], '']:
|
||||
different = True
|
||||
return different
|
||||
|
||||
|
||||
def ensure_image_exists(module, image):
|
||||
"""If image is passed, ensure it exists, if not - pull it or fail.
|
||||
|
||||
@ -1205,6 +1796,9 @@ class PodmanContainer:
|
||||
self.name = name
|
||||
self.stdout, self.stderr = '', ''
|
||||
self.info = self.get_info()
|
||||
self.version = self._get_podman_version()
|
||||
self.diff = {}
|
||||
self.actions = []
|
||||
|
||||
@property
|
||||
def exists(self):
|
||||
@ -1214,9 +1808,17 @@ class PodmanContainer:
|
||||
@property
|
||||
def different(self):
|
||||
"""Check if container is different."""
|
||||
# TODO(sshnaidm): implement difference calculation between input vars
|
||||
# and current container to understand if we need to recreate it
|
||||
return True
|
||||
diffcheck = PodmanContainerDiff(self.module, self.info, self.version)
|
||||
is_different = diffcheck.is_different()
|
||||
diffs = diffcheck.diff
|
||||
if self.module._diff and is_different and diffs['before'] and diffs['after']:
|
||||
self.diff['before'] = "\n".join(
|
||||
["%s - %s" % (k, v) for k, v in sorted(
|
||||
diffs['before'].items())]) + "\n"
|
||||
self.diff['after'] = "\n".join(
|
||||
["%s - %s" % (k, v) for k, v in sorted(
|
||||
diffs['after'].items())]) + "\n"
|
||||
return is_different
|
||||
|
||||
@property
|
||||
def running(self):
|
||||
@ -1234,6 +1836,13 @@ class PodmanContainer:
|
||||
[self.module.params['executable'], b'container', b'inspect', self.name])
|
||||
return json.loads(out)[0] if rc == 0 else {}
|
||||
|
||||
def _get_podman_version(self):
|
||||
rc, out, err = self.module.run_command(
|
||||
[self.module.params['executable'], b'--version'])
|
||||
if rc != 0 or not out or "version" not in out:
|
||||
self.module.fail_json(msg="%s run failed!" % self.module.params['executable'])
|
||||
return out.split("version")[1].strip()
|
||||
|
||||
def _perform_action(self, action):
|
||||
"""Perform action with container.
|
||||
|
||||
@ -1241,19 +1850,25 @@ class PodmanContainer:
|
||||
action {str} -- action to perform - start, create, stop, run,
|
||||
delete
|
||||
"""
|
||||
b_command = PodmanModuleParams(action, self.module.params
|
||||
b_command = PodmanModuleParams(action,
|
||||
self.module.params,
|
||||
self.version,
|
||||
self.module,
|
||||
).construct_command_from_params()
|
||||
self.module.log("PODMAN-CONTAINER-DEBUG: " +
|
||||
"%s" % " ".join([to_native(i) for i in b_command]))
|
||||
rc, out, err = self.module.run_command(
|
||||
[self.module.params['executable'], b'container'] + b_command,
|
||||
expand_user_and_vars=False)
|
||||
self.stdout = out
|
||||
self.stderr = err
|
||||
if rc != 0:
|
||||
self.module.fail_json(
|
||||
msg="Can't %s container %s" % (action, self.name),
|
||||
stdout=out, stderr=err)
|
||||
full_cmd = " ".join([self.module.params['executable']] +
|
||||
[to_native(i) for i in b_command])
|
||||
self.module.log("PODMAN-CONTAINER-DEBUG: %s" % full_cmd)
|
||||
self.actions.append(full_cmd)
|
||||
if not self.module.check_mode:
|
||||
rc, out, err = self.module.run_command(
|
||||
[self.module.params['executable'], b'container'] + b_command,
|
||||
expand_user_and_vars=False)
|
||||
self.stdout = out
|
||||
self.stderr = err
|
||||
if rc != 0:
|
||||
self.module.fail_json(
|
||||
msg="Can't %s container %s" % (action, self.name),
|
||||
stdout=out, stderr=err)
|
||||
|
||||
def run(self):
|
||||
"""Run the container."""
|
||||
@ -1326,11 +1941,15 @@ class PodmanManager:
|
||||
changed {bool} -- whether any action was performed
|
||||
(default: {True})
|
||||
"""
|
||||
facts = self.container.get_info()
|
||||
facts = self.container.get_info() if changed else self.container.info
|
||||
out, err = self.container.stdout, self.container.stderr
|
||||
self.results.update({'changed': changed, 'container': facts,
|
||||
'ansible_facts': {'podman_container': facts}},
|
||||
stdout=out, stderr=err)
|
||||
'podman_actions': self.container.actions},
|
||||
stdout=out, stderr=err)
|
||||
if self.container.diff:
|
||||
self.results.update({'diff': self.container.diff})
|
||||
if self.module.params['debug']:
|
||||
self.results.update({'podman_version': self.container.version})
|
||||
self.module.exit_json(**self.results)
|
||||
|
||||
def make_started(self):
|
||||
@ -1347,7 +1966,7 @@ class PodmanManager:
|
||||
self.results['actions'].append('restarted %s' %
|
||||
self.container.name)
|
||||
self.update_container_result()
|
||||
self.module.exit_json(**self.results)
|
||||
self.update_container_result(changed=False)
|
||||
elif not self.container.exists:
|
||||
self.container.run()
|
||||
self.results['actions'].append('started %s' % self.container.name)
|
||||
@ -1387,7 +2006,7 @@ class PodmanManager:
|
||||
self.results['actions'].append('deleted %s' % self.container.name)
|
||||
self.results.update({'changed': True})
|
||||
self.results.update({'container': {},
|
||||
'ansible_facts': {'podman_container': {}}})
|
||||
'podman_actions': self.container.actions})
|
||||
self.module.exit_json(**self.results)
|
||||
|
||||
def execute(self):
|
||||
@ -1411,6 +2030,7 @@ def main():
|
||||
['no_hosts', 'etc_hosts'],
|
||||
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
# work on input vars
|
||||
if module.params['state'] in ['started', 'present'] and \
|
||||
|
@ -71,17 +71,11 @@
|
||||
assert:
|
||||
that:
|
||||
- image is changed
|
||||
- image.ansible_facts is defined
|
||||
- image.ansible_facts.podman_container is defined
|
||||
- image.ansible_facts.podman_container['State']['Running']
|
||||
- image.container is defined
|
||||
- image.container['State']['Running']
|
||||
- "'pulled image alpine:3.7' in image.actions"
|
||||
- "'started container' in image.actions"
|
||||
- image2 is changed
|
||||
- image2.ansible_facts is defined
|
||||
- image2.ansible_facts.podman_container is defined
|
||||
- image2.ansible_facts.podman_container['State']['Running']
|
||||
- image2.container is defined
|
||||
- image2.container['State']['Running']
|
||||
- "'pulled image alpine:3.7' not in image2.actions"
|
||||
@ -118,9 +112,8 @@
|
||||
assert:
|
||||
that:
|
||||
- recreated is changed
|
||||
- recreated.ansible_facts is defined
|
||||
- recreated.ansible_facts.podman_container is defined
|
||||
- recreated.ansible_facts.podman_container['State']['Running']
|
||||
- recreated.container is defined
|
||||
- recreated.container['State']['Running']
|
||||
- "'recreated container' in recreated.actions"
|
||||
fail_msg: Force recreate test failed!
|
||||
success_msg: Force recreate test passed!
|
||||
@ -141,14 +134,12 @@
|
||||
assert:
|
||||
that:
|
||||
- stopped is changed
|
||||
- stopped.ansible_facts is defined
|
||||
- stopped.ansible_facts.podman_container is defined
|
||||
- not stopped.ansible_facts.podman_container['State']['Running']
|
||||
- stopped.container is defined
|
||||
- not stopped.container['State']['Running']
|
||||
- "'stopped container' in stopped.actions"
|
||||
- stopped_again is not changed
|
||||
- stopped_again.ansible_facts is defined
|
||||
- stopped_again.ansible_facts.podman_container is defined
|
||||
- not stopped_again.ansible_facts.podman_container['State']['Running']
|
||||
- stopped_again.container is defined
|
||||
- not stopped_again.container['State']['Running']
|
||||
- stopped_again.actions == []
|
||||
fail_msg: Stopping container test failed!
|
||||
success_msg: Stopping container test passed!
|
||||
@ -169,14 +160,12 @@
|
||||
assert:
|
||||
that:
|
||||
- deleted is changed
|
||||
- deleted.ansible_facts is defined
|
||||
- deleted.ansible_facts.podman_container is defined
|
||||
- deleted.ansible_facts.podman_container == {}
|
||||
- deleted.container is defined
|
||||
- deleted.container == {}
|
||||
- "'deleted container' in deleted.actions"
|
||||
- deleted_again is not changed
|
||||
- deleted_again.ansible_facts is defined
|
||||
- deleted_again.ansible_facts.podman_container is defined
|
||||
- deleted_again.ansible_facts.podman_container == {}
|
||||
- deleted_again.container is defined
|
||||
- deleted_again.container == {}
|
||||
- deleted_again.actions == []
|
||||
fail_msg: Deleting stopped container test failed!
|
||||
success_msg: Deleting stopped container test passed!
|
||||
@ -193,10 +182,9 @@
|
||||
assert:
|
||||
that:
|
||||
- created is changed
|
||||
- created.ansible_facts is defined
|
||||
- created.ansible_facts.podman_container is defined
|
||||
- created.ansible_facts.podman_container != {}
|
||||
- not created.ansible_facts.podman_container['State']['Running']
|
||||
- created.container is defined
|
||||
- created.container != {}
|
||||
- not created.container['State']['Running']
|
||||
- "'created container' in created.actions"
|
||||
fail_msg: "Creating stopped container test failed!"
|
||||
success_msg: "Creating stopped container test passed!"
|
||||
@ -218,9 +206,6 @@
|
||||
assert:
|
||||
that:
|
||||
- started is changed
|
||||
- started.ansible_facts is defined
|
||||
- started.ansible_facts.podman_container is defined
|
||||
- started.ansible_facts.podman_container['State']['Running']
|
||||
- started.container is defined
|
||||
- started.container['State']['Running']
|
||||
- "'pulled image alpine:3.7' not in started.actions"
|
||||
@ -241,14 +226,12 @@
|
||||
assert:
|
||||
that:
|
||||
- deleted is changed
|
||||
- deleted.ansible_facts is defined
|
||||
- deleted.ansible_facts.podman_container is defined
|
||||
- deleted.ansible_facts.podman_container == {}
|
||||
- deleted.container is defined
|
||||
- deleted.container == {}
|
||||
- "'deleted container' in deleted.actions"
|
||||
- deleted_again is not changed
|
||||
- deleted_again.ansible_facts is defined
|
||||
- deleted_again.ansible_facts.podman_container is defined
|
||||
- deleted_again.ansible_facts.podman_container == {}
|
||||
- deleted_again.container is defined
|
||||
- deleted_again.container == {}
|
||||
- deleted_again.actions == []
|
||||
fail_msg: Deleting started container test failed!
|
||||
success_msg: Deleting started container test passed!
|
||||
@ -293,54 +276,112 @@
|
||||
assert:
|
||||
that:
|
||||
- test is changed
|
||||
- test.ansible_facts is defined
|
||||
- test.ansible_facts.podman_container is defined
|
||||
- test.ansible_facts.podman_container != {}
|
||||
- test.ansible_facts.podman_container['State']['Running']
|
||||
- test.container is defined
|
||||
- test.container != {}
|
||||
- test.container['State']['Running']
|
||||
# test capabilities
|
||||
- "'CAP_SYS_TIME' in test.ansible_facts.podman_container['BoundingCaps']"
|
||||
- "'CAP_NET_ADMIN' in test.ansible_facts.podman_container['BoundingCaps']"
|
||||
- "'CAP_SYS_TIME' in test.container['BoundingCaps']"
|
||||
- "'CAP_NET_ADMIN' in test.container['BoundingCaps']"
|
||||
# test annotations
|
||||
- test.ansible_facts.podman_container['Config']['Annotations']['this'] is defined
|
||||
- test.ansible_facts.podman_container['Config']['Annotations']['this'] == "annotation_value"
|
||||
- test.container['Config']['Annotations']['this'] is defined
|
||||
- test.container['Config']['Annotations']['this'] == "annotation_value"
|
||||
# test DNS
|
||||
- >-
|
||||
(test.ansible_facts.podman_container['HostConfig']['Dns'] is defined and
|
||||
test.ansible_facts.podman_container['HostConfig']['Dns'] == ['1.1.1.1', '8.8.4.4']) or
|
||||
(test.ansible_facts.podman_container['HostConfig']['DNS'] is defined and
|
||||
test.ansible_facts.podman_container['HostConfig']['DNS'] == ['1.1.1.1', '8.8.4.4'])
|
||||
(test.container['HostConfig']['Dns'] is defined and
|
||||
test.container['HostConfig']['Dns'] == ['1.1.1.1', '8.8.4.4']) or
|
||||
(test.container['HostConfig']['DNS'] is defined and
|
||||
test.container['HostConfig']['DNS'] == ['1.1.1.1', '8.8.4.4'])
|
||||
# test ports
|
||||
- test.ansible_facts.podman_container['NetworkSettings']['Ports']|length == 2
|
||||
- test.container['NetworkSettings']['Ports']|length == 2
|
||||
# test working dir
|
||||
- test.ansible_facts.podman_container['Config']['WorkingDir'] == "/bin"
|
||||
- test.container['Config']['WorkingDir'] == "/bin"
|
||||
# test dns search
|
||||
- >-
|
||||
(test.ansible_facts.podman_container['HostConfig']['DnsSearch'] is defined and
|
||||
test.ansible_facts.podman_container['HostConfig']['DnsSearch'] == ['example.com']) or
|
||||
(test.ansible_facts.podman_container['HostConfig']['DNSSearch'] is defined and
|
||||
test.ansible_facts.podman_container['HostConfig']['DNSSearch'] == ['example.com'])
|
||||
(test.container['HostConfig']['DnsSearch'] is defined and
|
||||
test.container['HostConfig']['DnsSearch'] == ['example.com']) or
|
||||
(test.container['HostConfig']['DNSSearch'] is defined and
|
||||
test.container['HostConfig']['DNSSearch'] == ['example.com'])
|
||||
# test environment variables
|
||||
- "'FOO=bar' in test.ansible_facts.podman_container['Config']['Env']"
|
||||
- "'BAR=foo' in test.ansible_facts.podman_container['Config']['Env']"
|
||||
- "'TEST=1' in test.ansible_facts.podman_container['Config']['Env']"
|
||||
- "'BOOL=False' in test.ansible_facts.podman_container['Config']['Env']"
|
||||
- "'FOO=bar' in test.container['Config']['Env']"
|
||||
- "'BAR=foo' in test.container['Config']['Env']"
|
||||
- "'TEST=1' in test.container['Config']['Env']"
|
||||
- "'BOOL=False' in test.container['Config']['Env']"
|
||||
# test labels
|
||||
- test.ansible_facts.podman_container['Config']['Labels'] | length == 2
|
||||
- test.ansible_facts.podman_container['Config']['Labels']['somelabel'] == "labelvalue"
|
||||
- test.ansible_facts.podman_container['Config']['Labels']['otheralbe'] == "othervalue"
|
||||
- test.container['Config']['Labels'] | length == 2
|
||||
- test.container['Config']['Labels']['somelabel'] == "labelvalue"
|
||||
- test.container['Config']['Labels']['otheralbe'] == "othervalue"
|
||||
# test mounts
|
||||
- >-
|
||||
(test.ansible_facts.podman_container['Mounts'][0]['Destination'] is defined and
|
||||
'/data' in test.ansible_facts.podman_container['Mounts'] | map(attribute='Destination') | list) or
|
||||
(test.ansible_facts.podman_container['Mounts'][0]['destination'] is defined and
|
||||
'/data' in test.ansible_facts.podman_container['Mounts'] | map(attribute='destination') | list)
|
||||
(test.container['Mounts'][0]['Destination'] is defined and
|
||||
'/data' in test.container['Mounts'] | map(attribute='Destination') | list) or
|
||||
(test.container['Mounts'][0]['destination'] is defined and
|
||||
'/data' in test.container['Mounts'] | map(attribute='destination') | list)
|
||||
- >-
|
||||
(test.ansible_facts.podman_container['Mounts'][0]['Source'] is defined and
|
||||
'/tmp' in test.ansible_facts.podman_container['Mounts'] | map(attribute='Source') | list) or
|
||||
(test.ansible_facts.podman_container['Mounts'][0]['source'] is defined and
|
||||
'/tmp' in test.ansible_facts.podman_container['Mounts'] | map(attribute='source') | list)
|
||||
(test.container['Mounts'][0]['Source'] is defined and
|
||||
'/tmp' in test.container['Mounts'] | map(attribute='Source') | list) or
|
||||
(test.container['Mounts'][0]['source'] is defined and
|
||||
'/tmp' in test.container['Mounts'] | map(attribute='source') | list)
|
||||
fail_msg: Parameters container test failed!
|
||||
success_msg: Parameters container test passed!
|
||||
|
||||
- name: Check basic idempotency of running container
|
||||
podman_container:
|
||||
name: testidem
|
||||
image: alpine
|
||||
state: present
|
||||
command: sleep 20m
|
||||
|
||||
- name: Check basic idempotency of running container - run it again
|
||||
podman_container:
|
||||
name: testidem
|
||||
image: alpine
|
||||
state: present
|
||||
command: sleep 20m
|
||||
register: idem
|
||||
|
||||
- name: Check that nothing was changed
|
||||
assert:
|
||||
that:
|
||||
- not idem.changed
|
||||
|
||||
- name: Run changed container (with tty enabled)
|
||||
podman_container:
|
||||
name: testidem
|
||||
image: alpine
|
||||
state: present
|
||||
command: sleep 20m
|
||||
tty: true
|
||||
register: idem1
|
||||
|
||||
- name: Check that container is recreated when changed
|
||||
assert:
|
||||
that:
|
||||
- idem1 is changed
|
||||
|
||||
- name: Run changed container without specifying an option, use defaults
|
||||
podman_container:
|
||||
name: testidem
|
||||
image: alpine
|
||||
state: present
|
||||
command: sleep 20m
|
||||
register: idem2
|
||||
|
||||
- name: Check that container is recreated when changed to default value
|
||||
assert:
|
||||
that:
|
||||
- idem2 is changed
|
||||
|
||||
- name: Remove container
|
||||
podman_container:
|
||||
name: testidem
|
||||
state: absent
|
||||
register: remove
|
||||
|
||||
- name: Check podman_actions
|
||||
assert:
|
||||
that:
|
||||
- "'podman rm -f testidem' in remove.podman_actions"
|
||||
|
||||
always:
|
||||
- name: Delete all container leftovers from tests
|
||||
podman_container:
|
||||
|
@ -16,7 +16,24 @@
|
||||
|
||||
- name: Prepare
|
||||
hosts: all
|
||||
gather_facts: true
|
||||
roles:
|
||||
- role: test_deps
|
||||
test_deps_extra_packages:
|
||||
- podman
|
||||
|
||||
post_tasks:
|
||||
- name: Check podman version
|
||||
command: podman version
|
||||
register: p_ver
|
||||
changed_when: false
|
||||
|
||||
- name: Print podman version
|
||||
debug:
|
||||
msg: |
|
||||
podman version:
|
||||
{{ p_ver.stdout }}
|
||||
|
||||
Testing with ansible {{ ansible_version.full }}
|
||||
with python {{ ansible_python_version }}
|
||||
on host {{ ansible_distribution }} {{ ansible_distribution_version }}
|
||||
|
Loading…
Reference in New Issue
Block a user