From 6733c5f649c336da687382ef7469301f343c070c Mon Sep 17 00:00:00 2001 From: Will Thames Date: Wed, 27 May 2020 17:49:28 +1000 Subject: [PATCH] Handle list merges where items have been added elsewhere For example, a Pod has its service account token mounted as a volume - we don't want to later try and remove it. Other examples are likely available --- openshift/dynamic/apply.py | 3 +++ test/unit/test_apply.py | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/openshift/dynamic/apply.py b/openshift/dynamic/apply.py index 3b0ef325..2eb2a2b5 100644 --- a/openshift/dynamic/apply.py +++ b/openshift/dynamic/apply.py @@ -178,6 +178,9 @@ def list_merge(last_applied, actual, desired, position): else: patch = merge(last_applied_dict[key], desired_dict[key], actual_dict[key], position) result.append(dict_merge(actual_dict[key], patch)) + for key in actual_dict: + if key not in desired_dict and key not in last_applied_dict: + result.append(actual_dict[key]) return result else: return desired diff --git a/test/unit/test_apply.py b/test/unit/test_apply.py index d8d74bb0..907d08d2 100644 --- a/test/unit/test_apply.py +++ b/test/unit/test_apply.py @@ -53,6 +53,7 @@ ), expected = dict(metadata=dict(annotations=None), data=dict(two=None, three="3")) ), + dict( last_applied = dict( kind="Service", @@ -165,6 +166,43 @@ expected=dict(spec=dict(containers=[dict(name="busybox", image="busybox", resources=dict(requests=dict(cpu="50m", memory="50Mi"), limits=dict(cpu=None, memory="50Mi")))])) ), + dict( + desired = dict(kind='Pod', + spec=dict(containers=[ + dict(name='hello', + volumeMounts=[dict(name="test", mountPath="/test")]) + ], + volumes=[ + dict(name="test", configMap=dict(name="test")), + ])), + last_applied = dict(kind='Pod', + spec=dict(containers=[ + dict(name='hello', + volumeMounts=[dict(name="test", mountPath="/test")]) + ], + volumes=[ + dict(name="test", configMap=dict(name="test")), + ])), + actual = dict(kind='Pod', + spec=dict(containers=[ + dict(name='hello', + volumeMounts=[dict(name="test", mountPath="/test"), + dict(mountPath="/var/run/secrets/kubernetes.io/serviceaccount", name="default-token-xyz")]) + ], + volumes=[ + dict(name="test", configMap=dict(name="test")), + dict(name="default-token-xyz", secret=dict(secretName="default-token-xyz")), + ])), + expected = dict(spec=dict(containers=[ + dict(name='hello', + volumeMounts=[dict(name="test", mountPath="/test"), + dict(mountPath="/var/run/secrets/kubernetes.io/serviceaccount", name="default-token-xyz")]) + ], + volumes=[ + dict(name="test", configMap=dict(name="test")), + dict(name="default-token-xyz", secret=dict(secretName="default-token-xyz")), + ])), + ), # This next one is based on a real world case where definition was mostly # str type and everything else was mostly unicode type (don't ask me how)