mirror of
https://github.com/ansible-collections/kubernetes.core.git
synced 2026-04-27 16:46:26 +00:00
k8s - fix issue with server side apply (#549)
k8s - fix issue with server side apply SUMMARY Fix #548 and #547 ISSUE TYPE Bugfix Pull Request Reviewed-by: Mike Graves <mgraves@redhat.com> Reviewed-by: Bikouo Aubin <None>
This commit is contained in:
4
changelogs/fragments/549-fix-server-side-apply.yaml
Normal file
4
changelogs/fragments/549-fix-server-side-apply.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
bugfixes:
|
||||
- k8s - Fix issue with server side apply with kubernetes release '25.3.0' (https://github.com/ansible-collections/kubernetes.core/issues/548).
|
||||
- k8s - Fix issue with check_mode when using server side apply (https://github.com/ansible-collections/kubernetes.core/issues/547).
|
||||
@@ -24,6 +24,13 @@ from ansible.module_utils.common.dict_transformations import dict_merge
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.exceptions import (
|
||||
ApplyException,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import (
|
||||
gather_versions,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
|
||||
LooseVersion,
|
||||
)
|
||||
|
||||
|
||||
try:
|
||||
from kubernetes.dynamic.exceptions import NotFoundError
|
||||
@@ -131,7 +138,10 @@ def k8s_apply(resource, definition, **kwargs):
|
||||
existing, desired = apply_object(resource, definition)
|
||||
server_side = kwargs.get("server_side", False)
|
||||
if server_side:
|
||||
body = json.dumps(definition).encode()
|
||||
versions = gather_versions()
|
||||
body = definition
|
||||
if LooseVersion(versions["kubernetes"]) < LooseVersion("25.0.0"):
|
||||
body = json.dumps(definition).encode()
|
||||
# server_side_apply is forces content_type to 'application/apply-patch+yaml'
|
||||
return resource.server_side_apply(
|
||||
body=body,
|
||||
@@ -139,6 +149,7 @@ def k8s_apply(resource, definition, **kwargs):
|
||||
namespace=definition["metadata"].get("namespace"),
|
||||
force_conflicts=kwargs.get("force_conflicts"),
|
||||
field_manager=kwargs.get("field_manager"),
|
||||
dry_run=kwargs.get("dry_run"),
|
||||
)
|
||||
if not existing:
|
||||
return resource.create(
|
||||
|
||||
@@ -717,9 +717,67 @@
|
||||
- result.result.metadata.managedFields[0].manager == 'manager-02'
|
||||
- result.result.data.key == 'value-1'
|
||||
|
||||
# check_mode with server side apply
|
||||
- name: Ensure namespace does not exist
|
||||
k8s:
|
||||
state: absent
|
||||
kind: Namespace
|
||||
name: testing
|
||||
wait: true
|
||||
|
||||
- name: Create namespace using server_side_apply=true and check_mode=true
|
||||
k8s:
|
||||
apply: true
|
||||
server_side_apply:
|
||||
field_manager: ansible
|
||||
definition:
|
||||
kind: Namespace
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: testing
|
||||
check_mode: true
|
||||
register: _create
|
||||
|
||||
- name: Ensure namespace was not created
|
||||
k8s_info:
|
||||
kind: Namespace
|
||||
name: testing
|
||||
register: _info
|
||||
|
||||
- name: Validate that check_mode reported change even if namespace was not created
|
||||
assert:
|
||||
that:
|
||||
- _create is changed
|
||||
- not _info.resources
|
||||
|
||||
# server side apply over kubernetes client releases
|
||||
- name: Create temporary directory
|
||||
tempfile:
|
||||
state: directory
|
||||
suffix: .server
|
||||
register: path
|
||||
|
||||
- set_fact:
|
||||
virtualenv_src: "{{ path.path }}"
|
||||
|
||||
- include_tasks: tasks/server_side_apply.yml
|
||||
with_items:
|
||||
- '24.2.0'
|
||||
- '25.2.0a1'
|
||||
- '25.3.0b1'
|
||||
- '25.3.0'
|
||||
- '23.6.0'
|
||||
|
||||
always:
|
||||
- name: Remove namespace
|
||||
k8s:
|
||||
kind: Namespace
|
||||
name: "{{ test_namespace }}"
|
||||
state: absent
|
||||
|
||||
- name: Delete temporary directory
|
||||
file:
|
||||
path: "{{ virtualenv_src }}"
|
||||
state: absent
|
||||
ignore_errors: true
|
||||
when: virtualenv_src is defined
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
- set_fact:
|
||||
kubernetes_version: "kubernetes=={{ item }}"
|
||||
virtualenv_path: "{{ virtualenv_src }}/venv{{ item | replace('.', '') }}"
|
||||
|
||||
- name: Install kubernetes version
|
||||
pip:
|
||||
name:
|
||||
- '{{ kubernetes_version }}'
|
||||
virtualenv_command: "virtualenv --python {{ ansible_python_interpreter }}"
|
||||
virtualenv: "{{ virtualenv_path }}"
|
||||
|
||||
- name: Update namespace using server side apply
|
||||
k8s:
|
||||
apply: true
|
||||
server_side_apply:
|
||||
field_manager: "ansible{{ item | replace('.', '') }}"
|
||||
force_conflicts: true
|
||||
definition:
|
||||
kind: Namespace
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: testing
|
||||
vars:
|
||||
ansible_python_interpreter: "{{ virtualenv_path }}/bin/python"
|
||||
@@ -70,16 +70,10 @@ auth:
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
|
||||
try:
|
||||
from kubernetes import client, config
|
||||
from kubernetes.dynamic import DynamicClient, LazyDiscoverer
|
||||
|
||||
HAS_KUBERNETES_MODULE = True
|
||||
|
||||
except ImportError:
|
||||
HAS_KUBERNETES_MODULE = False
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
||||
get_api_client,
|
||||
)
|
||||
|
||||
|
||||
class K8SInventoryTestModule(AnsibleModule):
|
||||
@@ -91,10 +85,6 @@ class K8SInventoryTestModule(AnsibleModule):
|
||||
)
|
||||
|
||||
super(K8SInventoryTestModule, self).__init__(argument_spec=argument_spec)
|
||||
|
||||
if not HAS_KUBERNETES_MODULE:
|
||||
self.fail_json(msg=missing_required_lib("kubernetes"))
|
||||
|
||||
self.execute_module()
|
||||
|
||||
def execute_module(self):
|
||||
@@ -114,19 +104,15 @@ class K8SInventoryTestModule(AnsibleModule):
|
||||
)
|
||||
)
|
||||
|
||||
client_config = type.__call__(client.Configuration)
|
||||
config.load_kube_config(
|
||||
config_file=kubeconfig_path, client_configuration=client_config
|
||||
)
|
||||
DynamicClient(client.ApiClient(client_config), discoverer=LazyDiscoverer)
|
||||
client = get_api_client(kubeconfig=kubeconfig_path)
|
||||
|
||||
result = dict(host=os.path.join(dest_dir, "host_data.txt"))
|
||||
# create file containing host information
|
||||
with open(result["host"], "w") as fd:
|
||||
fd.write(client_config.host)
|
||||
fd.write(client.configuration.host)
|
||||
for key in ("cert_file", "key_file", "ssl_ca_cert"):
|
||||
dest_file = os.path.join(dest_dir, "{0}_data.txt".format(key))
|
||||
shutil.copyfile(getattr(client_config, key), dest_file)
|
||||
shutil.copyfile(getattr(client.configuration, key), dest_file)
|
||||
result[key] = dest_file
|
||||
|
||||
self.exit_json(auth=result)
|
||||
|
||||
Reference in New Issue
Block a user