Compare commits

5 Commits
4.0.0 ... 3.0.1

Author SHA1 Message Date
Bikouo Aubin
1c0734dd4e Prepare release 3.0.1 (#693) 2024-03-04 11:02:29 +01:00
patchback[bot]
e6d138dbf0 helm - Add reuse-values when running helm diff (#683) (#692)
helm - Add reuse-values when running helm diff

SUMMARY

closes #680

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

helm

Reviewed-by: GomathiselviS
Reviewed-by: Alina Buzachis
(cherry picked from commit 23e94b60c1)

Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>
2024-03-01 18:01:13 +01:00
patchback[bot]
eed4ebb0af Align helmdiff_check behavior with the deploy function (#670) (#690)
Align `helmdiff_check` behavior with the `deploy` function

SUMMARY
Align helmdiff_check behavior with the deploy function

Fixes #638
helmdiff_check respects set_values parameter
Fixes #669
helmdiff_check command line parameters sequence aligned to the deploy function

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME
kubernetes.core.helm

Reviewed-by: Mike Graves <mgraves@redhat.com>
(cherry picked from commit 7c4ec3b982)

Co-authored-by: psmolkin <pavel.smolkin@gmail.com>
2024-03-01 17:50:35 +01:00
patchback[bot]
d3031fcbd3 [PR #676/19559892 backport][stable-3] fix(Collection's util resource discovery fails when complex subresources present #659) (#687)
* fix(Collection's util resource discovery fails when complex subresources present #659) (#676)

* fix(Collection's util resource discovery fails when complex subresources present #659)

* fix(add changelog fragment)

* update node image

* Create discovery.yml

* Update main.yml

---------

Co-authored-by: Bastien Bosser <bastien.bosser@eviden.com>
Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>
(cherry picked from commit 1955989278)

* adding sanity ignore file

* Remove refresh_ignore_files

* Update ignore files content

---------

Co-authored-by: bastienbosser <55381632+bastienbosser@users.noreply.github.com>
Co-authored-by: abikouo <abikouo@redhat.com>
2024-03-01 16:44:19 +01:00
GomathiselviS
e756cedf33 Prepare for release 3.0.0 (#662)
Prepare for release 3.0.0

SUMMARY



Updated version to 3.0.0
Executed antsibull-changelog to generate changelog

ISSUE TYPE


Docs Pull Request

COMPONENT NAME

ADDITIONAL INFORMATION

Reviewed-by: Alina Buzachis
Reviewed-by: Helen Bailey <hebailey@redhat.com>
Reviewed-by: GomathiselviS
2023-11-17 21:52:11 +00:00
52 changed files with 1717 additions and 729 deletions

View File

@@ -21,4 +21,4 @@ jobs:
- uses: actions/checkout@v4
- name: Run ansible-lint
uses: ansible/ansible-lint@v24.2.3
uses: ansible/ansible-lint@v6.21.0

View File

@@ -4,59 +4,6 @@ Kubernetes Collection Release Notes
.. contents:: Topics
v4.0.0
======
Release Summary
---------------
This major release brings several bug fixes. We have also removed support for ``ansible-core<2.15`` and deprecated functions and class from ``module_utils/common.py``.
Minor Changes
-------------
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 5.0 (https://github.com/ansible-collections/kubernetes.core/pull/723).
- k8s - The module and K8sService were changed so warnings returned by the K8S API are now displayed to the user.
Removed Features (previously deprecated)
----------------------------------------
- k8s - Support for ``merge_type=json`` has been removed in version 4.0.0. Please use ``kubernetes.core.k8s_json_patch`` instead (https://github.com/ansible-collections/kubernetes.core/pull/722).
- k8s_exec - the previously deprecated ``result.return_code`` return value has been removed, consider using ``result.rc`` instead (https://github.com/ansible-collections/kubernetes.core/pull/726).
- module_utils/common.py - the previously deprecated ``K8sAnsibleMixin`` class has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
- module_utils/common.py - the previously deprecated ``configuration_digest()`` function has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
- module_utils/common.py - the previously deprecated ``get_api_client()`` function has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
- module_utils/common.py - the previously deprecated ``unique_string()`` function has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
Bugfixes
--------
- Resolve Collections util resource discovery fails when complex subresources present (https://github.com/ansible-collections/kubernetes.core/pull/676).
- align `helmdiff_check()` function commandline rendering with the `deploy()` function (https://github.com/ansible-collections/kubernetes.core/pull/670).
- avoid unsafe conditions in integration tests (https://github.com/ansible-collections/kubernetes.core/pull/665).
- helm - use ``reuse-values`` when running ``helm diff`` command (https://github.com/ansible-collections/kubernetes.core/issues/680).
- integrations test helm_kubeconfig - set helm version to v3.10.3 to avoid incompatability with new bitnami charts (https://github.com/ansible-collections/kubernetes.core/pull/670).
v3.1.0
======
Release Summary
---------------
This release comes with some bugfixes and documentation updates. It also adds new features to the kubectl connection plugin and the kustomize lookup plugin.
Minor Changes
-------------
- kubectl - added support of local enviroment variable that will be used for kubectl and may be requried for establishing connections ifself (https://github.com/ansible-collections/kubernetes.core/pull/702)
- kustomize - new parameter added to --enable-helm (https://github.com/ansible-collections/kubernetes.core/issues/568)
Bugfixes
--------
- helm - expand kubeconfig path with user's home directory for consistency with k8s
- k8s_json_patch - rename action symlink to ensure k8s action plugin is used (https://github.com/ansible-collections/kubernetes.core/pull/652).
v3.0.1
======

View File

@@ -1,5 +1,5 @@
# Also needs to be updated in galaxy.yml
VERSION = 4.0.0
VERSION = 3.0.0
TEST_ARGS ?= ""
PYTHON_VERSION ?= `python -c 'import platform; print(".".join(platform.python_version_tuple()[0:2]))'`

View File

@@ -93,7 +93,7 @@ You can also include it in a `requirements.yml` file and install it via `ansible
---
collections:
- name: kubernetes.core
version: 4.0.0
version: 3.0.0
```
### Installing the Kubernetes Python Library

View File

@@ -833,66 +833,3 @@ releases:
- 20240228-fix-helm-diff-with-reuse-values.yml
- 3.0.1.yml
release_date: '2024-03-01'
3.1.0:
changes:
bugfixes:
- helm - expand kubeconfig path with user's home directory for consistency with
k8s
- k8s_json_patch - rename action symlink to ensure k8s action plugin is used
(https://github.com/ansible-collections/kubernetes.core/pull/652).
minor_changes:
- kubectl - added support of local enviroment variable that will be used for
kubectl and may be requried for establishing connections ifself (https://github.com/ansible-collections/kubernetes.core/pull/702)
- kustomize - new parameter added to --enable-helm (https://github.com/ansible-collections/kubernetes.core/issues/568)
release_summary: This release comes with some bugfixes and documentation updates.
It also adds new features to the kubectl connection plugin and the kustomize
lookup plugin.
fragments:
- 20240426-add-support-of-kubectl-local-env-vars-for-connection-plugin.yml
- 3.1.0.yml
- 592-kustomize-helm-support.yml
- 652-fix-json-patch-action.yml
- 654-helm-expand-user.yml
release_date: '2024-05-16'
4.0.0:
changes:
bugfixes:
- Resolve Collections util resource discovery fails when complex subresources
present (https://github.com/ansible-collections/kubernetes.core/pull/676).
- align `helmdiff_check()` function commandline rendering with the `deploy()`
function (https://github.com/ansible-collections/kubernetes.core/pull/670).
- avoid unsafe conditions in integration tests (https://github.com/ansible-collections/kubernetes.core/pull/665).
- helm - use ``reuse-values`` when running ``helm diff`` command (https://github.com/ansible-collections/kubernetes.core/issues/680).
- integrations test helm_kubeconfig - set helm version to v3.10.3 to avoid incompatability
with new bitnami charts (https://github.com/ansible-collections/kubernetes.core/pull/670).
minor_changes:
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 5.0 (https://github.com/ansible-collections/kubernetes.core/pull/723).
- k8s - The module and K8sService were changed so warnings returned by the K8S
API are now displayed to the user.
release_summary: This major release brings several bug fixes. We have also removed
support for ``ansible-core<2.15`` and deprecated functions and class from
``module_utils/common.py``.
removed_features:
- k8s - Support for ``merge_type=json`` has been removed in version 4.0.0. Please
use ``kubernetes.core.k8s_json_patch`` instead (https://github.com/ansible-collections/kubernetes.core/pull/722).
- k8s_exec - the previously deprecated ``result.return_code`` return value has
been removed, consider using ``result.rc`` instead (https://github.com/ansible-collections/kubernetes.core/pull/726).
- module_utils/common.py - the previously deprecated ``K8sAnsibleMixin`` class
has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
- module_utils/common.py - the previously deprecated ``configuration_digest()``
function has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
- module_utils/common.py - the previously deprecated ``get_api_client()`` function
has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
- module_utils/common.py - the previously deprecated ``unique_string()`` function
has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
fragments:
- 20231206-fix-unsafe-condition-in-integration.yml
- 20240117-fix-helm-diff-cmd-line-rendering.yml
- 20240222-Collections-util-resource-discovery-fails-when-complex-subresources-present.yml
- 20240228-fix-helm-diff-with-reuse-values.yml
- 20240423-k8s-display-warnings-to-users.yml
- 4.0.0.yaml
- inventory-update_removal_date.yml
- k8s-merge_type-removed.yml
- module_utils-common-remove-deprecated-functions-and-class.yaml
release_date: '2024-05-24'

View File

@@ -17,7 +17,7 @@ DEPRECATED
----------
:Removed in collection release after
:Why: As discussed in https://github.com/ansible-collections/kubernetes.core/issues/31, we decided to
remove the k8s inventory plugin in release 5.0.0.
remove the k8s inventory plugin in release 4.0.0.
:Alternative: Use :ref:`kubernetes.core.k8s_info <kubernetes.core.k8s_info_module>` and :ref:`ansible.builtin.add_host <ansible.builtin.add_host_module>` instead.
@@ -357,7 +357,7 @@ Status
------
- This inventory will be removed in version 5.0.0. *[deprecated]*
- This inventory will be removed in version 4.0.0. *[deprecated]*
- For more information see `DEPRECATED`_.

View File

@@ -121,7 +121,7 @@ Parameters
<td>
<div><code>apply</code> compares the desired resource definition with the previously supplied resource definition, ignoring properties that are automatically generated</div>
<div><code>apply</code> works better with Services than &#x27;force=yes&#x27;</div>
<div>Mutually exclusive with <code>merge_type</code>.</div>
<div>mutually exclusive with <code>merge_type</code></div>
</td>
</tr>
<tr>
@@ -513,17 +513,18 @@ Parameters
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>json</li>
<li>merge</li>
<li>strategic-merge</li>
</ul>
</td>
<td>
<div>Whether to override the default patch merge approach with a specific type. By default, the strategic merge will typically be used.</div>
<div>For example, Custom Resource Definitions typically aren&#x27;t updatable by the usual strategic merge. You may want to use <code>merge</code> if you see &quot;strategic merge patch format is not supported&quot;.</div>
<div>For example, Custom Resource Definitions typically aren&#x27;t updatable by the usual strategic merge. You may want to use <code>merge</code> if you see &quot;strategic merge patch format is not supported&quot;</div>
<div>See <a href='https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/#use-a-json-merge-patch-to-update-a-deployment'>https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/#use-a-json-merge-patch-to-update-a-deployment</a></div>
<div>If more than one <code>merge_type</code> is given, the merge_types will be tried in order. This defaults to <code>[&#x27;strategic-merge&#x27;, &#x27;merge&#x27;]</code>, which is ideal for using the same parameters on resource kinds that combine Custom Resources and built-in resources.</div>
<div>Mutually exclusive with <code>apply</code>.</div>
<div><em>merge_type=json</em> has been removed in version 4.0.0. Please use <span class='module'>kubernetes.core.k8s_json_patch</span> instead.</div>
<div>mutually exclusive with <code>apply</code></div>
<div><em>merge_type=json</em> is deprecated and will be removed in version 3.0.0. Please use <span class='module'>kubernetes.core.k8s_json_patch</span> instead.</div>
</td>
</tr>
<tr>

View File

@@ -211,27 +211,6 @@ Parameters
<div>The configuration can be provided as dictionary. Added in version 2.4.0.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>kubectl_local_env_vars</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">dictionary</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.1.0</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">{}</div>
</td>
<td>
<div>var: ansible_kubectl_local_env_vars</div>
</td>
<td>
<div>Local enviromantal variable to be passed locally to the kubectl command line.</div>
<div>Please be aware that this passes information directly on the command line and it could expose sensitive data.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>

View File

@@ -77,24 +77,6 @@ Parameters
<div>If omitted, &#x27;.&#x27; is assumed.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>enable_helm</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">-</span>
</div>
</td>
<td>
<b>Default:</b><br/><div style="color: blue">"False"</div>
</td>
<td>
</td>
<td>
<div>Enable the helm chart inflation generator</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
@@ -130,21 +112,17 @@ Examples
.. code-block:: yaml
- name: Run lookup using kustomize
ansible.builtin.set_fact:
set_fact:
resources: "{{ lookup('kubernetes.core.kustomize', binary_path='/path/to/kustomize') }}"
- name: Run lookup using kubectl kustomize
ansible.builtin.set_fact:
set_fact:
resources: "{{ lookup('kubernetes.core.kustomize', binary_path='/path/to/kubectl') }}"
- name: Create kubernetes resources for lookup output
kubernetes.core.k8s:
k8s:
definition: "{{ lookup('kubernetes.core.kustomize', dir='/path/to/kustomization') }}"
- name: Create kubernetes resources for lookup output with `--enable-helm` set
kubernetes.core.k8s:
definition: "{{ lookup('kubernetes.core.kustomize', dir='/path/to/kustomization', enable_helm=True) }}"
Return Values

View File

@@ -25,7 +25,7 @@ tags:
- openshift
- okd
- cluster
version: 4.0.0
version: 3.0.0
build_ignore:
- .DS_Store
- "*.tar.gz"

View File

@@ -22,10 +22,10 @@ plugin_routing:
redirect: community.okd.openshift
k8s:
deprecation:
removal_version: 5.0.0
removal_version: 4.0.0
warning_text: >-
The k8s inventory plugin has been deprecated and
will be removed in release 5.0.0.
will be removed in release 4.0.0.
modules:
k8s_auth:
redirect: community.okd.k8s_auth

View File

@@ -72,15 +72,6 @@ DOCUMENTATION = r"""
- name: ansible_kubectl_extra_args
env:
- name: K8S_AUTH_EXTRA_ARGS
kubectl_local_env_vars:
description:
- Local enviromantal variable to be passed locally to the kubectl command line.
- Please be aware that this passes information directly on the command line and it could expose sensitive data.
default: {}
type: dict
version_added: 3.1.0
vars:
- name: ansible_kubectl_local_env_vars
kubectl_kubeconfig:
description:
- Path to a kubectl config file. Defaults to I(~/.kube/config)
@@ -310,19 +301,6 @@ class Connection(ConnectionBase):
return local_cmd, censored_local_cmd
def _local_env(self):
"""Return a dict of local environment variables to pass to the kubectl command"""
local_env = {}
local_local_env_vars_name = "{0}_local_env_vars".format(self.transport)
local_env_vars = self.get_option(local_local_env_vars_name)
if local_env_vars:
if isinstance(local_env_vars, dict):
local_env_vars = json.dumps(local_env_vars)
local_env = os.environ.copy()
local_env.update(json.loads(local_env_vars))
return local_env
return None
def _connect(self, port=None):
"""Connect to the container. Nothing to do"""
super(Connection, self)._connect()
@@ -351,7 +329,6 @@ class Connection(ConnectionBase):
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=self._local_env(),
)
stdout, stderr = p.communicate(in_data)
@@ -401,11 +378,7 @@ class Connection(ConnectionBase):
args = [to_bytes(i, errors="surrogate_or_strict") for i in args]
try:
p = subprocess.Popen(
args,
stdin=in_file,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=self._local_env(),
args, stdin=in_file, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
except OSError:
raise AnsibleError(
@@ -442,11 +415,7 @@ class Connection(ConnectionBase):
) as out_file:
try:
p = subprocess.Popen(
args,
stdin=subprocess.PIPE,
stdout=out_file,
stderr=subprocess.PIPE,
env=self._local_env(),
args, stdin=subprocess.PIPE, stdout=out_file, stderr=subprocess.PIPE
)
except OSError:
raise AnsibleError(

View File

@@ -36,12 +36,12 @@ options:
description:
- Provide a URL for accessing the API. Can also be specified via C(K8S_AUTH_HOST) environment variable.
type: str
version_added: 1.2.0
version_added: "1.2.0"
api_key:
description:
- Token used to authenticate with the API. Can also be specified via C(K8S_AUTH_API_KEY) environment variable.
type: str
version_added: 1.2.0
version_added: "1.2.0"
validate_certs:
description:
- Whether or not to verify the API server's SSL certificates. Can also be specified via C(K8S_AUTH_VERIFY_SSL)
@@ -49,12 +49,12 @@ options:
type: bool
aliases: [ verify_ssl ]
default: True
version_added: 1.2.0
version_added: "1.2.0"
ca_cert:
description:
- Path to a CA certificate used to authenticate with the API. The full certificate chain must be provided to
avoid certificate validation errors. Can also be specified via C(K8S_AUTH_SSL_CA_CERT) environment variable.
type: path
aliases: [ ssl_ca_cert ]
version_added: 1.2.0
version_added: "1.2.0"
"""

View File

@@ -15,7 +15,7 @@ class ModuleDocFragment(object):
options:
delete_options:
type: dict
version_added: 1.2.0
version_added: '1.2.0'
description:
- Configure behavior when deleting an object.
- Only used when I(state=absent).

View File

@@ -20,10 +20,10 @@ DOCUMENTATION = """
- Uses k8s.(yml|yaml) YAML configuration file to set parameter values.
deprecated:
removed_in: 5.0.0
removed_in: 4.0.0
why: |
As discussed in U(https://github.com/ansible-collections/kubernetes.core/issues/31), we decided to
remove the k8s inventory plugin in release 5.0.0.
remove the k8s inventory plugin in release 4.0.0.
alternative: "Use M(kubernetes.core.k8s_info) and M(ansible.builtin.add_host) instead."
options:
@@ -125,19 +125,19 @@ import json
from ansible.errors import AnsibleError
from ansible.plugins.inventory import BaseInventoryPlugin, Cacheable, Constructable
try:
from kubernetes.dynamic.exceptions import DynamicApiError
HAS_K8S_MODULE_HELPER = True
k8s_import_exception = None
except ImportError as e:
HAS_K8S_MODULE_HELPER = False
k8s_import_exception = e
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
HAS_K8S_MODULE_HELPER,
k8s_import_exception,
)
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
get_api_client,
)
try:
from kubernetes.dynamic.exceptions import DynamicApiError
except ImportError:
pass
def format_dynamic_api_exc(exc):
if exc.body:
@@ -164,8 +164,8 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
super(InventoryModule, self).parse(inventory, loader, path)
self.display.deprecated(
"The 'k8s' inventory plugin has been deprecated and will be removed in release 5.0.0",
version="5.0.0",
"The 'k8s' inventory plugin has been deprecated and will be removed in release 4.0.0",
version="4.0.0",
collection_name="kubernetes.core",
)
cache_key = self._get_cache_prefix(path)

View File

@@ -8,7 +8,7 @@ DOCUMENTATION = """
short_description: Build a set of kubernetes resources using a 'kustomization.yaml' file.
version_added: 2.2.0
version_added: "2.2.0"
author:
- Aubin Bikouo (@abikouo)
@@ -30,10 +30,6 @@ DOCUMENTATION = """
opt_dirs:
description:
- An optional list of directories to search for the executable in addition to PATH.
enable_helm:
description:
- Enable the helm chart inflation generator
default: "False"
requirements:
- "python >= 3.6"
@@ -41,20 +37,16 @@ DOCUMENTATION = """
EXAMPLES = """
- name: Run lookup using kustomize
ansible.builtin.set_fact:
set_fact:
resources: "{{ lookup('kubernetes.core.kustomize', binary_path='/path/to/kustomize') }}"
- name: Run lookup using kubectl kustomize
ansible.builtin.set_fact:
set_fact:
resources: "{{ lookup('kubernetes.core.kustomize', binary_path='/path/to/kubectl') }}"
- name: Create kubernetes resources for lookup output
kubernetes.core.k8s:
k8s:
definition: "{{ lookup('kubernetes.core.kustomize', dir='/path/to/kustomization') }}"
- name: Create kubernetes resources for lookup output with `--enable-helm` set
kubernetes.core.k8s:
definition: "{{ lookup('kubernetes.core.kustomize', dir='/path/to/kustomization', enable_helm=True) }}"
"""
RETURN = """
@@ -99,14 +91,7 @@ def run_command(command):
class LookupModule(LookupBase):
def run(
self,
terms,
variables=None,
dir=".",
binary_path=None,
opt_dirs=None,
enable_helm=False,
**kwargs
self, terms, variables=None, dir=".", binary_path=None, opt_dirs=None, **kwargs
):
executable_path = binary_path
if executable_path is None:
@@ -137,9 +122,6 @@ class LookupModule(LookupBase):
)
)
if enable_helm:
command += ["--enable-helm"]
(out, err) = run_command(command)
if err:
raise AnsibleLookupError(

View File

@@ -149,7 +149,6 @@ def k8s_apply(resource, definition, **kwargs):
force_conflicts=kwargs.get("force_conflicts"),
field_manager=kwargs.get("field_manager"),
dry_run=kwargs.get("dry_run"),
serialize=kwargs.get("serialize"),
)
if not existing:
return resource.create(
@@ -159,7 +158,6 @@ def k8s_apply(resource, definition, **kwargs):
return resource.get(
name=definition["metadata"]["name"],
namespace=definition["metadata"].get("namespace"),
**kwargs
)
return resource.patch(
body=desired,

File diff suppressed because it is too large Load Diff

View File

@@ -115,7 +115,7 @@ class AnsibleHelmModule(object):
kubeconfig = self.params.get("kubeconfig")
if kubeconfig:
if isinstance(kubeconfig, string_types):
with open(os.path.expanduser(kubeconfig)) as fd:
with open(kubeconfig) as fd:
kubeconfig_content = yaml.safe_load(fd)
elif isinstance(kubeconfig, dict):
kubeconfig_content = kubeconfig

View File

@@ -139,7 +139,6 @@ def perform_action(svc, definition: Dict, params: Dict) -> Dict:
result = {"changed": False, "result": {}}
instance = {}
warnings = []
resource = svc.find_resource(kind, api_version, fail=True)
definition["kind"] = resource.kind
@@ -173,7 +172,7 @@ def perform_action(svc, definition: Dict, params: Dict) -> Dict:
return result
if params.get("apply"):
instance, warnings = svc.apply(resource, definition, existing)
instance = svc.apply(resource, definition, existing)
result["method"] = "apply"
elif not existing:
if state == "patched":
@@ -184,19 +183,16 @@ def perform_action(svc, definition: Dict, params: Dict) -> Dict:
)
)
return result
instance, warnings = svc.create(resource, definition)
instance = svc.create(resource, definition)
result["method"] = "create"
result["changed"] = True
elif params.get("force", False):
instance, warnings = svc.replace(resource, definition, existing)
instance = svc.replace(resource, definition, existing)
result["method"] = "replace"
else:
instance, warnings = svc.update(resource, definition, existing)
instance = svc.update(resource, definition, existing)
result["method"] = "update"
if warnings:
result["warnings"] = warnings
# If needed, wait and/or create diff
success = True

View File

@@ -2,8 +2,6 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
import copy
from json import loads
from re import compile
from typing import Any, Dict, List, Optional, Tuple
from ansible.module_utils.common.dict_transformations import dict_merge
@@ -144,12 +142,18 @@ class K8sService:
name: str,
namespace: str,
merge_type: str = None,
) -> Tuple[Dict, List[str]]:
) -> Dict:
if merge_type == "json":
self.module.deprecate(
msg="json as a merge_type value is deprecated. Please use the k8s_json_patch module instead.",
version="4.0.0",
collection_name="kubernetes.core",
)
try:
params = dict(name=name, namespace=namespace, serialize=False)
params = dict(name=name, namespace=namespace)
if merge_type:
params["content_type"] = "application/{0}-patch+json".format(merge_type)
return decode_response(self.client.patch(resource, definition, **params))
return self.client.patch(resource, definition, **params).to_dict()
except Exception as e:
reason = e.body if hasattr(e, "body") else e
msg = "Failed to patch object: {0}".format(reason)
@@ -326,124 +330,123 @@ class K8sService:
result["resources"].append(hide_fields(res, hidden_fields))
return result
def create(self, resource: Resource, definition: Dict) -> Tuple[Dict, List[str]]:
def create(self, resource: Resource, definition: Dict) -> Dict:
namespace = definition["metadata"].get("namespace")
name = definition["metadata"].get("name")
if self._client_side_dry_run:
return _encode_stringdata(definition), []
try:
return decode_response(
self.client.create(
resource, definition, namespace=namespace, serialize=False
k8s_obj = _encode_stringdata(definition)
else:
try:
k8s_obj = self.client.create(
resource, definition, namespace=namespace
).to_dict()
except ConflictError:
# Some resources, like ProjectRequests, can't be created multiple times,
# because the resources that they create don't match their kind
# In this case we'll mark it as unchanged and warn the user
self.module.warn(
"{0} was not found, but creating it returned a 409 Conflict error. This can happen \
if the resource you are creating does not directly create a resource of the same kind.".format(
name
)
)
)
except ConflictError:
# Some resources, like ProjectRequests, can't be created multiple times,
# because the resources that they create don't match their kind
# In this case we'll mark it as unchanged and warn the user
self.module.warn(
"{0} was not found, but creating it returned a 409 Conflict error. This can happen \
if the resource you are creating does not directly create a resource of the same kind.".format(
name
)
)
return dict(), []
except Exception as e:
reason = e.body if hasattr(e, "body") else e
msg = "Failed to create object: {0}".format(reason)
raise CoreException(msg) from e
return dict()
except Exception as e:
reason = e.body if hasattr(e, "body") else e
msg = "Failed to create object: {0}".format(reason)
raise CoreException(msg) from e
return k8s_obj
def apply(
self,
resource: Resource,
definition: Dict,
existing: Optional[ResourceInstance] = None,
) -> Tuple[Dict, List[str]]:
) -> Dict:
namespace = definition["metadata"].get("namespace")
server_side_apply = self.module.params.get("server_side_apply")
if server_side_apply:
requires("kubernetes", "19.15.0", reason="to use server side apply")
if self._client_side_dry_run:
ignored, patch = apply_object(resource, _encode_stringdata(definition))
if existing:
return dict_merge(existing.to_dict(), patch), []
k8s_obj = dict_merge(existing.to_dict(), patch)
else:
return patch, []
try:
params = {}
if server_side_apply:
params["server_side"] = True
params.update(server_side_apply)
return decode_response(
self.client.apply(
resource, definition, namespace=namespace, serialize=False, **params
)
)
except Exception as e:
reason = e.body if hasattr(e, "body") else e
msg = "Failed to apply object: {0}".format(reason)
raise CoreException(msg) from e
k8s_obj = patch
else:
try:
params = {}
if server_side_apply:
params["server_side"] = True
params.update(server_side_apply)
k8s_obj = self.client.apply(
resource, definition, namespace=namespace, **params
).to_dict()
except Exception as e:
reason = e.body if hasattr(e, "body") else e
msg = "Failed to apply object: {0}".format(reason)
raise CoreException(msg) from e
return k8s_obj
def replace(
self,
resource: Resource,
definition: Dict,
existing: ResourceInstance,
) -> Tuple[Dict, List[str]]:
) -> Dict:
append_hash = self.module.params.get("append_hash", False)
name = definition["metadata"].get("name")
namespace = definition["metadata"].get("namespace")
if self._client_side_dry_run:
return _encode_stringdata(definition), []
try:
return decode_response(
self.client.replace(
k8s_obj = _encode_stringdata(definition)
else:
try:
k8s_obj = self.client.replace(
resource,
definition,
name=name,
namespace=namespace,
append_hash=append_hash,
serialize=False,
)
)
except Exception as e:
reason = e.body if hasattr(e, "body") else e
msg = "Failed to replace object: {0}".format(reason)
raise CoreException(msg) from e
).to_dict()
except Exception as e:
reason = e.body if hasattr(e, "body") else e
msg = "Failed to replace object: {0}".format(reason)
raise CoreException(msg) from e
return k8s_obj
def update(
self, resource: Resource, definition: Dict, existing: ResourceInstance
) -> Tuple[Dict, List[str]]:
) -> Dict:
name = definition["metadata"].get("name")
namespace = definition["metadata"].get("namespace")
if self._client_side_dry_run:
return dict_merge(existing.to_dict(), _encode_stringdata(definition)), []
exception = None
for merge_type in self.module.params.get("merge_type") or [
"strategic-merge",
"merge",
]:
try:
return self.patch_resource(
resource,
definition,
name,
namespace,
merge_type=merge_type,
)
except CoreException as e:
exception = e
continue
raise exception
k8s_obj = dict_merge(existing.to_dict(), _encode_stringdata(definition))
else:
exception = None
for merge_type in self.module.params.get("merge_type") or [
"strategic-merge",
"merge",
]:
try:
k8s_obj = self.patch_resource(
resource,
definition,
name,
namespace,
merge_type=merge_type,
)
exception = None
except CoreException as e:
exception = e
continue
break
if exception:
raise exception
return k8s_obj
def delete(
self,
@@ -540,83 +543,3 @@ def hide_field(definition: dict, hidden_field: str) -> dict:
else:
del definition[split[0]]
return definition
def decode_response(resp) -> Tuple[Dict, List[str]]:
"""
This function decodes unserialized responses from the Kubernetes python
client and decodes the RFC2616 14.46 warnings found in the response
headers.
"""
obj = ResourceInstance(None, loads(resp.data.decode("utf8"))).to_dict()
warnings = []
if (
resp.headers is not None
and "warning" in resp.headers
and resp.headers["warning"] is not None
):
warnings = resp.headers["warning"].split(", ")
return obj, decode_warnings(warnings)
def decode_warnings(warnings: str) -> List[str]:
"""
This function decodes RFC2616 14.46 warnings in a simplified way, where
only the warn-texts are returned in a list.
"""
p = compile('\\d{3} .+ (".+")')
decoded = []
for warning in warnings:
m = p.match(warning)
if m:
try:
parsed, unused = parse_quoted_string(m.group(1))
decoded.append(parsed)
except ValueError:
continue
return decoded
def parse_quoted_string(quoted_string: str) -> Tuple[str, str]:
"""
This function was adapted from:
https://github.com/kubernetes/apimachinery/blob/bb8822152cabfb4f34dbc26270f874ce53db50de/pkg/util/net/http.go#L609
"""
if len(quoted_string) == 0:
raise ValueError("invalid quoted string: 0-length")
if quoted_string[0] != '"':
raise ValueError("invalid quoted string: missing initial quote")
quoted_string = quoted_string[1:]
remainder = ""
escaping = False
closed_quote = False
result = []
for i, b in enumerate(quoted_string):
if b == '"':
if escaping:
result.append(b)
escaping = False
else:
closed_quote = True
remainder_start = i + 1
remainder = quoted_string[remainder_start:].strip()
break
elif b == "\\":
if escaping:
result.append(b)
escaping = False
else:
escaping = True
else:
result.append(b)
escaping = False
if not closed_quote:
raise ValueError("invalid quoted string: missing closing quote")
return "".join(result), remainder

View File

@@ -14,7 +14,7 @@ module: helm
short_description: Manages Kubernetes packages with the Helm package manager
version_added: 0.11.0
version_added: "0.11.0"
author:
- Lucas Boisserie (@LucasBoisserie)
@@ -61,7 +61,7 @@ options:
default: false
type: bool
aliases: [ dep_up ]
version_added: 2.4.0
version_added: "2.4.0"
release_name:
description:
- Release name to manage.
@@ -99,7 +99,7 @@ options:
default: []
type: list
elements: str
version_added: 1.1.0
version_added: '1.1.0'
update_repo_cache:
description:
- Run C(helm repo update) before the operation. Can be run as part of the package installation or as a separate step (see Examples).
@@ -129,7 +129,7 @@ options:
- string
- json
- file
version_added: 2.4.0
version_added: '2.4.0'
reuse_values:
description:
- When upgrading package, specifies wether to reuse the last release's values and merge in any overrides from parameters I(release_values),
@@ -137,14 +137,14 @@ options:
- If I(reset_values) is set to C(True), this is ignored.
type: bool
required: false
version_added: 2.5.0
version_added: '2.5.0'
reset_values:
description:
- When upgrading package, reset the values to the ones built into the chart.
type: bool
required: false
default: True
version_added: 2.5.0
version_added: '2.5.0'
#Helm options
disable_hook:
@@ -181,7 +181,7 @@ options:
- similar to C(wait_timeout) but does not required C(wait) to be activated.
- Mutually exclusive with C(wait_timeout).
type: str
version_added: 2.3.0
version_added: "2.3.0"
atomic:
description:
- If set, the installation process deletes the installation on failure.
@@ -192,12 +192,12 @@ options:
- Create the release namespace if not present.
type: bool
default: False
version_added: 0.11.1
version_added: "0.11.1"
post_renderer:
description:
- Path to an executable to be used for post rendering.
type: str
version_added: 2.4.0
version_added: "2.4.0"
replace:
description:
- Reuse the given name, only if that name is a deleted release which remains in the history.
@@ -205,19 +205,19 @@ options:
- mutually exclusive with with C(history_max).
type: bool
default: False
version_added: 1.11.0
version_added: "1.11.0"
skip_crds:
description:
- Skip custom resource definitions when installing or upgrading.
type: bool
default: False
version_added: 1.2.0
version_added: "1.2.0"
history_max:
description:
- Limit the maximum number of revisions saved per release.
- mutually exclusive with with C(replace).
type: int
version_added: 2.2.0
version_added: "2.2.0"
extends_documentation_fragment:
- kubernetes.core.helm_common_options
"""

View File

@@ -14,7 +14,7 @@ module: helm_info
short_description: Get information from Helm package deployed inside the cluster
version_added: 0.11.0
version_added: "0.11.0"
author:
- Lucas Boisserie (@LucasBoisserie)
@@ -53,7 +53,7 @@ options:
type: list
elements: str
default: []
version_added: 2.3.0
version_added: "2.3.0"
get_all_values:
description:
- Set to C(True) if you want to get all (computed) values of the release.
@@ -61,7 +61,7 @@ options:
required: false
default: false
type: bool
version_added: 2.4.0
version_added: "2.4.0"
extends_documentation_fragment:
- kubernetes.core.helm_common_options
"""
@@ -123,18 +123,18 @@ status:
elements: dict
description: Hooks of the release
returned: always
version_added: 2.4.0
version_added: "2.4.0"
notes:
type: str
description: Notes of the release
returned: always
version_added: 2.4.0
version_added: "2.4.0"
manifest:
type: list
elements: dict
description: Manifest of the release
returned: always
version_added: 2.4.0
version_added: "2.4.0"
"""
import copy

View File

@@ -12,7 +12,7 @@ DOCUMENTATION = r"""
---
module: helm_plugin
short_description: Manage Helm plugins
version_added: 1.0.0
version_added: "1.0.0"
author:
- Abhijeet Kasurde (@Akasurde)
requirements:
@@ -47,7 +47,7 @@ options:
- Ignored when C(state=absent) or C(state=latest).
required: false
type: str
version_added: 2.3.0
version_added: "2.3.0"
extends_documentation_fragment:
- kubernetes.core.helm_common_options
"""

View File

@@ -12,7 +12,7 @@ DOCUMENTATION = r"""
---
module: helm_plugin_info
short_description: Gather information about Helm plugins
version_added: 1.0.0
version_added: "1.0.0"
author:
- Abhijeet Kasurde (@Akasurde)
requirements:

View File

@@ -12,7 +12,7 @@ DOCUMENTATION = r"""
---
module: helm_pull
short_description: download a chart from a repository and (optionally) unpack it in local directory.
version_added: 2.4.0
version_added: "2.4.0"
author:
- Aubin Bikouo (@abikouo)
description:

View File

@@ -14,7 +14,7 @@ module: helm_repository
short_description: Manage Helm repositories.
version_added: 0.11.0
version_added: "0.11.0"
author:
- Lucas Boisserie (@LucasBoisserie)
@@ -76,12 +76,12 @@ options:
description:
- Provide a URL for accessing the API. Can also be specified via C(K8S_AUTH_HOST) environment variable.
type: str
version_added: 2.3.0
version_added: "2.3.0"
api_key:
description:
- Token used to authenticate with the API. Can also be specified via C(K8S_AUTH_API_KEY) environment variable.
type: str
version_added: 2.3.0
version_added: "2.3.0"
validate_certs:
description:
- Whether or not to verify the API server's SSL certificates. Can also be specified via C(K8S_AUTH_VERIFY_SSL)
@@ -89,21 +89,21 @@ options:
type: bool
aliases: [ verify_ssl ]
default: True
version_added: 2.3.0
version_added: "2.3.0"
ca_cert:
description:
- Path to a CA certificate used to authenticate with the API. The full certificate chain must be provided to
avoid certificate validation errors. Can also be specified via C(K8S_AUTH_SSL_CA_CERT) environment variable.
type: path
aliases: [ ssl_ca_cert ]
version_added: 2.3.0
version_added: "2.3.0"
context:
description:
- Helm option to specify which kubeconfig context to use.
- If the value is not specified in the task, the value of environment variable C(K8S_AUTH_CONTEXT) will be used instead.
type: str
aliases: [ kube_context ]
version_added: 2.4.0
version_added: "2.4.0"
kubeconfig:
description:
- Helm option to specify kubeconfig path to use.
@@ -111,14 +111,14 @@ options:
- The configuration can be provided as dictionary.
type: raw
aliases: [ kubeconfig_path ]
version_added: 2.4.0
version_added: "2.4.0"
force_update:
description:
- Whether or not to replace (overwrite) the repo if it already exists.
type: bool
aliases: [ force ]
default: False
version_added: 2.4.0
version_added: "2.4.0"
"""
EXAMPLES = r"""

View File

@@ -53,7 +53,7 @@ options:
default: false
type: bool
aliases: [ dep_up ]
version_added: 2.4.0
version_added: "2.4.0"
disable_hook:
description:
- Prevent hooks from running during install.
@@ -139,7 +139,7 @@ options:
- string
- json
- file
version_added: 2.4.0
version_added: '2.4.0'
"""
EXAMPLES = r"""

View File

@@ -57,14 +57,15 @@ options:
- Whether to override the default patch merge approach with a specific type. By 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".
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)
- If more than one C(merge_type) is given, the merge_types will be tried in order. This defaults to
C(['strategic-merge', 'merge']), which is ideal for using the same parameters on resource kinds that
combine Custom Resources and built-in resources.
- Mutually exclusive with C(apply).
- I(merge_type=json) has been removed in version 4.0.0. Please use M(kubernetes.core.k8s_json_patch) instead.
- mutually exclusive with C(apply)
- I(merge_type=json) is deprecated and will be removed in version 3.0.0. Please use M(kubernetes.core.k8s_json_patch) instead.
choices:
- json
- merge
- strategic-merge
type: list
@@ -100,7 +101,7 @@ options:
- C(apply) compares the desired resource definition with the previously supplied resource definition,
ignoring properties that are automatically generated
- C(apply) works better with Services than 'force=yes'
- Mutually exclusive with C(merge_type).
- mutually exclusive with C(merge_type)
default: False
type: bool
template:
@@ -459,7 +460,7 @@ def argspec():
argument_spec.update(copy.deepcopy(AUTH_ARG_SPEC))
argument_spec.update(copy.deepcopy(WAIT_ARG_SPEC))
argument_spec["merge_type"] = dict(
type="list", elements="str", choices=["merge", "strategic-merge"]
type="list", elements="str", choices=["json", "merge", "strategic-merge"]
)
argument_spec["validate"] = dict(type="dict", default=None, options=validate_spec())
argument_spec["append_hash"] = dict(type="bool", default=False)

View File

@@ -11,7 +11,7 @@ __metaclass__ = type
DOCUMENTATION = r"""
module: k8s_cluster_info
version_added: 0.11.1
version_added: "0.11.1"
short_description: Describe Kubernetes (K8s) cluster, APIs available and their respective versions

View File

@@ -14,7 +14,7 @@ module: k8s_cp
short_description: Copy files and directories to and from pod.
version_added: 2.2.0
version_added: "2.2.0"
author:
- Aubin Bikouo (@abikouo)

View File

@@ -15,7 +15,7 @@ module: k8s_drain
short_description: Drain, Cordon, or Uncordon node in k8s cluster
version_added: 2.2.0
version_added: "2.2.0"
author: Aubin Bikouo (@abikouo)

View File

@@ -15,7 +15,7 @@ module: k8s_exec
short_description: Execute command in Pod
version_added: 0.10.0
version_added: "0.10.0"
author: "Tristan de Cacqueray (@tristanC)"
@@ -135,7 +135,7 @@ from ansible.module_utils._text import to_native
from ansible_collections.kubernetes.core.plugins.module_utils.ansiblemodule import (
AnsibleModule,
)
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
AUTH_ARG_SPEC,
)
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
@@ -219,6 +219,12 @@ def execute_module(module, client):
else:
rc = int(err["details"]["causes"][0]["message"])
module.deprecate(
"The 'return_code' return key is being renamed to 'rc'. "
"Both keys are being returned for now to allow users to migrate their automation.",
version="4.0.0",
collection_name="kubernetes.core",
)
module.exit_json(
# Some command might change environment, but ultimately failing at end
changed=True,

View File

@@ -14,7 +14,7 @@ module: k8s_log
short_description: Fetch logs from Kubernetes resources
version_added: 0.10.0
version_added: "0.10.0"
author:
- "Fabian von Feilitzsch (@fabianvf)"
@@ -61,26 +61,26 @@ options:
- A relative time in seconds before the current time from which to show logs.
required: no
type: str
version_added: 2.2.0
version_added: '2.2.0'
previous:
description:
- If C(true), print the logs for the previous instance of the container in a pod if it exists.
required: no
type: bool
default: False
version_added: 2.4.0
version_added: '2.4.0'
tail_lines:
description:
- A number of lines from the end of the logs to retrieve.
required: no
type: int
version_added: 2.4.0
version_added: '2.4.0'
all_containers:
description:
- If set to C(true), retrieve all containers' logs in the pod(s).
- mutually exclusive with C(container).
type: bool
version_added: 2.4.0
version_added: '2.4.0'
requirements:
- "python >= 3.9"

View File

@@ -12,7 +12,7 @@ __metaclass__ = type
DOCUMENTATION = r"""
module: k8s_rollback
short_description: Rollback Kubernetes (K8S) Deployments and DaemonSets
version_added: 1.0.0
version_added: "1.0.0"
author:
- "Julien Huon (@julienhuon)"
description:

View File

@@ -13,7 +13,7 @@ __metaclass__ = type
DOCUMENTATION = r"""
module: k8s_taint
short_description: Taint a node in a Kubernetes/OpenShift cluster
version_added: 2.3.0
version_added: "2.3.0"
author: Alina Buzachis (@alinabuzachis)
description:
- Taint allows a node to refuse Pod to be scheduled unless that Pod has a matching toleration.

View File

@@ -73,7 +73,7 @@
assert:
that:
- install is changed
- install.status.chart == chart_test+"-"+chart_test_version
- install.status.chart == "{{ chart_test }}-{{ chart_test_version }}"
- install.status.status | lower == 'deployed'
- name: Check helm_info content
@@ -95,7 +95,7 @@
- name: "Assert that {{ chart_test }} is installed from {{ source }} with helm_info"
assert:
that:
- content_info.status.chart == chart_test+"-"+chart_test_version
- content_info.status.chart == "{{ chart_test }}-{{ chart_test_version }}"
- content_info.status.status | lower == 'deployed'
- release_state_content_info.status.status | lower == 'deployed'
@@ -112,7 +112,7 @@
assert:
that:
- install is not changed
- install.status.chart == chart_test+"-"+chart_test_version
- install.status.chart == "{{ chart_test }}-{{ chart_test_version }}"
- install.status.status | lower == 'deployed'
- name: "Add vars to {{ chart_test }} from {{ source }}"
@@ -130,7 +130,7 @@
that:
- install is changed
- install.status.status | lower == 'deployed'
- install.status.chart == chart_test+"-"+chart_test_version
- install.status.chart == "{{ chart_test }}-{{ chart_test_version }}"
- "install.status['values'].revisionHistoryLimit == 0"
- name: Check idempotency after adding vars
@@ -148,7 +148,7 @@
that:
- install is not changed
- install.status.status | lower == 'deployed'
- install.status.chart == chart_test+"-"+chart_test_version
- install.status.chart == "{{ chart_test }}-{{ chart_test_version }}"
- "install.status['values'].revisionHistoryLimit == 0"
- name: "Remove Vars to {{ chart_test }} from {{ source }}"
@@ -165,7 +165,7 @@
that:
- install is changed
- install.status.status | lower == 'deployed'
- install.status.chart == chart_test+"-"+chart_test_version
- install.status.chart == "{{ chart_test }}-{{ chart_test_version }}"
- install.status['values'] == {}
- name: Check idempotency after removing vars
@@ -182,7 +182,7 @@
that:
- install is not changed
- install.status.status | lower == 'deployed'
- install.status.chart == chart_test+"-"+chart_test_version
- install.status.chart == "{{ chart_test }}-{{ chart_test_version }}"
- install.status['values'] == {}
- name: "Upgrade {{ chart_test }} from {{ source }}"
@@ -199,7 +199,7 @@
that:
- install is changed
- install.status.status | lower == 'deployed'
- install.status.chart == chart_test+"-"+chart_test_version_upgrade
- install.status.chart == "{{ chart_test }}-{{ chart_test_version_upgrade }}"
- name: Check idempotency after upgrade
helm:
@@ -215,7 +215,7 @@
that:
- install is not changed
- install.status.status | lower == 'deployed'
- install.status.chart == chart_test+"-"+chart_test_version_upgrade
- install.status.chart == "{{ chart_test }}-{{ chart_test_version_upgrade }}"
- name: "Remove {{ chart_test }} from {{ source }}"
helm:
@@ -316,7 +316,7 @@
that:
- install is changed
- install.status.status | lower == 'deployed'
- install.status.chart == chart_test+"-"+chart_test_version
- install.status.chart == "{{ chart_test }}-{{ chart_test_version }}"
- "install.status['values'].revisionHistoryLimit == 0"
- name: "Install {{ chart_test }} from {{ source }} with values_files (again)"
@@ -357,7 +357,7 @@
- result is changed
- result is not failed
- result.rc == 0
- result.command is match(helm_binary+" template "+chart_source)
- result.command is match("{{ helm_binary }} template {{ chart_source }}")
- name: Check templates created
stat:
@@ -388,7 +388,7 @@
- result is changed
- result is not failed
- result.rc == 0
- result.command is match(helm_binary+" template MyRelease "+chart_source)
- result.command is match("{{ helm_binary }} template MyRelease {{ chart_source }}")
- result.stdout is search("ThisValue")
when: chart_source is search("test-chart")
# limit assertion of test result to controlled (local) chart_source

View File

@@ -182,7 +182,7 @@
- name: assert that pods are running on cordoned node
assert:
that:
- Pod.resources | selectattr('status.phase', 'equalto', 'Running') | selectattr('spec.nodeName', 'equalto', node_to_drain) | list | length > 0
- "{{ Pod.resources | selectattr('status.phase', 'equalto', 'Running') | selectattr('spec.nodeName', 'equalto', node_to_drain) | list | length > 0 }}"
- name: Uncordon node
k8s_drain:
@@ -236,7 +236,7 @@
assert:
that:
- drain_result is changed
- '"node "+node_to_drain+" marked unschedulable." in drain_result.result'
- '"node {{ node_to_drain }} marked unschedulable." in drain_result.result'
- name: assert that unmanaged pod were deleted
k8s_info:
@@ -338,7 +338,7 @@
assert:
that:
- disable_evict is changed
- '"node "+node_to_drain+" marked unschedulable." in disable_evict.result'
- '"node {{ node_to_drain }} marked unschedulable." in disable_evict.result'
- name: assert that unmanaged pod were deleted
k8s_info:
@@ -401,7 +401,7 @@
assert:
that:
- drain_pod_selector is changed
- '"node "+node_to_drain+" marked unschedulable." in drain_pod_selector.result'
- '"node {{ node_to_drain }} marked unschedulable." in drain_pod_selector.result'
- name: assert that pod created before is still running
k8s_info:
@@ -429,8 +429,8 @@
assert:
that:
- drain_pod_selector_equal is changed
- '"node "+node_to_drain+" already marked unschedulable." in drain_pod_selector_equal.result'
- '"Deleting Pods not managed by ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet: "+test_namespace+"/ansible-drain-pod." in drain_pod_selector_equal.warnings'
- '"node {{ node_to_drain }} already marked unschedulable." in drain_pod_selector_equal.result'
- '"Deleting Pods not managed by ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet: {{ test_namespace }}/ansible-drain-pod." in drain_pod_selector_equal.warnings'
- name: Uncordon node
k8s_drain:

View File

@@ -424,7 +424,7 @@
- assert:
that:
- result.resources[0].data.testkey == (cmap_data.stdout | b64encode)
- result.resources[0].data.testkey == "{{ cmap_data.stdout | b64encode }}"
# test setting module defaults for kubernetes.core.k8s_info
- block:

View File

@@ -69,7 +69,7 @@
- name: assert pod has been created
assert:
that:
- pods.resources | length == 1
- "{{ pods.resources | length == 1 }}"
- name: create pod using generate_name parameter should succeed
k8s:
@@ -86,7 +86,7 @@
- name: assert pod has been created
assert:
that:
- pods.resources | length == 2
- "{{ pods.resources | length == 2 }}"
- name: create pod using metadata.generateName parameter should succeed
k8s:
@@ -102,7 +102,7 @@
- name: assert pod has been created
assert:
that:
- pods.resources | length == 3
- "{{ pods.resources | length == 3 }}"
- name: create object using metadata.generateName should support wait option
k8s:

View File

@@ -192,7 +192,7 @@
- name: Check that module waited
assert:
that:
- ( lookup('pipe', 'date +%s')|int - start|int ) > 30
- "{{ lookup('pipe', 'date +%s') }} - {{ start }} > 30"
- name: Create simple pod
k8s:

View File

@@ -11,7 +11,7 @@
assert:
that:
- fake_pod is failed
- fake_pod.msg == "Pod "+test_namespace+"/this_pod_does_exist not found."
- 'fake_pod.msg == "Pod {{ test_namespace }}/this_pod_does_exist not found."'
- name: create hello-world deployment
k8s:

View File

@@ -65,7 +65,7 @@
assert:
that:
- _result.result.status.phase == 'Running'
- _result.result.spec.nodeName == node_to_taint
- _result.result.spec.nodeName == "{{ node_to_taint }}"
- name: Taint node (check_mode)
kubernetes.core.k8s_taint:
@@ -89,8 +89,8 @@
assert:
that:
- _result.changed
- item['effect'] == taint_patch_1[0]['effect']
- item['key'] == taint_patch_1[0]['key']
- "{{ item['effect'] == taint_patch_1[0]['effect'] }}"
- "{{ item['key'] == taint_patch_1[0]['key'] }}"
loop: "{{ _result.result.spec.taints }}"
- name: Taint node (idempotency) - (check_mode)

View File

@@ -213,8 +213,8 @@
- name: check that resources creation failed
assert:
that:
- resource.results.0.resources | length == 0
- resource.results.1.resources | length == 0
- '{{ resource.results[0].resources | length == 0 }}'
- '{{ resource.results[1].resources | length == 0 }}'
- name: create pod without namespace (continue_on_error = true)
kubernetes.core.k8s:

View File

@@ -130,9 +130,9 @@
assert:
that:
- result_configmap.apiVersion == 'v1'
- result_configmap.metadata.name == configmap_name
- result_configmap.metadata.namespace == test_namespace[2]
- result_configmap.data.value == configmap_data
- result_configmap.metadata.name == "{{ configmap_name }}"
- result_configmap.metadata.namespace == "{{ test_namespace[2] }}"
- result_configmap.data.value == "{{ configmap_data }}"
# test lookup plugin using src parameter
- block:
@@ -159,9 +159,9 @@
assert:
that:
- src_configmap.apiVersion == 'v1'
- src_configmap.metadata.name == configmap_name
- src_configmap.metadata.namespace == test_namespace[2]
- src_configmap.data.value == configmap_data
- src_configmap.metadata.name == "{{ configmap_name }}"
- src_configmap.metadata.namespace == "{{ test_namespace[2] }}"
- src_configmap.data.value == "{{ configmap_data }}"
always:
- name: Delete temporary file created
@@ -198,9 +198,9 @@
assert:
that:
- configmap_no_ssl.apiVersion == 'v1'
- configmap_no_ssl.metadata.name == configmap_name
- configmap_no_ssl.metadata.namespace == test_namespace[2]
- configmap_no_ssl.data.value == configmap_data
- configmap_no_ssl.metadata.name == "{{ configmap_name }}"
- configmap_no_ssl.metadata.namespace == "{{ test_namespace[2] }}"
- configmap_no_ssl.data.value == "{{ configmap_data }}"
- name: Retrieve configmap using authentication aliases (validate_certs=true)
set_fact:
@@ -210,9 +210,9 @@
assert:
that:
- configmap_with_ssl.apiVersion == 'v1'
- configmap_with_ssl.metadata.name == configmap_name
- configmap_with_ssl.metadata.namespace == test_namespace[2]
- configmap_with_ssl.data.value == configmap_data
- configmap_with_ssl.metadata.name == "{{ configmap_name }}"
- configmap_with_ssl.metadata.namespace == "{{ test_namespace[2] }}"
- configmap_with_ssl.data.value == "{{ configmap_data }}"
always:
- name: Delete temporary directory

View File

@@ -1,9 +1,18 @@
plugins/module_utils/client/discovery.py import-3.6!skip
plugins/module_utils/client/discovery.py import-3.7!skip
plugins/module_utils/client/discovery.py import-3.8!skip
plugins/module_utils/client/discovery.py import-3.9!skip
plugins/module_utils/client/discovery.py import-3.10!skip
plugins/module_utils/client/discovery.py import-3.11!skip
plugins/module_utils/client/resource.py import-3.6!skip
plugins/module_utils/client/resource.py import-3.7!skip
plugins/module_utils/client/resource.py import-3.8!skip
plugins/module_utils/client/resource.py import-3.9!skip
plugins/module_utils/client/resource.py import-3.10!skip
plugins/module_utils/client/resource.py import-3.11!skip
plugins/module_utils/k8sdynamicclient.py import-3.6!skip
plugins/module_utils/k8sdynamicclient.py import-3.7!skip
plugins/module_utils/k8sdynamicclient.py import-3.8!skip
plugins/module_utils/k8sdynamicclient.py import-3.9!skip
plugins/module_utils/k8sdynamicclient.py import-3.10!skip
plugins/module_utils/k8sdynamicclient.py import-3.11!skip

View File

@@ -1,9 +1,18 @@
plugins/module_utils/client/discovery.py import-3.6!skip
plugins/module_utils/client/discovery.py import-3.7!skip
plugins/module_utils/client/discovery.py import-3.8!skip
plugins/module_utils/client/discovery.py import-3.9!skip
plugins/module_utils/client/discovery.py import-3.10!skip
plugins/module_utils/client/discovery.py import-3.11!skip
plugins/module_utils/client/resource.py import-3.6!skip
plugins/module_utils/client/resource.py import-3.7!skip
plugins/module_utils/client/resource.py import-3.8!skip
plugins/module_utils/client/resource.py import-3.9!skip
plugins/module_utils/client/resource.py import-3.10!skip
plugins/module_utils/client/resource.py import-3.11!skip
plugins/module_utils/k8sdynamicclient.py import-3.6!skip
plugins/module_utils/k8sdynamicclient.py import-3.7!skip
plugins/module_utils/k8sdynamicclient.py import-3.8!skip
plugins/module_utils/k8sdynamicclient.py import-3.9!skip
plugins/module_utils/k8sdynamicclient.py import-3.10!skip
plugins/module_utils/k8sdynamicclient.py import-3.11!skip

View File

@@ -1,11 +1,20 @@
plugins/module_utils/client/discovery.py import-3.6!skip
plugins/module_utils/client/discovery.py import-3.7!skip
plugins/module_utils/client/discovery.py import-3.8!skip
plugins/module_utils/client/discovery.py import-3.9!skip
plugins/module_utils/client/discovery.py import-3.10!skip
plugins/module_utils/client/discovery.py import-3.11!skip
plugins/module_utils/client/discovery.py import-3.12!skip
plugins/module_utils/client/resource.py import-3.6!skip
plugins/module_utils/client/resource.py import-3.7!skip
plugins/module_utils/client/resource.py import-3.8!skip
plugins/module_utils/client/resource.py import-3.9!skip
plugins/module_utils/client/resource.py import-3.10!skip
plugins/module_utils/client/resource.py import-3.11!skip
plugins/module_utils/client/resource.py import-3.12!skip
plugins/module_utils/k8sdynamicclient.py import-3.6!skip
plugins/module_utils/k8sdynamicclient.py import-3.7!skip
plugins/module_utils/k8sdynamicclient.py import-3.8!skip
plugins/module_utils/k8sdynamicclient.py import-3.9!skip
plugins/module_utils/k8sdynamicclient.py import-3.10!skip
plugins/module_utils/k8sdynamicclient.py import-3.11!skip

View File

@@ -1,31 +0,0 @@
plugins/module_utils/client/discovery.py import-3.9!skip
plugins/module_utils/client/discovery.py import-3.10!skip
plugins/module_utils/client/discovery.py import-3.11!skip
plugins/module_utils/client/discovery.py import-3.12!skip
plugins/module_utils/client/resource.py import-3.9!skip
plugins/module_utils/client/resource.py import-3.10!skip
plugins/module_utils/client/resource.py import-3.11!skip
plugins/module_utils/client/resource.py import-3.12!skip
plugins/module_utils/k8sdynamicclient.py import-3.9!skip
plugins/module_utils/k8sdynamicclient.py import-3.10!skip
plugins/module_utils/k8sdynamicclient.py import-3.11!skip
plugins/module_utils/k8sdynamicclient.py import-3.12!skip
plugins/module_utils/version.py pylint!skip
plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc
plugins/modules/k8s_scale.py validate-modules:parameter-type-not-in-doc
plugins/modules/k8s_service.py validate-modules:parameter-type-not-in-doc
tests/unit/module_utils/fixtures/definitions.yml yamllint!skip
tests/unit/module_utils/fixtures/deployments.yml yamllint!skip
tests/integration/targets/k8s_delete/files/deployments.yaml yamllint!skip
tests/unit/module_utils/fixtures/pods.yml yamllint!skip
tests/integration/targets/helm/files/appversionless-chart-v2/templates/configmap.yaml yamllint!skip
tests/integration/targets/helm/files/appversionless-chart/templates/configmap.yaml yamllint!skip
tests/integration/targets/helm/files/test-chart-v2/templates/configmap.yaml yamllint!skip
tests/integration/targets/helm/files/test-chart/templates/configmap.yaml yamllint!skip
tests/integration/targets/helm_diff/files/test-chart/templates/configmap.yaml yamllint!skip
tests/integration/targets/k8s_scale/files/deployment.yaml yamllint!skip
plugins/modules/k8s.py validate-modules:return-syntax-error
plugins/modules/k8s_scale.py validate-modules:return-syntax-error
plugins/modules/k8s_service.py validate-modules:return-syntax-error
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip

View File

@@ -31,7 +31,7 @@ modified_def["metadata"]["labels"]["environment"] = "testing"
@pytest.mark.parametrize(
"action, params, existing, instance_warnings, expected",
"action, params, existing, instance, expected",
[
(
"delete",
@@ -51,26 +51,14 @@ modified_def["metadata"]["labels"]["environment"] = "testing"
"apply",
{"apply": "yes"},
{},
(definition, []),
definition,
{"changed": True, "method": "apply", "result": definition},
),
(
"apply",
{"apply": "yes"},
{},
(definition, ["test warning"]),
{
"changed": True,
"method": "apply",
"result": definition,
"warnings": ["test warning"],
},
),
(
"create",
{"state": "patched"},
{},
({}, []),
{},
{
"changed": False,
"result": {},
@@ -83,78 +71,42 @@ modified_def["metadata"]["labels"]["environment"] = "testing"
"create",
{},
{},
(definition, []),
definition,
{"changed": True, "method": "create", "result": definition},
),
(
"create",
{},
{},
(definition, ["test warning"]),
{
"changed": True,
"method": "create",
"result": definition,
"warnings": ["test warning"],
},
),
(
"replace",
{"force": "yes"},
definition,
(definition, []),
definition,
{"changed": False, "method": "replace", "result": definition},
),
(
"replace",
{"force": "yes"},
definition,
(modified_def, []),
modified_def,
{"changed": True, "method": "replace", "result": modified_def},
),
(
"replace",
{"force": "yes"},
definition,
(modified_def, ["test warning"]),
{
"changed": True,
"method": "replace",
"result": modified_def,
"warnings": ["test warning"],
},
),
(
"update",
{},
definition,
(definition, []),
definition,
{"changed": False, "method": "update", "result": definition},
),
(
"update",
{},
definition,
(modified_def, []),
modified_def,
{"changed": True, "method": "update", "result": modified_def},
),
(
"update",
{},
definition,
(modified_def, ["test warning"]),
{
"changed": True,
"method": "update",
"result": modified_def,
"warnings": ["test warning"],
},
),
(
"create",
{"label_selectors": ["app=foo"]},
{},
(definition, []),
definition,
{
"changed": False,
"msg": "resource 'kind=Pod,name=foo,namespace=foo' filtered by label_selectors.",
@@ -164,18 +116,18 @@ modified_def["metadata"]["labels"]["environment"] = "testing"
"create",
{"label_selectors": ["app=nginx"]},
{},
(definition, []),
definition,
{"changed": True, "method": "create", "result": definition},
),
],
)
def test_perform_action(action, params, existing, instance_warnings, expected):
def test_perform_action(action, params, existing, instance, expected):
svc = Mock()
svc.find_resource.return_value = Mock(
kind=definition["kind"], group_version=definition["apiVersion"]
)
svc.retrieve.return_value = ResourceInstance(None, existing) if existing else None
spec = {action + ".return_value": instance_warnings}
spec = {action + ".return_value": instance}
svc.configure_mock(**spec)
result = perform_action(svc, definition, params)

View File

@@ -1,11 +1,9 @@
from json import dumps
from unittest.mock import Mock
import pytest
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.service import (
K8sService,
diff_objects,
parse_quoted_string,
)
from kubernetes.dynamic.exceptions import NotFoundError
from kubernetes.dynamic.resource import Resource, ResourceInstance
@@ -59,22 +57,6 @@ def mock_pod_updated_resource_instance():
return ResourceInstance(None, pod_definition_updated)
@pytest.fixture(scope="module")
def mock_pod_response():
resp = Mock()
resp.data.decode.return_value = dumps(pod_definition)
resp.headers = {}
return resp
@pytest.fixture(scope="module")
def mock_pod_warnings_response():
resp = Mock()
resp.data.decode.return_value = dumps(pod_definition)
resp.headers = {"warning": '299 - "test warning 1", 299 - "test warning 2"'}
return resp
def test_diff_objects_no_diff():
match, diff = diff_objects(pod_definition, pod_definition)
@@ -177,33 +159,16 @@ def test_service_delete_existing_resource_check_mode(mock_pod_resource_instance)
client.delete.assert_not_called()
def test_service_create_resource(mock_pod_response, mock_pod_resource_instance):
spec = {"create.side_effect": [mock_pod_response]}
def test_service_create_resource(mock_pod_resource_instance):
spec = {"create.side_effect": [mock_pod_resource_instance]}
client = Mock(**spec)
module = Mock()
module.params = {}
module.check_mode = False
svc = K8sService(client, module)
result, warnings = svc.create(Mock(), pod_definition)
result = svc.create(Mock(), pod_definition)
assert result == mock_pod_resource_instance.to_dict()
assert not warnings
def test_service_create_resource_warnings(
mock_pod_warnings_response, mock_pod_resource_instance
):
spec = {"create.side_effect": [mock_pod_warnings_response]}
client = Mock(**spec)
module = Mock()
module.params = {}
module.check_mode = False
svc = K8sService(client, module)
result, warnings = svc.create(Mock(), pod_definition)
assert result == mock_pod_resource_instance.to_dict()
assert warnings[0] == "test warning 1"
assert warnings[1] == "test warning 2"
def test_service_create_resource_check_mode():
@@ -211,10 +176,9 @@ def test_service_create_resource_check_mode():
client.create.return_value = mock_pod_resource_instance
module = Mock(params={}, check_mode=True)
svc = K8sService(client, module)
result, warnings = svc.create(Mock(), pod_definition)
result = svc.create(Mock(), pod_definition)
assert result == pod_definition
assert not warnings
client.create.assert_not_called()
@@ -260,99 +224,40 @@ def test_create_project_request():
assert results["result"] == project_definition
def test_service_apply_existing_resource(mock_pod_response, mock_pod_resource_instance):
spec = {"apply.side_effect": [mock_pod_response]}
def test_service_apply_existing_resource(mock_pod_resource_instance):
spec = {"apply.side_effect": [mock_pod_resource_instance]}
client = Mock(**spec)
module = Mock()
module.params = {"apply": True}
module.check_mode = False
svc = K8sService(client, module)
result, warnings = svc.apply(
Mock(), pod_definition_updated, mock_pod_resource_instance
)
result = svc.apply(Mock(), pod_definition_updated, mock_pod_resource_instance)
assert result == mock_pod_resource_instance.to_dict()
assert not warnings
def test_service_apply_existing_resource_warnings(
mock_pod_warnings_response, mock_pod_resource_instance
):
spec = {"apply.side_effect": [mock_pod_warnings_response]}
client = Mock(**spec)
module = Mock()
module.params = {"apply": True}
module.check_mode = False
svc = K8sService(client, module)
result, warnings = svc.apply(
Mock(), pod_definition_updated, mock_pod_resource_instance
)
assert result == mock_pod_resource_instance.to_dict()
assert warnings[0] == "test warning 1"
assert warnings[1] == "test warning 2"
def test_service_replace_existing_resource(
mock_pod_response, mock_pod_resource_instance
):
spec = {"replace.side_effect": [mock_pod_response]}
def test_service_replace_existing_resource(mock_pod_resource_instance):
spec = {"replace.side_effect": [mock_pod_resource_instance]}
client = Mock(**spec)
module = Mock()
module.params = {}
module.check_mode = False
svc = K8sService(client, module)
result, warnings = svc.replace(Mock(), pod_definition, mock_pod_resource_instance)
result = svc.replace(Mock(), pod_definition, mock_pod_resource_instance)
assert result == mock_pod_resource_instance.to_dict()
assert not warnings
def test_service_replace_existing_resource_warnings(
mock_pod_warnings_response, mock_pod_resource_instance
):
spec = {"replace.side_effect": [mock_pod_warnings_response]}
def test_service_update_existing_resource(mock_pod_resource_instance):
spec = {"replace.side_effect": [mock_pod_resource_instance]}
client = Mock(**spec)
module = Mock()
module.params = {}
module.check_mode = False
svc = K8sService(client, module)
result, warnings = svc.replace(Mock(), pod_definition, mock_pod_resource_instance)
result = svc.replace(Mock(), pod_definition, mock_pod_resource_instance)
assert result == mock_pod_resource_instance.to_dict()
assert warnings[0] == "test warning 1"
assert warnings[1] == "test warning 2"
def test_service_update_existing_resource(
mock_pod_response, mock_pod_resource_instance
):
spec = {"replace.side_effect": [mock_pod_response]}
client = Mock(**spec)
module = Mock()
module.params = {}
module.check_mode = False
svc = K8sService(client, module)
result, warnings = svc.replace(Mock(), pod_definition, mock_pod_resource_instance)
assert result == mock_pod_resource_instance.to_dict()
assert not warnings
def test_service_update_existing_resource_warnings(
mock_pod_warnings_response, mock_pod_resource_instance
):
spec = {"replace.side_effect": [mock_pod_warnings_response]}
client = Mock(**spec)
module = Mock()
module.params = {}
module.check_mode = False
svc = K8sService(client, module)
result, warnings = svc.replace(Mock(), pod_definition, mock_pod_resource_instance)
assert result == mock_pod_resource_instance.to_dict()
assert warnings[0] == "test warning 1"
assert warnings[1] == "test warning 2"
def test_service_find(mock_pod_resource_instance):
@@ -383,24 +288,3 @@ def test_service_find_error():
assert isinstance(results, dict)
assert results["api_found"] is True
assert results["resources"] == []
@pytest.mark.parametrize(
"quoted_string,expected_val,expected_remainder",
[
(
'"Response is stale" Tue, 15 Nov 1994 12:45:26 GMT',
"Response is stale",
"Tue, 15 Nov 1994 12:45:26 GMT",
),
(
'"unknown field \\"spec.template.spec.disk\\""',
'unknown field "spec.template.spec.disk"',
"",
),
],
)
def test_parse_quoted_string(quoted_string, expected_val, expected_remainder):
val, remainder = parse_quoted_string(quoted_string)
assert val == expected_val
assert remainder == expected_remainder