From 323a1dcff837c4e40491fcb70050b82817764d94 Mon Sep 17 00:00:00 2001 From: Alexei Znamensky <103110+russoz@users.noreply.github.com> Date: Sun, 8 Oct 2023 23:03:31 +1300 Subject: [PATCH] snap: detect change by checking final state (#7340) * snap: detect change by checking final state * detect change in snap_status variable * add changelog frag --- changelogs/fragments/7340-snap-fix.yml | 2 ++ plugins/modules/snap.py | 37 ++++++++++++------------- tests/unit/plugins/modules/test_snap.py | 27 ++++++++++++++++++ 3 files changed, 47 insertions(+), 19 deletions(-) create mode 100644 changelogs/fragments/7340-snap-fix.yml diff --git a/changelogs/fragments/7340-snap-fix.yml b/changelogs/fragments/7340-snap-fix.yml new file mode 100644 index 0000000000..a929964869 --- /dev/null +++ b/changelogs/fragments/7340-snap-fix.yml @@ -0,0 +1,2 @@ +bugfixes: + - snap - change the change detection mechanism from "parsing installation" to "comparing end state with initial state" (https://github.com/ansible-collections/community.general/pull/7340, https://github.com/ansible-collections/community.general/issues/7265). diff --git a/plugins/modules/snap.py b/plugins/modules/snap.py index 0a0aadef94..fd16764802 100644 --- a/plugins/modules/snap.py +++ b/plugins/modules/snap.py @@ -183,7 +183,6 @@ class Snap(StateModuleHelper): __disable_re = re.compile(r'(?:\S+\s+){5}(?P\S+)') __set_param_re = re.compile(r'(?P\S+:)?(?P\S+)\s*=\s*(?P.+)') __list_re = re.compile(r'^(?P\S+)\s+\S+\s+\S+\s+(?P\S+)') - __install_re = re.compile(r'(?P\S+)\s.+\s(installed|refreshed)') module = dict( argument_spec={ 'name': dict(type='list', elements='str', required=True), @@ -209,14 +208,24 @@ class Snap(StateModuleHelper): # if state=present there might be file names passed in 'name', in # which case they must be converted to their actual snap names, which # is done using the names_from_snaps() method calling 'snap info'. + self.vars.set("snapinfo_run_info", [], output=(self.verbosity >= 4)) + self.vars.set("status_run_info", [], output=(self.verbosity >= 4)) + self.vars.set("status_out", None, output=(self.verbosity >= 4)) + self.vars.set("run_info", [], output=(self.verbosity >= 4)) + if self.vars.state == "present": - self.vars.set("snapinfo_run_info", [], output=(self.verbosity >= 4)) self.vars.set("snap_names", self.names_from_snaps(self.vars.name)) status_var = "snap_names" else: status_var = "name" - self.vars.set("snap_status", self.snap_status(self.vars[status_var], self.vars.channel), output=False) - self.vars.set("snap_status_map", dict(zip(self.vars.name, self.vars.snap_status)), output=False) + self.vars.set("status_var", status_var, output=False) + self.vars.set("snap_status", self.snap_status(self.vars[self.vars.status_var], self.vars.channel), output=False, change=True) + self.vars.set("snap_status_map", dict(zip(self.vars.name, self.vars.snap_status)), output=False, change=True) + + def __quit_module__(self): + self.vars.snap_status = self.snap_status(self.vars[self.vars.status_var], self.vars.channel) + if self.vars.channel is None: + self.vars.channel = "stable" def _run_multiple_commands(self, commands, actionable_names, bundle=True, refresh=False): results_cmd = [] @@ -252,10 +261,6 @@ class Snap(StateModuleHelper): results_run_info, ) - def __quit_module__(self): - if self.vars.channel is None: - self.vars.channel = "stable" - def convert_json_subtree_to_map(self, json_subtree, prefix=None): option_map = {} @@ -350,9 +355,8 @@ class Snap(StateModuleHelper): list_out = out.split('\n')[1:] list_out = [self.__list_re.match(x) for x in list_out] list_out = [(m.group('name'), m.group('channel')) for m in list_out if m] - if self.verbosity >= 4: - self.vars.status_out = list_out - self.vars.status_run_info = ctx.run_info + self.vars.status_out = list_out + self.vars.status_run_info = ctx.run_info return [_status_check(n, channel, list_out) for n in snap_name] @@ -383,14 +387,10 @@ class Snap(StateModuleHelper): self.vars.cmd, rc, out, err, run_info = self._run_multiple_commands(params, actionable_snaps, bundle=False, refresh=refresh) else: self.vars.cmd, rc, out, err, run_info = self._run_multiple_commands(params, actionable_snaps, refresh=refresh) - if self.verbosity >= 4: - self.vars.run_info = run_info + self.vars.run_info = run_info if rc == 0: - match_install2 = [self.__install_re.match(line) for line in out.split('\n')] - match_install = [m.group('name') in actionable_snaps for m in match_install2 if m] - if len(match_install) == len(actionable_snaps): - return + return classic_snap_pattern = re.compile(r'^error: This revision of snap "(?P\w+)"' r' was published using classic confinement') @@ -480,8 +480,7 @@ class Snap(StateModuleHelper): if self.check_mode: return self.vars.cmd, rc, out, err, run_info = self._run_multiple_commands(params, actionable_snaps) - if self.verbosity >= 4: - self.vars.run_info = run_info + self.vars.run_info = run_info if rc == 0: return msg = "Ooops! Snap operation failed while executing '{cmd}', please examine logs and " \ diff --git a/tests/unit/plugins/modules/test_snap.py b/tests/unit/plugins/modules/test_snap.py index 8f31828604..480f637b6d 100644 --- a/tests/unit/plugins/modules/test_snap.py +++ b/tests/unit/plugins/modules/test_snap.py @@ -402,6 +402,19 @@ TEST_CASES = [ out="hello-world (12345/stable) v12345 from Canonical** installed\n", err="", ), + RunCmdCall( + command=['/testbin/snap', 'list'], + environ={'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False}, + rc=0, + out=( + "Name Version Rev Tracking Publisher Notes" + "core20 20220826 1623 latest/stable canonical** base" + "lxd 5.6-794016a 23680 latest/stable/… canonical** -" + "hello-world 5.6-794016a 23680 latest/stable/… canonical** -" + "snapd 2.57.4 17336 latest/stable canonical** snapd" + ""), + err="", + ), ] ), ModuleTestCase( @@ -438,6 +451,20 @@ TEST_CASES = [ out=issue_6803_kubectl_out, err="", ), + RunCmdCall( + command=['/testbin/snap', 'list'], + environ={'environ_update': {'LANGUAGE': 'C', 'LC_ALL': 'C'}, 'check_rc': False}, + rc=0, + out=( + "Name Version Rev Tracking Publisher Notes" + "core20 20220826 1623 latest/stable canonical** base" + "lxd 5.6-794016a 23680 latest/stable/… canonical** -" + "microk8s 5.6-794016a 23680 latest/stable/… canonical** -" + "kubectl 5.6-794016a 23680 latest/stable/… canonical** -" + "snapd 2.57.4 17336 latest/stable canonical** snapd" + ""), + err="", + ), ] ), ]