mirror of
https://github.com/ansible-collections/kubernetes.core.git
synced 2026-05-12 12:32:05 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b16bb15d34 | ||
|
|
588f60adc8 | ||
|
|
deac7719c2 | ||
|
|
cb4b792038 | ||
|
|
6215ac763b | ||
|
|
d5599f1964 | ||
|
|
90134ec3e0 |
1
.github/workflows/integration-tests.yaml
vendored
1
.github/workflows/integration-tests.yaml
vendored
@@ -26,6 +26,7 @@ jobs:
|
||||
with:
|
||||
path: ${{ env.source_dir }}
|
||||
fetch-depth: "0"
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
- name: list changes for pull request
|
||||
id: splitter
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -21,3 +21,6 @@ tests/integration/*-chart-*.tgz
|
||||
# ansible-test generated file
|
||||
tests/integration/inventory
|
||||
tests/integration/*-*.yml
|
||||
|
||||
# VS Code settings
|
||||
.vscode/
|
||||
|
||||
@@ -4,6 +4,21 @@ Kubernetes Collection Release Notes
|
||||
|
||||
.. contents:: Topics
|
||||
|
||||
v5.4.1
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
This release includes bugfixes for k8s service field handling, k8s_cp init containers support, and removes deprecated ansible.module_utils.six imports.
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Remove ``ansible.module_utils.six`` imports to avoid warnings (https://github.com/ansible-collections/kubernetes.core/pull/998).
|
||||
- Update the `k8s_cp` module to also work for init containers (https://github.com/ansible-collections/kubernetes.core/pull/971).
|
||||
- module_utils/k8s/service - hide fields first before creating diffs (https://github.com/ansible-collections/kubernetes.core/pull/915).
|
||||
|
||||
v5.4.0
|
||||
======
|
||||
|
||||
@@ -28,15 +43,15 @@ This release includes minor changes, bug fixes and also bumps ``ansible-lint`` v
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- kubernetes.core - Bump version of ``ansible-lint`` to ``25.1.2`` (https://github.com/ansible-collections/kubernetes.core/pull/919).
|
||||
- Bump version of ``ansible-lint`` to 25.1.2 (https://github.com/ansible-collections/kubernetes.core/pull/919).
|
||||
- action/k8s_info - update templating mechanism with changes from ``ansible-core 2.19`` (https://github.com/ansible-collections/kubernetes.core/pull/888).
|
||||
- helm - add ``reset_then_reuse_values`` support to helm module (https://github.com/ansible-collections/kubernetes.core/issues/803).
|
||||
- helm - add support for ``insecure_skip_tls_verify`` option to helm and ``helm_repository`` (https://github.com/ansible-collections/kubernetes.core/issues/694).
|
||||
- helm - add support for ``insecure_skip_tls_verify`` option to helm and helm_repository(https://github.com/ansible-collections/kubernetes.core/issues/694).
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- module_utils/k8s/service - Fix issue when trying to delete resource using ``delete_options`` and ``check_mode=true`` (https://github.com/ansible-collections/kubernetes.core/issues/892).
|
||||
- module_utils/k8s/service - fix issue when trying to delete resource using ``delete_options`` and ``check_mode=true`` (https://github.com/ansible-collections/kubernetes.core/issues/892).
|
||||
|
||||
v5.2.0
|
||||
======
|
||||
|
||||
2
Makefile
2
Makefile
@@ -1,5 +1,5 @@
|
||||
# Also needs to be updated in galaxy.yml
|
||||
VERSION = 5.4.0
|
||||
VERSION = 5.4.1
|
||||
|
||||
TEST_ARGS ?= ""
|
||||
PYTHON_VERSION ?= `python -c 'import platform; print(".".join(platform.python_version_tuple()[0:2]))'`
|
||||
|
||||
@@ -106,7 +106,7 @@ You can also include it in a `requirements.yml` file and install it via `ansible
|
||||
---
|
||||
collections:
|
||||
- name: kubernetes.core
|
||||
version: 5.4.0
|
||||
version: 5.4.1
|
||||
```
|
||||
|
||||
### Installing the Kubernetes Python Library
|
||||
|
||||
@@ -977,7 +977,7 @@ releases:
|
||||
- kustomize - kustomize plugin fails with deprecation warnings (https://github.com/ansible-collections/kubernetes.core/issues/639).
|
||||
- waiter - Fix waiting for daemonset when desired number of pods is 0. (https://github.com/ansible-collections/kubernetes.core/pull/756).
|
||||
minor_changes:
|
||||
- Bump version of ansible-lint to minimum 24.7.0 (https://github.com/ansible-collections/kubernetes.core/pull/765).
|
||||
- Bump version of ``ansible-lint`` to minimum 24.7.0 (https://github.com/ansible-collections/kubernetes.core/pull/765).
|
||||
- Parameter insecure_registry added to helm_template as equivalent of insecure-skip-tls-verify
|
||||
(https://github.com/ansible-collections/kubernetes.core/pull/805).
|
||||
- k8s_drain - Improve error message for pod disruption budget when draining
|
||||
@@ -1056,3 +1056,18 @@ releases:
|
||||
- 20250605-fix-helm_registry_auth-integration_test.yaml
|
||||
- 5.4.0.yml
|
||||
release_date: '2025-08-12'
|
||||
5.4.1:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Remove ``ansible.module_utils.six`` imports to avoid warnings (https://github.com/ansible-collections/kubernetes.core/pull/998).
|
||||
- Update the `k8s_cp` module to also work for init containers (https://github.com/ansible-collections/kubernetes.core/pull/971).
|
||||
- module_utils/k8s/service - hide fields first before creating diffs (https://github.com/ansible-collections/kubernetes.core/pull/915).
|
||||
release_summary: This release includes bugfixes for k8s service field handling,
|
||||
k8s_cp init containers support, and removes deprecated ansible.module_utils.six
|
||||
imports.
|
||||
fragments:
|
||||
- 20250428-k8s-service-hide-fields-first.yaml
|
||||
- 20250731-fix-k8s_cp-initcontainers.yaml
|
||||
- 20250922-remove-ansible-six-imports.yaml
|
||||
- 5.4.1.yml
|
||||
release_date: '2025-10-07'
|
||||
|
||||
@@ -512,6 +512,7 @@ Notes
|
||||
|
||||
.. note::
|
||||
- the tar binary is required on the container when copying from local filesystem to pod.
|
||||
- the (init) container has to be started before you copy files or directories to it.
|
||||
- To avoid SSL certificate validation errors when ``validate_certs`` is *True*, the full certificate chain for the API server must be provided via ``ca_cert`` or in the kubeconfig file.
|
||||
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ tags:
|
||||
- openshift
|
||||
- okd
|
||||
- cluster
|
||||
version: 5.4.0
|
||||
version: 5.4.1
|
||||
build_ignore:
|
||||
- .DS_Store
|
||||
- "*.tar.gz"
|
||||
|
||||
@@ -22,7 +22,6 @@ from ansible.errors import (
|
||||
)
|
||||
from ansible.module_utils._text import to_bytes, to_native, to_text
|
||||
from ansible.module_utils.parsing.convert_bool import boolean
|
||||
from ansible.module_utils.six import iteritems, string_types
|
||||
from ansible.plugins.action import ActionBase
|
||||
|
||||
try:
|
||||
@@ -100,7 +99,7 @@ class ActionModule(ActionBase):
|
||||
"trim_blocks": True,
|
||||
"lstrip_blocks": False,
|
||||
}
|
||||
if isinstance(template, string_types):
|
||||
if isinstance(template, str):
|
||||
# treat this as raw_params
|
||||
template_param["path"] = template
|
||||
elif isinstance(template, dict):
|
||||
@@ -120,7 +119,7 @@ class ActionModule(ActionBase):
|
||||
):
|
||||
if s_type in template_args:
|
||||
value = ensure_type(template_args[s_type], "string")
|
||||
if value is not None and not isinstance(value, string_types):
|
||||
if value is not None and not isinstance(value, str):
|
||||
raise AnsibleActionFail(
|
||||
"%s is expected to be a string, but got %s instead"
|
||||
% (s_type, type(value))
|
||||
@@ -196,7 +195,7 @@ class ActionModule(ActionBase):
|
||||
)
|
||||
|
||||
template_params = []
|
||||
if isinstance(template, string_types) or isinstance(template, dict):
|
||||
if isinstance(template, str) or isinstance(template, dict):
|
||||
template_params.append(self.get_template_args(template))
|
||||
elif isinstance(template, list):
|
||||
for element in template:
|
||||
@@ -246,7 +245,7 @@ class ActionModule(ActionBase):
|
||||
# add ansible 'template' vars
|
||||
temp_vars = copy.deepcopy(task_vars)
|
||||
overrides = {}
|
||||
for key, value in iteritems(template_item):
|
||||
for key, value in template_item.items():
|
||||
if hasattr(self._templar.environment, key):
|
||||
if value is not None:
|
||||
overrides[key] = value
|
||||
@@ -303,7 +302,7 @@ class ActionModule(ActionBase):
|
||||
)
|
||||
|
||||
def get_kubeconfig(self, kubeconfig, remote_transport, new_module_args):
|
||||
if isinstance(kubeconfig, string_types):
|
||||
if isinstance(kubeconfig, str):
|
||||
# find the kubeconfig in the expected search path
|
||||
if not remote_transport:
|
||||
# kubeconfig is local
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
from ansible.module_utils.six import string_types
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
def list_dict_str(value):
|
||||
if isinstance(value, (list, dict, string_types)):
|
||||
if isinstance(value, (list, dict, str)):
|
||||
return value
|
||||
raise TypeError
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ class K8SCopy(metaclass=ABCMeta):
|
||||
return error, stdout, stderr
|
||||
except Exception as e:
|
||||
self.module.fail_json(
|
||||
msg="Error while running/parsing from pod {1}/{2} command='{0}' : {3}".format(
|
||||
msg="Error while running/parsing from pod {0}/{1} command='{2}' : {3}".format(
|
||||
self.namespace, self.name, cmd, to_native(e)
|
||||
)
|
||||
)
|
||||
@@ -435,11 +435,21 @@ def check_pod(svc):
|
||||
|
||||
try:
|
||||
result = svc.client.get(resource, name=name, namespace=namespace)
|
||||
containers = [
|
||||
c["name"] for c in result.to_dict()["status"]["containerStatuses"]
|
||||
]
|
||||
if container and container not in containers:
|
||||
containers = dict(
|
||||
{
|
||||
c["name"]: c
|
||||
for cl in ["initContainerStatuses", "containerStatuses"]
|
||||
for c in result.to_dict()["status"].get(cl, [])
|
||||
}
|
||||
)
|
||||
if container and container not in containers.keys():
|
||||
module.fail_json(msg="Pod has no container {0}".format(container))
|
||||
return containers
|
||||
if (
|
||||
container
|
||||
and container in containers
|
||||
and not bool(containers[container].get("started", False))
|
||||
):
|
||||
module.fail_json(msg="Pod container {0} is not started".format(container))
|
||||
return containers.keys()
|
||||
except Exception as exc:
|
||||
_fail(exc)
|
||||
|
||||
@@ -15,7 +15,6 @@ import tempfile
|
||||
import traceback
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
from ansible.module_utils.six import string_types
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
|
||||
LooseVersion,
|
||||
)
|
||||
@@ -113,7 +112,7 @@ class AnsibleHelmModule(object):
|
||||
kubeconfig_content = None
|
||||
kubeconfig = self.params.get("kubeconfig")
|
||||
if kubeconfig:
|
||||
if isinstance(kubeconfig, string_types):
|
||||
if isinstance(kubeconfig, str):
|
||||
with open(os.path.expanduser(kubeconfig)) as fd:
|
||||
kubeconfig_content = yaml.safe_load(fd)
|
||||
elif isinstance(kubeconfig, dict):
|
||||
|
||||
@@ -5,7 +5,6 @@ import hashlib
|
||||
import os
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from ansible.module_utils.six import iteritems, string_types
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
|
||||
AUTH_ARG_MAP,
|
||||
AUTH_ARG_SPEC,
|
||||
@@ -115,7 +114,7 @@ def _load_config(auth: Dict) -> None:
|
||||
"persist_config": auth.get("persist_config"),
|
||||
}
|
||||
if kubeconfig:
|
||||
if isinstance(kubeconfig, string_types):
|
||||
if isinstance(kubeconfig, str):
|
||||
kubernetes.config.load_kube_config(config_file=kubeconfig, **optional_arg)
|
||||
elif isinstance(kubeconfig, dict):
|
||||
kubernetes.config.load_kube_config_from_dict(
|
||||
@@ -163,7 +162,7 @@ def _create_configuration(auth: Dict):
|
||||
except AttributeError:
|
||||
configuration = kubernetes.client.Configuration()
|
||||
|
||||
for key, value in iteritems(auth):
|
||||
for key, value in auth.items():
|
||||
if key in AUTH_ARG_MAP.keys() and value is not None:
|
||||
if key == "api_key":
|
||||
setattr(
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
import os
|
||||
from typing import Dict, Iterable, List, Optional, Union, cast
|
||||
|
||||
from ansible.module_utils.six import string_types
|
||||
from ansible.module_utils.urls import Request
|
||||
|
||||
try:
|
||||
@@ -78,11 +77,11 @@ def create_definitions(params: Dict) -> List[ResourceDefinition]:
|
||||
def from_yaml(definition: Union[str, List, Dict]) -> Iterable[Dict]:
|
||||
"""Load resource definitions from a yaml definition."""
|
||||
definitions: List[Dict] = []
|
||||
if isinstance(definition, string_types):
|
||||
if isinstance(definition, str):
|
||||
definitions += yaml.safe_load_all(definition)
|
||||
elif isinstance(definition, list):
|
||||
for item in definition:
|
||||
if isinstance(item, string_types):
|
||||
if isinstance(item, str):
|
||||
definitions += yaml.safe_load_all(item)
|
||||
else:
|
||||
definitions.append(item)
|
||||
|
||||
@@ -498,8 +498,8 @@ def diff_objects(
|
||||
if not diff:
|
||||
return True, result
|
||||
|
||||
result["before"] = diff[0]
|
||||
result["after"] = diff[1]
|
||||
result["before"] = hide_fields(diff[0], hidden_fields)
|
||||
result["after"] = hide_fields(diff[1], hidden_fields)
|
||||
|
||||
if list(result["after"].keys()) == ["metadata"] and list(
|
||||
result["before"].keys()
|
||||
@@ -512,9 +512,6 @@ def diff_objects(
|
||||
).issubset(ignored_keys):
|
||||
return True, result
|
||||
|
||||
result["before"] = hide_fields(result["before"], hidden_fields)
|
||||
result["after"] = hide_fields(result["after"], hidden_fields)
|
||||
|
||||
return False, result
|
||||
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@ options:
|
||||
|
||||
notes:
|
||||
- the tar binary is required on the container when copying from local filesystem to pod.
|
||||
- the (init) container has to be started before you copy files or directories to it.
|
||||
"""
|
||||
|
||||
EXAMPLES = r"""
|
||||
|
||||
@@ -14,3 +14,9 @@ pod_with_two_container:
|
||||
|
||||
pod_without_executable_find:
|
||||
name: openjdk-pod
|
||||
|
||||
pod_with_initcontainer_and_container:
|
||||
name: pod-copy-2
|
||||
container:
|
||||
- container-20
|
||||
- container-21
|
||||
|
||||
@@ -18,6 +18,23 @@
|
||||
wait: yes
|
||||
template: pods_definition.j2
|
||||
|
||||
- name: Create Init Pod
|
||||
k8s:
|
||||
namespace: '{{ copy_namespace }}'
|
||||
template: pods_definition_init.j2
|
||||
|
||||
- kubernetes.core.k8s_info:
|
||||
api_version: v1
|
||||
kind: Pod
|
||||
name: '{{ pod_with_initcontainer_and_container.name }}'
|
||||
namespace: '{{ copy_namespace }}'
|
||||
register: init_pod_status
|
||||
until: >-
|
||||
init_pod_status.resources|length > 0
|
||||
and 'initContainerStatuses' in init_pod_status.resources.0.status
|
||||
and init_pod_status.resources.0.status.initContainerStatuses|length > 0
|
||||
and init_pod_status.resources.0.status.initContainerStatuses.0.started|bool
|
||||
|
||||
- include_tasks: test_copy_errors.yml
|
||||
- include_tasks: test_check_mode.yml
|
||||
- include_tasks: test_copy_file.yml
|
||||
@@ -25,6 +42,7 @@
|
||||
- include_tasks: test_copy_directory.yml
|
||||
- include_tasks: test_copy_large_file.yml
|
||||
- include_tasks: test_copy_item_with_space_in_its_name.yml
|
||||
- include_tasks: test_init_container_pod.yml
|
||||
|
||||
always:
|
||||
|
||||
|
||||
@@ -67,3 +67,21 @@
|
||||
that:
|
||||
- copy_fake_container is failed
|
||||
- copy_fake_container.msg == "Pod has no container this_is_a_fake_container"
|
||||
|
||||
# copy file to not started container in pod should fail
|
||||
- name: copy file to not started container in pod should fail
|
||||
k8s_cp:
|
||||
namespace: '{{ copy_namespace }}'
|
||||
pod: '{{ pod_with_initcontainer_and_container.name }}'
|
||||
remote_path: /tmp
|
||||
local_path: files/simple_file.txt
|
||||
state: to_pod
|
||||
container: '{{ pod_with_initcontainer_and_container.container[1] }}'
|
||||
ignore_errors: true
|
||||
register: copy_not_started_container
|
||||
|
||||
- name: check that error message is as expected
|
||||
assert:
|
||||
that:
|
||||
- copy_not_started_container is failed
|
||||
- copy_not_started_container.msg == "Pod container {{ pod_with_initcontainer_and_container.container[1] }} is not started"
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
- set_fact:
|
||||
random_content: "{{ lookup('password', '/dev/null chars=ascii_lowercase,digits,punctuation length=128') }}"
|
||||
|
||||
- name: Copy content into init container
|
||||
k8s_cp:
|
||||
namespace: '{{ copy_namespace }}'
|
||||
pod: '{{ pod_with_initcontainer_and_container.name }}'
|
||||
remote_path: /file_from_localhost.txt
|
||||
content: '{{ random_content }}'
|
||||
container: '{{ pod_with_initcontainer_and_container.container[0] }}'
|
||||
state: to_pod
|
||||
|
||||
- name: Get the content from copied file
|
||||
kubernetes.core.k8s_exec:
|
||||
namespace: '{{ copy_namespace }}'
|
||||
pod: '{{ pod_with_initcontainer_and_container.name }}'
|
||||
container: '{{ pod_with_initcontainer_and_container.container[0] }}'
|
||||
command: cat /file_from_localhost.txt
|
||||
register: exec_out
|
||||
|
||||
- name: check that content is found and the same as generated earlier
|
||||
assert:
|
||||
that:
|
||||
- exec_out.stdout == random_content
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: '{{ pod_with_initcontainer_and_container.name }}'
|
||||
spec:
|
||||
initContainers:
|
||||
- name: '{{ pod_with_initcontainer_and_container.container[0] }}'
|
||||
image: busybox
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- while true;do date;sleep 5; done
|
||||
containers:
|
||||
- name: '{{ pod_with_initcontainer_and_container.container[1] }}'
|
||||
image: busybox
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- while true;do date;sleep 5; done
|
||||
@@ -58,7 +58,7 @@
|
||||
- "'managedFields' not in hf4.resources[0]['metadata']"
|
||||
|
||||
|
||||
- name: Hiding a changed field should still result in a change
|
||||
- name: Hiding a changed field should not result in a change
|
||||
k8s:
|
||||
definition: "{{ hide_fields_base_configmap | combine({'data':{'hello':'different'}}) }}"
|
||||
hidden_fields:
|
||||
@@ -67,10 +67,10 @@
|
||||
register: hf5
|
||||
diff: true
|
||||
|
||||
- name: Ensure that hidden changed field changed
|
||||
- name: Ensure that hidden changed field not changed
|
||||
assert:
|
||||
that:
|
||||
- hf5.changed
|
||||
- not hf5.changed
|
||||
|
||||
- name: Apply works with hidden fields
|
||||
k8s:
|
||||
|
||||
@@ -10,7 +10,6 @@ import ansible.module_utils.basic
|
||||
import pytest
|
||||
from ansible.module_utils._text import to_bytes
|
||||
from ansible.module_utils.common._collections_compat import MutableMapping
|
||||
from ansible.module_utils.six import string_types
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -20,7 +19,7 @@ def stdin(mocker, request):
|
||||
old_argv = sys.argv
|
||||
sys.argv = ["ansible_unittest"]
|
||||
|
||||
if isinstance(request.param, string_types):
|
||||
if isinstance(request.param, str):
|
||||
args = request.param
|
||||
elif isinstance(request.param, MutableMapping):
|
||||
if "ANSIBLE_MODULE_ARGS" not in request.param:
|
||||
|
||||
Reference in New Issue
Block a user