From 0b772622883fe4836309e435d86383c8e8a9e350 Mon Sep 17 00:00:00 2001 From: Will Thames Date: Mon, 23 Jul 2018 14:05:25 +1000 Subject: [PATCH] Add merge_type parameter to k8s module (#42219) Allows patching of custom Kubernetes resources that don't support strategic merge patching Check that openshift module supports content_type param (requires version newer than 0.6.0) --- lib/ansible/module_utils/k8s/common.py | 5 +++-- lib/ansible/module_utils/k8s/raw.py | 20 ++++++++++++++++++-- lib/ansible/modules/clustering/k8s/k8s.py | 15 +++++++++++++++ 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/lib/ansible/module_utils/k8s/common.py b/lib/ansible/module_utils/k8s/common.py index a747d527c8..300b55d0a8 100644 --- a/lib/ansible/module_utils/k8s/common.py +++ b/lib/ansible/module_utils/k8s/common.py @@ -1,5 +1,4 @@ -# -# Copyright 2018 Red Hat | Ansible +# Copyright 2018 Red Hat | Ansible # # This file is part of Ansible # @@ -27,6 +26,7 @@ from ansible.module_utils.six import iteritems, string_types try: import kubernetes + import openshift from openshift.dynamic import DynamicClient from openshift.dynamic.exceptions import ResourceNotFoundError, ResourceNotUniqueError HAS_K8S_MODULE_HELPER = True @@ -258,6 +258,7 @@ class KubernetesAnsibleModule(AnsibleModule, K8sAnsibleMixin): if not HAS_K8S_MODULE_HELPER: self.fail_json(msg="This module requires the OpenShift Python client. Try `pip install openshift`") + self.openshift_version = openshift.__version__ if not HAS_YAML: self.fail_json(msg="This module requires PyYAML. Try `pip install PyYAML`") diff --git a/lib/ansible/module_utils/k8s/raw.py b/lib/ansible/module_utils/k8s/raw.py index 4bc2fa3e44..9b2cfa75b3 100644 --- a/lib/ansible/module_utils/k8s/raw.py +++ b/lib/ansible/module_utils/k8s/raw.py @@ -18,7 +18,8 @@ from __future__ import absolute_import, division, print_function - +import copy +from ansible.module_utils.k8s.common import AUTH_ARG_SPEC, COMMON_ARG_SPEC from ansible.module_utils.six import string_types from ansible.module_utils.k8s.common import KubernetesAnsibleModule from ansible.module_utils.common.dict_transformations import dict_merge @@ -34,6 +35,13 @@ except ImportError: class KubernetesRawModule(KubernetesAnsibleModule): + @property + def argspec(self): + argument_spec = copy.deepcopy(COMMON_ARG_SPEC) + argument_spec.update(copy.deepcopy(AUTH_ARG_SPEC)) + argument_spec['merge_type'] = dict(choices=['json', 'merge', 'strategic-merge']) + return argument_spec + def __init__(self, *args, **kwargs): self.client = None @@ -203,7 +211,15 @@ class KubernetesRawModule(KubernetesAnsibleModule): k8s_obj = dict_merge(existing.to_dict(), definition) else: try: - k8s_obj = resource.patch(definition, name=name, namespace=namespace).to_dict() + params = dict(name=name, namespace=namespace) + if self.params['merge_type']: + from distutils.version import LooseVersion + if LooseVersion(self.openshift_version) < LooseVersion("0.6.2"): + self.fail_json(msg="openshift >= 0.6.2 is required for merge_type") + params['content_type'] = 'application/{0}-patch+json'.format(self.params['merge_type']) + k8s_obj = resource.patch(definition, **params).to_dict() + match, diffs = self.diff_objects(existing.to_dict(), k8s_obj) + result['result'] = k8s_obj except DynamicApiError as exc: self.fail_json(msg="Failed to patch object: {0}".format(exc.body), error=exc.status, status=exc.status, reason=exc.reason) diff --git a/lib/ansible/modules/clustering/k8s/k8s.py b/lib/ansible/modules/clustering/k8s/k8s.py index 6fb6084757..fe2f9efc24 100644 --- a/lib/ansible/modules/clustering/k8s/k8s.py +++ b/lib/ansible/modules/clustering/k8s/k8s.py @@ -40,6 +40,21 @@ extends_documentation_fragment: - k8s_resource_options - k8s_auth_options +options: + merge_type: + description: + - Whether to override the default patch merge approach with a specific type. By the default, the strategic + merge will typically be used. + - For example, Custom Resource Definitions typically aren't updatable by the usual strategic merge. You may + want to use C(merge) if you see "strategic merge patch format is not supported" + - See U(https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/#use-a-json-merge-patch-to-update-a-deployment) + - Requires openshift >= 0.6.2 + choices: + - json + - merge + - strategic-merge + version_added: "2.7" + requirements: - "python >= 2.7" - "openshift >= 0.6"