diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-18 05:52:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-18 05:52:22 +0000 |
commit | 38b7c80217c4e72b1d8988eb1e60bb6e77334114 (patch) | |
tree | 356e9fd3762877d07cde52d21e77070aeff7e789 /ansible_collections/containers/podman/plugins/module_utils | |
parent | Adding upstream version 7.7.0+dfsg. (diff) | |
download | ansible-38b7c80217c4e72b1d8988eb1e60bb6e77334114.tar.xz ansible-38b7c80217c4e72b1d8988eb1e60bb6e77334114.zip |
Adding upstream version 9.4.0+dfsg.upstream/9.4.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/containers/podman/plugins/module_utils')
3 files changed, 331 insertions, 58 deletions
diff --git a/ansible_collections/containers/podman/plugins/module_utils/podman/common.py b/ansible_collections/containers/podman/plugins/module_utils/podman/common.py index dba3aff65..cbb6b080e 100644 --- a/ansible_collections/containers/podman/plugins/module_utils/podman/common.py +++ b/ansible_collections/containers/podman/plugins/module_utils/podman/common.py @@ -19,6 +19,25 @@ except ImportError: ' < 2.11, you need to use Python < 3.12 with ' 'distutils.version present'), exc) +ARGUMENTS_OPTS_DICT = { + '--attach': ['--attach', '-a'], + '--cpu-shares': ['--cpu-shares', '-c'], + '--detach': ['--detach', '-d'], + '--env': ['--env', '-e'], + '--hostname': ['--hostname', '-h'], + '--interactive': ['--interactive', '-i'], + '--label': ['--label', '-l'], + '--memory': ['--memory', '-m'], + '--network': ['--network', '--net'], + '--publish': ['--publish', '-p'], + '--publish-all': ['--publish-all', '-P'], + '--quiet': ['--quiet', '-q'], + '--tty': ['--tty', '-t'], + '--user': ['--user', '-u'], + '--volume': ['--volume', '-v'], + '--workdir': ['--workdir', '-w'], +} + def run_podman_command(module, executable='podman', args=None, expected_rc=0, ignore_errors=False): if not isinstance(executable, list): @@ -50,8 +69,15 @@ def run_generate_systemd_command(module, module_params, name, version): command.extend([ '--restart-policy', sysconf['restart_policy']]) - if sysconf.get('time'): - command.extend(['--time', str(sysconf['time'])]) + if sysconf.get('restart_sec') is not None: + command.extend(['--restart-sec=%s' % sysconf['restart_sec']]) + if (sysconf.get('stop_timeout') is not None) or (sysconf.get('time') is not None): + # Select correct parameter name based on version + arg_name = 'stop-timeout' if gt4ver else 'time' + arg_value = sysconf.get('stop_timeout') if sysconf.get('stop_timeout') is not None else sysconf.get('time') + command.extend(['--%s=%s' % (arg_name, arg_value)]) + if sysconf.get('start_timeout') is not None: + command.extend(['--start-timeout=%s' % sysconf['start_timeout']]) if sysconf.get('no_header'): command.extend(['--no-header']) if sysconf.get('names', True): @@ -96,34 +122,103 @@ def run_generate_systemd_command(module, module_params, name, version): return rc, systemd, err +def compare_systemd_file_content(file_path, file_content): + if not os.path.exists(file_path): + # File does not exist, so all lines in file_content are different + return '', file_content + # Read the file + with open(file_path, 'r') as unit_file: + current_unit_file_content = unit_file.read() + + # Function to remove comments from file content + def remove_comments(content): + return "\n".join([line for line in content.splitlines() if not line.startswith('#')]) + + # Remove comments from both file contents before comparison + current_unit_file_content_nocmnt = remove_comments(current_unit_file_content) + unit_content_nocmnt = remove_comments(file_content) + if current_unit_file_content_nocmnt == unit_content_nocmnt: + return None + + # Get the different lines between the two contents + diff_in_file = [line + for line in unit_content_nocmnt.splitlines() + if line not in current_unit_file_content_nocmnt.splitlines()] + diff_in_string = [line + for line in current_unit_file_content_nocmnt.splitlines() + if line not in unit_content_nocmnt.splitlines()] + + return diff_in_string, diff_in_file + + def generate_systemd(module, module_params, name, version): - empty = {} + result = { + 'changed': False, + 'systemd': {}, + 'diff': {}, + } sysconf = module_params['generate_systemd'] rc, systemd, err = run_generate_systemd_command(module, module_params, name, version) if rc != 0: module.log( "PODMAN-CONTAINER-DEBUG: Error generating systemd: %s" % err) - return empty + if sysconf: + module.fail_json(msg="Error generating systemd: %s" % err) + return result else: try: data = json.loads(systemd) + result['systemd'] = data if sysconf.get('path'): full_path = os.path.expanduser(sysconf['path']) if not os.path.exists(full_path): os.makedirs(full_path) + result['changed'] = True if not os.path.isdir(full_path): module.fail_json("Path %s is not a directory! " "Can not save systemd unit files there!" % full_path) for file_name, file_content in data.items(): file_name += ".service" + if not os.path.exists(os.path.join(full_path, file_name)): + result['changed'] = True + if result['diff'].get('before') is None: + result['diff'] = {'before': {}, 'after': {}} + result['diff']['before'].update( + {'systemd_{file_name}.service'.format(file_name=file_name): ''}) + result['diff']['after'].update( + {'systemd_{file_name}.service'.format(file_name=file_name): file_content}) + + else: + diff_ = compare_systemd_file_content(os.path.join(full_path, file_name), file_content) + if diff_: + result['changed'] = True + if result['diff'].get('before') is None: + result['diff'] = {'before': {}, 'after': {}} + result['diff']['before'].update( + {'systemd_{file_name}.service'.format(file_name=file_name): "\n".join(diff_[0])}) + result['diff']['after'].update( + {'systemd_{file_name}.service'.format(file_name=file_name): "\n".join(diff_[1])}) with open(os.path.join(full_path, file_name), 'w') as f: f.write(file_content) - return data + diff_before = "\n".join( + ["{j} - {k}".format(j=j, k=k) + for j, k in result['diff'].get('before', {}).items() if 'PIDFile' not in k]).strip() + diff_after = "\n".join( + ["{j} - {k}".format(j=j, k=k) + for j, k in result['diff'].get('after', {}).items() if 'PIDFile' not in k]).strip() + if diff_before or diff_after: + result['diff']['before'] = diff_before + "\n" + result['diff']['after'] = diff_after + "\n" + else: + result['diff'] = {} + return result except Exception as e: module.log( "PODMAN-CONTAINER-DEBUG: Error writing systemd: %s" % e) - return empty + if sysconf: + module.fail_json(msg="Error writing systemd: %s" % e) + return result def delete_systemd(module, module_params, name, version): @@ -230,3 +325,15 @@ def normalize_signal(signal_name_or_number): if signal_name not in _signal_map: raise RuntimeError("Unknown signal '{0}'".format(signal_name_or_number)) return str(_signal_map[signal_name]) + + +def get_podman_version(module, fail=True): + executable = module.params['executable'] if module.params['executable'] else 'podman' + rc, out, err = module.run_command( + [executable, b'--version']) + if rc != 0 or not out or "version" not in out: + if fail: + module.fail_json(msg="'%s --version' run failed! Error: %s" % + (executable, err)) + return None + return out.split("version")[1].strip() diff --git a/ansible_collections/containers/podman/plugins/module_utils/podman/podman_container_lib.py b/ansible_collections/containers/podman/plugins/module_utils/podman/podman_container_lib.py index 1ba28f4c8..ff4c18629 100644 --- a/ansible_collections/containers/podman/plugins/module_utils/podman/podman_container_lib.py +++ b/ansible_collections/containers/podman/plugins/module_utils/podman/podman_container_lib.py @@ -9,6 +9,7 @@ from ansible_collections.containers.podman.plugins.module_utils.podman.common im from ansible_collections.containers.podman.plugins.module_utils.podman.common import generate_systemd from ansible_collections.containers.podman.plugins.module_utils.podman.common import delete_systemd from ansible_collections.containers.podman.plugins.module_utils.podman.common import normalize_signal +from ansible_collections.containers.podman.plugins.module_utils.podman.common import ARGUMENTS_OPTS_DICT __metaclass__ = type @@ -19,6 +20,7 @@ ARGUMENTS_SPEC_CONTAINER = dict( 'absent', 'present', 'stopped', 'started', 'created']), image=dict(type='str'), annotation=dict(type='dict'), + attach=dict(type='list', elements='str', choices=['stdout', 'stderr', 'stdin']), authfile=dict(type='path'), blkio_weight=dict(type='int'), blkio_weight_device=dict(type='dict'), @@ -32,12 +34,16 @@ ARGUMENTS_SPEC_CONTAINER = dict( conmon_pidfile=dict(type='path'), command=dict(type='raw'), cpu_period=dict(type='int'), + cpu_quota=dict(type='int'), cpu_rt_period=dict(type='int'), cpu_rt_runtime=dict(type='int'), cpu_shares=dict(type='int'), cpus=dict(type='str'), cpuset_cpus=dict(type='str'), cpuset_mems=dict(type='str'), + delete_depend=dict(type='bool'), + delete_time=dict(type='str'), + delete_volumes=dict(type='bool'), detach=dict(type='bool', default=True), debug=dict(type='bool', default=False), detach_keys=dict(type='str', no_log=False), @@ -51,13 +57,14 @@ ARGUMENTS_SPEC_CONTAINER = dict( dns_search=dict(type='str', aliases=['dns_search_domains']), entrypoint=dict(type='str'), env=dict(type='dict'), - env_file=dict(type='path'), + env_file=dict(type='list', elements='path', aliases=['env_files']), env_host=dict(type='bool'), etc_hosts=dict(type='dict', aliases=['add_hosts']), expose=dict(type='list', elements='str', aliases=[ 'exposed', 'exposed_ports']), force_restart=dict(type='bool', default=False, aliases=['restart']), + force_delete=dict(type='bool', default=True), generate_systemd=dict(type='dict', default={}), gidmap=dict(type='list', elements='str'), group_add=dict(type='list', elements='str', aliases=['groups']), @@ -66,6 +73,8 @@ ARGUMENTS_SPEC_CONTAINER = dict( healthcheck_retries=dict(type='int'), healthcheck_start_period=dict(type='str'), healthcheck_timeout=dict(type='str'), + healthcheck_failure_action=dict(type='str', choices=[ + 'none', 'kill', 'restart', 'stop']), hooks_dir=dict(type='list', elements='str'), hostname=dict(type='str'), http_proxy=dict(type='bool'), @@ -112,6 +121,7 @@ ARGUMENTS_SPEC_CONTAINER = dict( recreate=dict(type='bool', default=False), requires=dict(type='list', elements='str'), restart_policy=dict(type='str'), + restart_time=dict(type='str'), rm=dict(type='bool', aliases=['remove', 'auto_remove']), rootfs=dict(type='bool'), secrets=dict(type='list', elements='str', no_log=True), @@ -121,6 +131,7 @@ ARGUMENTS_SPEC_CONTAINER = dict( sig_proxy=dict(type='bool'), stop_signal=dict(type='int'), stop_timeout=dict(type='int'), + stop_time=dict(type='str'), subgidname=dict(type='str'), subuidname=dict(type='str'), sysctl=dict(type='dict'), @@ -227,12 +238,35 @@ class PodmanModuleParams: def start_stop_delete(self): + def complete_params(cmd): + if self.params['attach'] and self.action == 'start': + cmd.append('--attach') + if self.params['detach'] is False and self.action == 'start' and '--attach' not in cmd: + cmd.append('--attach') + if self.params['detach_keys'] and self.action == 'start': + cmd += ['--detach-keys', self.params['detach_keys']] + if self.params['sig_proxy'] and self.action == 'start': + cmd.append('--sig-proxy') + if self.params['stop_time'] and self.action == 'stop': + cmd += ['--time', self.params['stop_time']] + if self.params['restart_time'] and self.action == 'restart': + cmd += ['--time', self.params['restart_time']] + if self.params['delete_depend'] and self.action == 'delete': + cmd.append('--depend') + if self.params['delete_time'] and self.action == 'delete': + cmd += ['--time', self.params['delete_time']] + if self.params['delete_volumes'] and self.action == 'delete': + cmd.append('--volumes') + if self.params['force_delete'] and self.action == 'delete': + cmd.append('--force') + return cmd + if self.action in ['stop', 'start', 'restart']: - cmd = [self.action, self.params['name']] + cmd = complete_params([self.action]) + [self.params['name']] return [to_bytes(i, errors='surrogate_or_strict') for i in cmd] if self.action == 'delete': - cmd = ['rm', '-f', self.params['name']] + cmd = complete_params(['rm']) + [self.params['name']] return [to_bytes(i, errors='surrogate_or_strict') for i in cmd] def check_version(self, param, minv=None, maxv=None): @@ -252,6 +286,11 @@ class PodmanModuleParams: c += ['--annotation', '='.join(annotate)] return c + def addparam_attach(self, c): + for attach in self.params['attach']: + c += ['--attach=%s' % attach] + return c + def addparam_authfile(self, c): return c + ['--authfile', self.params['authfile']] @@ -293,6 +332,9 @@ class PodmanModuleParams: def addparam_cpu_period(self, c): return c + ['--cpu-period', self.params['cpu_period']] + def addparam_cpu_quota(self, c): + return c + ['--cpu-quota', self.params['cpu_quota']] + def addparam_cpu_rt_period(self, c): return c + ['--cpu-rt-period', self.params['cpu_rt_period']] @@ -312,6 +354,9 @@ class PodmanModuleParams: return c + ['--cpuset-mems', self.params['cpuset_mems']] def addparam_detach(self, c): + # Remove detach from create command and don't set if attach is true + if self.action == 'create' or self.params['attach']: + return c return c + ['--detach=%s' % self.params['detach']] def addparam_detach_keys(self, c): @@ -362,7 +407,9 @@ class PodmanModuleParams: return c def addparam_env_file(self, c): - return c + ['--env-file', self.params['env_file']] + for env_file in self.params['env_file']: + c += ['--env-file', env_file] + return c def addparam_env_host(self, c): self.check_version('--env-host', minv='1.5.0') @@ -407,6 +454,10 @@ class PodmanModuleParams: return c + ['--healthcheck-timeout', self.params['healthcheck_timeout']] + def addparam_healthcheck_failure_action(self, c): + return c + ['--health-on-failure', + self.params['healthcheck_failure_action']] + def addparam_hooks_dir(self, c): for hook_dir in self.params['hooks_dir']: c += ['--hooks-dir=%s' % hook_dir] @@ -722,6 +773,35 @@ class PodmanContainerDiff: params_with_defaults[p] = self.module_params[p] return params_with_defaults + def _createcommand(self, argument): + """Returns list of values for given argument from CreateCommand + from Podman container inspect output. + + Args: + argument (str): argument name + + Returns: + + all_values: list of values for given argument from createcommand + """ + if "createcommand" not in self.info["config"]: + return [] + cr_com = self.info["config"]["createcommand"] + argument_values = ARGUMENTS_OPTS_DICT.get(argument, [argument]) + all_values = [] + for arg in argument_values: + for ind, cr_opt in enumerate(cr_com): + if arg == cr_opt: + # This is a key=value argument + if not cr_com[ind + 1].startswith("-"): + all_values.append(cr_com[ind + 1]) + else: + # This is a false/true switching argument + return [True] + if cr_opt.startswith("%s=" % arg): + all_values.append(cr_opt.split("=", 1)[1]) + return all_values + def _diff_update_and_compare(self, param_name, before, after): if before != after: self.diff['before'].update({param_name: before}) @@ -737,7 +817,7 @@ class PodmanContainerDiff: 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 + # It's impossible to get from inspect, recreate it if not default before = False after = self.params['env_host'] return self._diff_update_and_compare('env_host', before, after) @@ -826,9 +906,16 @@ class PodmanContainerDiff: def diffparam_cpu_period(self): before = self.info['hostconfig']['cpuperiod'] - after = self.params['cpu_period'] + # if cpu_period left to default keep settings + after = self.params['cpu_period'] or before return self._diff_update_and_compare('cpu_period', before, after) + def diffparam_cpu_quota(self): + before = self.info['hostconfig']['cpuquota'] + # if cpu_quota left to default keep settings + after = self.params['cpu_quota'] or before + return self._diff_update_and_compare('cpu_quota', before, after) + def diffparam_cpu_rt_period(self): before = self.info['hostconfig']['cpurealtimeperiod'] after = self.params['cpu_rt_period'] @@ -845,8 +932,9 @@ class PodmanContainerDiff: 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'] + before = self.info['hostconfig']['nanocpus'] / 1000000000 + # if cpus left to default keep settings + after = float(self.params['cpus'] or before) return self._diff_update_and_compare('cpus', before, after) def diffparam_cpuset_cpus(self): @@ -863,16 +951,13 @@ class PodmanContainerDiff: before = [":".join([i['pathonhost'], i['pathincontainer']]) for i in self.info['hostconfig']['devices']] if not before and 'createcommand' in self.info['config']: - cr_com = self.info['config']['createcommand'] - if '--device' in cr_com: - before = [cr_com[k + 1].lower() - for k, i in enumerate(cr_com) if i == '--device'] + before = [i.lower() for i in self._createcommand('--device')] before = [":".join((i, i)) if len(i.split(":")) == 1 else i for i in before] after = [":".join(i.split(":")[:2]) for i in self.params['device']] after = [":".join((i, i)) if len(i.split(":")) == 1 else i for i in after] - after = [i.lower() for i in after] + before, after = [i.lower() for i in before], [i.lower() for i in after] before, after = sorted(list(set(before))), sorted(list(set(after))) return self._diff_update_and_compare('devices', before, after) @@ -931,15 +1016,23 @@ class PodmanContainerDiff: # Healthcheck is only defined in container config if a healthcheck # was configured; otherwise the config key isn't part of the config. def diffparam_healthcheck(self): + before = '' if 'healthcheck' in self.info['config']: # the "test" key is a list of 2 items where the first one is # "CMD-SHELL" and the second one is the actual healthcheck command. - before = self.info['config']['healthcheck']['test'][1] - else: - before = '' + if len(self.info['config']['healthcheck']['test']) > 1: + before = self.info['config']['healthcheck']['test'][1] after = self.params['healthcheck'] or before return self._diff_update_and_compare('healthcheck', before, after) + def diffparam_healthcheck_failure_action(self): + if 'healthcheckonfailureaction' in self.info['config']: + before = self.info['config']['healthcheckonfailureaction'] + else: + before = '' + after = self.params['healthcheck_failure_action'] or before + return self._diff_update_and_compare('healthcheckonfailureaction', before, after) + # Because of hostname is random generated, this parameter has partial idempotency only. def diffparam_hostname(self): before = self.info['config']['hostname'] @@ -1066,9 +1159,8 @@ class PodmanContainerDiff: if macs: before = macs[0] if not before and 'createcommand' in self.info['config']: - cr_com = self.info['config']['createcommand'] - if '--mac-address' in cr_com: - before = cr_com[cr_com.index('--mac-address') + 1].lower() + before = [i.lower() for i in self._createcommand('--mac-address')] + before = before[0] if before else '' if self.module_params['mac_address'] is not None: after = self.params['mac_address'] else: @@ -1084,11 +1176,10 @@ class PodmanContainerDiff: before = [] # Special case for options for slirp4netns rootless networking from v2 if net_mode_before == 'slirp4netns' and 'createcommand' in self.info['config']: - cr_com = self.info['config']['createcommand'] - if '--network' in cr_com: - cr_net = cr_com[cr_com.index('--network') + 1].lower() - if 'slirp4netns:' in cr_net: - before = [cr_net] + cr_net = [i.lower() for i in self._createcommand('--network')] + for cr_net_opt in cr_net: + if 'slirp4netns:' in cr_net_opt: + before = [cr_net_opt] after = self.params['network'] or [] # If container is in pod and no networks are provided if not self.module_params['network'] and self.params['pod']: @@ -1124,8 +1215,19 @@ class PodmanContainerDiff: return self._diff_update_and_compare('privileged', before, after) def diffparam_pid(self): + def get_container_id_by_name(name): + rc, podman_inspect_info, err = self.module.run_command( + [self.module.params["executable"], "inspect", name, "-f", "{{.Id}}"]) + if rc != 0: + return None + return podman_inspect_info.strip() + before = self.info['hostconfig']['pidmode'] after = self.params['pid'] + if after is not None and "container:" in after and "container:" in before: + if after.split(":")[1] == before.split(":")[1]: + return self._diff_update_and_compare('pid', before, after) + after = "container:" + get_container_id_by_name(after.split(":")[1]) return self._diff_update_and_compare('pid', before, after) # TODO(sshnaidm) Need to add port ranges support @@ -1150,7 +1252,7 @@ class PodmanContainerDiff: if image_ports: after += list(image_ports.keys()) after = [ - i.replace("/tcp", "").replace("[", "").replace("]", "") + i.replace("/tcp", "").replace("[", "").replace("]", "").replace("0.0.0.0:", "") for i in after] # No support for port ranges yet for ports in after: @@ -1166,7 +1268,15 @@ class PodmanContainerDiff: def diffparam_restart_policy(self): before = self.info['hostconfig']['restartpolicy']['name'] + before_max_count = int(self.info['hostconfig']['restartpolicy'].get('maximumretrycount', 0)) after = self.params['restart_policy'] or "" + if ':' in after: + after, after_max_count = after.rsplit(':', 1) + after_max_count = int(after_max_count) + else: + after_max_count = 0 + before = "%s:%i" % (before, before_max_count) + after = "%s:%i" % (after, after_max_count) return self._diff_update_and_compare('restart_policy', before, after) def diffparam_rm(self): @@ -1175,11 +1285,16 @@ class PodmanContainerDiff: return self._diff_update_and_compare('rm', before, after) def diffparam_security_opt(self): - before = self.info['hostconfig']['securityopt'] - # In rootful containers with apparmor there is a default security opt - before = [o for o in before if 'apparmor=containers-default' not in o] - after = self.params['security_opt'] - before, after = sorted(list(set(before))), sorted(list(set(after))) + unsorted_before = self.info['hostconfig']['securityopt'] + unsorted_after = self.params['security_opt'] + # In rootful containers with apparmor there is a profile, "container-default", + # which is already added by default + # Since SElinux labels are basically annotations, they are merged in a single list + # element by podman so we need to split them in a (sorted) list if we want to compare it + # to the list we provide to the module + before = sorted(item for element in unsorted_before for item in element.split(',') + if 'apparmor=container-default' not in item) + after = sorted(list(set(unsorted_after))) return self._diff_update_and_compare('security_opt', before, after) def diffparam_stop_signal(self): @@ -1206,11 +1321,7 @@ class PodmanContainerDiff: after = self.params['ulimit'] or [] # In case of latest podman if 'createcommand' in self.info['config']: - ulimits = [] - for k, c in enumerate(self.info['config']['createcommand']): - if c == '--ulimit': - ulimits.append(self.info['config']['createcommand'][k + 1]) - before = ulimits + before = self._createcommand('--ulimit') before, after = sorted(before), sorted(after) return self._diff_update_and_compare('ulimit', before, after) if after: @@ -1428,8 +1539,6 @@ class PodmanContainer: self.version, self.module, ).construct_command_from_params() - if action == 'create': - b_command.remove(b'--detach=True') full_cmd = " ".join([self.module_params['executable']] + [to_native(i) for i in b_command]) self.actions.append(full_cmd) @@ -1449,7 +1558,7 @@ class PodmanContainer: self.stderr = err if rc != 0: self.module.fail_json( - msg="Can't %s container %s" % (action, self.name), + msg="Container %s exited with code %s when %sed" % (self.name, rc, action), stdout=out, stderr=err) def run(self): @@ -1547,11 +1656,19 @@ class PodmanManager: self.results.update({'diff': self.container.diff}) if self.module.params['debug'] or self.module_params['debug']: self.results.update({'podman_version': self.container.version}) + sysd = generate_systemd(self.module, + self.module_params, + self.name, + self.container.version) + self.results['changed'] = changed or sysd['changed'] self.results.update( - {'podman_systemd': generate_systemd(self.module, - self.module_params, - self.name, - self.container.version)}) + {'podman_systemd': sysd['systemd']}) + if sysd['diff']: + if 'diff' not in self.results: + self.results.update({'diff': sysd['diff']}) + else: + self.results['diff']['before'] += sysd['diff']['before'] + self.results['diff']['after'] += sysd['diff']['after'] def make_started(self): """Run actions if desired state is 'started'.""" @@ -1601,7 +1718,8 @@ class PodmanManager: self.results['actions'].append('started %s' % self.container.name) self.update_container_result() return - elif self.container.stopped and self.container.different: + elif self.container.stopped and \ + (self.container.different or self.recreate): self.container.recreate_run() self.results['actions'].append('recreated %s' % self.container.name) diff --git a/ansible_collections/containers/podman/plugins/module_utils/podman/podman_pod_lib.py b/ansible_collections/containers/podman/plugins/module_utils/podman/podman_pod_lib.py index 0b4afc0bc..4106136e2 100644 --- a/ansible_collections/containers/podman/plugins/module_utils/podman/podman_pod_lib.py +++ b/ansible_collections/containers/podman/plugins/module_utils/podman/podman_pod_lib.py @@ -27,10 +27,15 @@ ARGUMENTS_SPEC_POD = dict( recreate=dict(type='bool', default=False), add_host=dict(type='list', required=False, elements='str'), cgroup_parent=dict(type='str', required=False), + blkio_weight=dict(type='str', required=False), + blkio_weight_device=dict(type='list', elements='str', required=False), cpus=dict(type='str', required=False), cpuset_cpus=dict(type='str', required=False), + cpuset_mems=dict(type='str', required=False), + cpu_shares=dict(type='str', required=False), device=dict(type='list', elements='str', required=False), device_read_bps=dict(type='list', elements='str', required=False), + device_write_bps=dict(type='list', elements='str', required=False), 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), @@ -46,6 +51,8 @@ ARGUMENTS_SPEC_POD = dict( label=dict(type='dict', required=False), label_file=dict(type='str', required=False), mac_address=dict(type='str', required=False), + memory=dict(type='str', required=False), + memory_swap=dict(type='str', required=False), name=dict(type='str', required=True), network=dict(type='list', elements='str', required=False), network_alias=dict(type='list', elements='str', required=False, @@ -135,25 +142,52 @@ class PodmanPodModuleParams: c += ['--add-host', g] return c + def addparam_blkio_weight(self, c): + self.check_version('--blkio-weight', minv='4.3.0') + return c + ['--blkio-weight', self.params['blkio_weight']] + + def addparam_blkio_weight_device(self, c): + self.check_version('--blkio-weight-device', minv='4.3.0') + for dev in self.params['blkio_weight_device']: + c += ['--blkio-weight-device', dev] + return c + def addparam_cgroup_parent(self, c): return c + ['--cgroup-parent', self.params['cgroup_parent']] def addparam_cpus(self, c): + self.check_version('--cpus', minv='4.2.0') return c + ['--cpus', self.params['cpus']] def addparam_cpuset_cpus(self, c): + self.check_version('--cpus', minv='4.2.0') return c + ['--cpuset-cpus', self.params['cpuset_cpus']] + def addparam_cpuset_mems(self, c): + self.check_version('--cpuset-mems', minv='4.3.0') + return c + ['--cpuset-mems', self.params['cpuset_mems']] + + def addparam_cpu_shares(self, c): + self.check_version('--cpu-shares', minv='4.3.0') + return c + ['--cpu-shares', self.params['cpu_shares']] + def addparam_device(self, c): for dev in self.params['device']: c += ['--device', dev] return c def addparam_device_read_bps(self, c): + self.check_version('--device-read-bps', minv='4.3.0') for dev in self.params['device_read_bps']: c += ['--device-read-bps', dev] return c + def addparam_device_write_bps(self, c): + self.check_version('--device-write-bps', minv='4.3.0') + for dev in self.params['device_write_bps']: + c += ['--device-write-bps', dev] + return c + def addparam_dns(self, c): for g in self.params['dns']: c += ['--dns', g] @@ -209,6 +243,14 @@ class PodmanPodModuleParams: def addparam_mac_address(self, c): return c + ['--mac-address', self.params['mac_address']] + def addparam_memory(self, c): + self.check_version('--memory', minv='4.2.0') + return c + ['--memory', self.params['memory']] + + def addparam_memory_swap(self, c): + self.check_version('--memory-swap', minv='4.3.0') + return c + ['--memory-swap', self.params['memory_swap']] + def addparam_name(self, c): return c + ['--name', self.params['name']] @@ -323,10 +365,8 @@ class PodmanPodDiff: return self._diff_update_and_compare('add_host', before, after) def diffparam_cgroup_parent(self): - if 'cgroupparent' in self.info: - before = self.info['cgroupparent'] - elif 'config' in self.info and self.info['config'].get('cgroupparent'): - before = self.info['config']['cgroupparent'] + before = (self.info.get('cgroupparent', '') + or self.info.get('hostconfig', {}).get('cgroupparent', '')) after = self.params['cgroup_parent'] or before return self._diff_update_and_compare('cgroup_parent', before, after) @@ -511,7 +551,7 @@ class PodmanPodDiff: # TODO: find out why on Ubuntu the 'net' is not present if 'net' not in before: after.remove('net') - if self.params["uidmap"] or self.params["gidmap"]: + if self.params["uidmap"] or self.params["gidmap"] or self.params["userns"]: after.append('user') before, after = sorted(list(set(before))), sorted(list(set(after))) @@ -759,11 +799,19 @@ 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}) + sysd = generate_systemd(self.module, + self.module_params, + self.name, + self.pod.version) + self.results['changed'] = changed or sysd['changed'] self.results.update( - {'podman_systemd': generate_systemd(self.module, - self.module_params, - self.name, - self.pod.version)}) + {'podman_systemd': sysd['systemd']}) + if sysd['diff']: + if 'diff' not in self.results: + self.results.update({'diff': sysd['diff']}) + else: + self.results['diff']['before'] += sysd['diff']['before'] + self.results['diff']['after'] += sysd['diff']['after'] def execute(self): """Execute the desired action according to map of actions & states.""" |