From 58dba6bf22c5b8cffc6701ddd76024ce7ace4a9c Mon Sep 17 00:00:00 2001 From: abikouo <79859644+abikouo@users.noreply.github.com> Date: Tue, 15 Jun 2021 10:41:55 +0200 Subject: [PATCH] k8s apply - fix list merge for array attribute with empty dict (#131) Fix k8s apply --- ...29-k8s-fix-apply-array-with-empty-dict.yml | 3 + molecule/default/tasks/apply.yml | 60 +++++++++++++++++++ plugins/module_utils/apply.py | 36 +---------- 3 files changed, 65 insertions(+), 34 deletions(-) create mode 100644 changelogs/fragments/129-k8s-fix-apply-array-with-empty-dict.yml diff --git a/changelogs/fragments/129-k8s-fix-apply-array-with-empty-dict.yml b/changelogs/fragments/129-k8s-fix-apply-array-with-empty-dict.yml new file mode 100644 index 0000000000..d6f7dc92a0 --- /dev/null +++ b/changelogs/fragments/129-k8s-fix-apply-array-with-empty-dict.yml @@ -0,0 +1,3 @@ +--- +bugfixes: + - Fix apply for k8s module when an array attribute from definition contains empty dict (https://github.com/ansible-collections/kubernetes.core/issues/113). diff --git a/molecule/default/tasks/apply.yml b/molecule/default/tasks/apply.yml index 291a35d603..18c60d832f 100644 --- a/molecule/default/tasks/apply.yml +++ b/molecule/default/tasks/apply.yml @@ -836,6 +836,66 @@ that: - k8s_secret is not changed + - name: Create network policy (egress array with empty dict) + k8s: + namespace: "{{ apply_namespace }}" + apply: true + definition: + kind: NetworkPolicy + apiVersion: networking.k8s.io/v1 + metadata: + name: apply-netpolicy + labels: + app: apply-netpolicy + annotations: + {} + spec: + podSelector: + matchLabels: + app: apply-netpolicy + policyTypes: + - Ingress + - Egress + ingress: + - ports: + - port: 9093 + protocol: TCP + egress: + - {} + + - name: Apply network policy + k8s: + namespace: "{{ apply_namespace }}" + definition: + kind: NetworkPolicy + apiVersion: networking.k8s.io/v1 + metadata: + name: apply-netpolicy + labels: + app: apply-netpolicy + annotations: + {} + spec: + podSelector: + matchLabels: + app: apply-netpolicy + policyTypes: + - Ingress + - Egress + ingress: + - ports: + - port: 9093 + protocol: TCP + egress: + - {} + apply: true + register: k8s_networkpolicy + + - name: Check that nothing changed + assert: + that: + - k8s_networkpolicy is not changed + always: - name: Remove namespace k8s: diff --git a/plugins/module_utils/apply.py b/plugins/module_utils/apply.py index 4ccc8e69a6..87c3e2d6ec 100644 --- a/plugins/module_utils/apply.py +++ b/plugins/module_utils/apply.py @@ -18,10 +18,8 @@ from collections import OrderedDict import json -import sys from ansible.module_utils.common.dict_transformations import dict_merge -from ansible.module_utils.six import PY3 from ansible_collections.kubernetes.core.plugins.module_utils.exceptions import ApplyException try: @@ -29,8 +27,6 @@ except ImportError: pass -if PY3: - unicode = str LAST_APPLIED_CONFIG_ANNOTATION = 'kubectl.kubernetes.io/last-applied-configuration' @@ -79,34 +75,6 @@ ) -if sys.version_info.major >= 3: - json_loads_byteified = json.loads -else: - # https://stackoverflow.com/a/33571117 - def json_loads_byteified(json_text): - return _byteify( - json.loads(json_text, object_hook=_byteify), - ignore_dicts=True - ) - - def _byteify(data, ignore_dicts=False): - # if this is a unicode string, return its string representation - if isinstance(data, unicode): # noqa: F821 - return data.encode('utf-8') - # if this is a list of values, return list of byteified values - if isinstance(data, list): - return [_byteify(item, ignore_dicts=True) for item in data] - # if this is a dictionary, return dictionary of byteified keys and values - # but only if we haven't already byteified it - if isinstance(data, dict) and not ignore_dicts: - return { - _byteify(key, ignore_dicts=True): _byteify(value, ignore_dicts=True) - for key, value in data.items() - } - # if it's anything else, return it in its original form - return data - - def annotate(desired): return dict( metadata=dict( @@ -123,7 +91,7 @@ def apply_patch(actual, desired): if last_applied: # ensure that last_applied doesn't come back as a dict of unicode key/value pairs # json.loads can be used if we stop supporting python 2 - last_applied = json_loads_byteified(last_applied) + last_applied = json.loads(last_applied) patch = merge(dict_merge(last_applied, annotate(last_applied)), dict_merge(desired, annotate(desired)), actual) if patch: @@ -284,7 +252,7 @@ def get_delta(last_applied, actual, desired, position=None): elif isinstance(desired_value, list): p = list_merge(last_applied.get(k, []), actual_value, desired_value, this_position) if p: - patch[k] = [item for item in p if item] + patch[k] = [item for item in p if item is not None] elif actual_value != desired_value: patch[k] = desired_value return patch