From 56acd4356fcd88186f8f6766ae072258012706ad Mon Sep 17 00:00:00 2001 From: Alexei Znamensky <103110+russoz@users.noreply.github.com> Date: Thu, 8 Jul 2021 17:20:01 +1200 Subject: [PATCH] MH - dicts and lists change-tracking is fixed (#2951) * dicts and lists change-tracking is fixed * added changelog fragment * fixed sanity check --- .../fragments/2951-mh-vars-deepcopy.yml | 2 ++ plugins/module_utils/mh/mixins/vars.py | 6 ++-- .../module_utils/test_module_helper.py | 28 +++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/2951-mh-vars-deepcopy.yml diff --git a/changelogs/fragments/2951-mh-vars-deepcopy.yml b/changelogs/fragments/2951-mh-vars-deepcopy.yml new file mode 100644 index 0000000000..339cca3aa7 --- /dev/null +++ b/changelogs/fragments/2951-mh-vars-deepcopy.yml @@ -0,0 +1,2 @@ +bugfixes: + - module_helper module utils - fixed change-tracking for dictionaries and lists (https://github.com/ansible-collections/community.general/pull/2951). diff --git a/plugins/module_utils/mh/mixins/vars.py b/plugins/module_utils/mh/mixins/vars.py index 7c936e04ac..a11110ed60 100644 --- a/plugins/module_utils/mh/mixins/vars.py +++ b/plugins/module_utils/mh/mixins/vars.py @@ -6,6 +6,8 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type +import copy + class VarMeta(object): NOTHING = object() @@ -30,11 +32,11 @@ class VarMeta(object): if fact is not None: self.fact = fact if initial_value is not self.NOTHING: - self.initial_value = initial_value + self.initial_value = copy.deepcopy(initial_value) def set_value(self, value): if not self.init: - self.initial_value = value + self.initial_value = copy.deepcopy(value) self.init = True self.value = value return self diff --git a/tests/unit/plugins/module_utils/test_module_helper.py b/tests/unit/plugins/module_utils/test_module_helper.py index 6452784182..f40a0f10ee 100644 --- a/tests/unit/plugins/module_utils/test_module_helper.py +++ b/tests/unit/plugins/module_utils/test_module_helper.py @@ -151,17 +151,45 @@ def test_vardict(): assert vd.meta('a').diff is False assert vd.meta('a').change is False vd['b'] = 456 + assert vd.meta('b').output is True + assert vd.meta('b').diff is False + assert vd.meta('b').change is False vd.set_meta('a', diff=True, change=True) vd.set_meta('b', diff=True, output=False) vd['c'] = 789 + assert vd.has_changed('c') is False vd['a'] = 'new_a' + assert vd.has_changed('a') is True vd['c'] = 'new_c' + assert vd.has_changed('c') is False + vd['b'] = 'new_b' + assert vd.has_changed('b') is False assert vd.a == 'new_a' assert vd.c == 'new_c' assert vd.output() == {'a': 'new_a', 'c': 'new_c'} assert vd.diff() == {'before': {'a': 123}, 'after': {'a': 'new_a'}}, "diff={0}".format(vd.diff()) +def test_variable_meta_change(): + vd = VarDict() + vd.set('a', 123, change=True) + vd.set('b', [4, 5, 6], change=True) + vd.set('c', {'m': 7, 'n': 8, 'o': 9}, change=True) + vd.set('d', {'a1': {'a11': 33, 'a12': 34}}, change=True) + + vd.a = 1234 + assert vd.has_changed('a') is True + vd.b.append(7) + assert vd.b == [4, 5, 6, 7] + assert vd.has_changed('b') + vd.c.update({'p': 10}) + assert vd.c == {'m': 7, 'n': 8, 'o': 9, 'p': 10} + assert vd.has_changed('c') + vd.d['a1'].update({'a13': 35}) + assert vd.d == {'a1': {'a11': 33, 'a12': 34, 'a13': 35}} + assert vd.has_changed('d') + + class MockMH(object): changed = None