diff --git a/changelog/48609.changed b/changelog/48609.changed new file mode 100644 index 000000000000..92f1dc00f8e5 --- /dev/null +++ b/changelog/48609.changed @@ -0,0 +1 @@ +More intelligent diffing in changes of file.serialize state. diff --git a/salt/states/file.py b/salt/states/file.py index 838d8805c9f5..ece620799ac9 100644 --- a/salt/states/file.py +++ b/salt/states/file.py @@ -299,6 +299,7 @@ def run(): import salt.payload import salt.utils.data import salt.utils.dateutils +import salt.utils.dictdiffer import salt.utils.dictupdate import salt.utils.files import salt.utils.hashutils @@ -8024,6 +8025,7 @@ def serialize( salt.utils.data.repack_dictlist(deserializer_opts) ) + existing_data = None if merge_if_exists: if os.path.isfile(name): if deserializer_name not in __serializers__: @@ -8114,27 +8116,33 @@ def serialize( else: ret["result"] = True ret["comment"] = "The file {} is in the correct state".format(name) - return ret + else: + ret = __salt__["file.manage_file"]( + name=name, + sfn="", + ret=ret, + source=None, + source_sum={}, + user=user, + group=group, + mode=mode, + attrs=None, + saltenv=__env__, + backup=backup, + makedirs=makedirs, + template=None, + show_changes=show_changes, + encoding=encoding, + encoding_errors=encoding_errors, + contents=contents, + ) - return __salt__["file.manage_file"]( - name=name, - sfn="", - ret=ret, - source=None, - source_sum={}, - user=user, - group=group, - mode=mode, - attrs=None, - saltenv=__env__, - backup=backup, - makedirs=makedirs, - template=None, - show_changes=show_changes, - encoding=encoding, - encoding_errors=encoding_errors, - contents=contents, - ) + if isinstance(existing_data, dict) and isinstance(merged_data, dict): + ret["changes"]["diff"] = salt.utils.dictdiffer.recursive_diff( + existing_data, merged_data + ).diffs + + return ret def mknod(name, ntype, major=0, minor=0, user=None, group=None, mode="0600"): diff --git a/tests/integration/states/test_file.py b/tests/integration/states/test_file.py index fb56a9c4045c..542537f151e6 100644 --- a/tests/integration/states/test_file.py +++ b/tests/integration/states/test_file.py @@ -2052,6 +2052,12 @@ def test_serializer_deserializer_opts(self, name): ) ret = ret[next(iter(ret))] assert ret["result"], ret + assert "changes" in ret + assert "diff" in ret["changes"] + assert "foo" in ret["changes"]["diff"] + assert "abc" in ret["changes"]["diff"]["foo"] + assert "new" in ret["changes"]["diff"]["foo"]["abc"] + assert ret["changes"]["diff"]["foo"]["abc"]["new"], 123 with salt.utils.files.fopen(name) as fp_: serialized_data = salt.serializers.configparser.deserialize(fp_) @@ -2098,6 +2104,12 @@ def test_serializer_plist_binary_file_open(self, name): ) ret = ret[next(iter(ret))] assert ret["result"], ret + assert "changes" in ret + assert "diff" in ret["changes"] + assert "foo" in ret["changes"]["diff"] + assert "abc" in ret["changes"]["diff"]["foo"] + assert "new" in ret["changes"]["diff"]["foo"]["abc"] + assert ret["changes"]["diff"]["foo"]["abc"]["new"], 123 with salt.utils.files.fopen(name, "rb") as fp_: serialized_data = salt.serializers.plist.deserialize(fp_) @@ -2134,6 +2146,12 @@ def test_serializer_plist_file_open(self, name): ) ret = ret[next(iter(ret))] assert ret["result"], ret + assert "changes" in ret + assert "diff" in ret["changes"] + assert "foo" in ret["changes"]["diff"] + assert "abc" in ret["changes"]["diff"]["foo"] + assert "new" in ret["changes"]["diff"]["foo"]["abc"] + assert ret["changes"]["diff"]["foo"]["abc"]["new"], 123 with salt.utils.files.fopen(name, "rb") as fp_: serialized_data = salt.serializers.plist.deserialize(fp_)