mirror of
https://github.com/ansible-collections/kubernetes.core.git
synced 2026-05-12 20:42:08 +00:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b16bb15d34 | ||
|
|
588f60adc8 | ||
|
|
deac7719c2 | ||
|
|
cb4b792038 | ||
|
|
6215ac763b | ||
|
|
d5599f1964 | ||
|
|
90134ec3e0 | ||
|
|
dcbe52e722 | ||
|
|
1e711d4da8 | ||
|
|
4b2dc4f974 | ||
|
|
eb0aeeb318 | ||
|
|
f3d3696093 | ||
|
|
e3da2f28fd | ||
|
|
bb599542e8 | ||
|
|
6560fb1c53 | ||
|
|
20084d119e | ||
|
|
c47343d7b6 | ||
|
|
c213b51741 | ||
|
|
60b53b9dc9 | ||
|
|
d531368d64 | ||
|
|
c3bf5cc47f | ||
|
|
349534b85b | ||
|
|
92e3f98a20 | ||
|
|
d2dcb9e55f |
@@ -3,6 +3,7 @@ profile: production
|
|||||||
|
|
||||||
exclude_paths:
|
exclude_paths:
|
||||||
- .ansible/
|
- .ansible/
|
||||||
|
- .github/
|
||||||
- tests/integration
|
- tests/integration
|
||||||
- tests/unit
|
- tests/unit
|
||||||
- tests/sanity
|
- tests/sanity
|
||||||
@@ -3,3 +3,4 @@
|
|||||||
plugins/connection/kubectl.py no-changed-when
|
plugins/connection/kubectl.py no-changed-when
|
||||||
# false positive result
|
# false positive result
|
||||||
plugins/connection/kubectl.py var-naming[no-reserved]
|
plugins/connection/kubectl.py var-naming[no-reserved]
|
||||||
|
plugins/connection/kubectl.py jinja[invalid]
|
||||||
|
|||||||
17
.github/workflows/integration-tests.yaml
vendored
17
.github/workflows/integration-tests.yaml
vendored
@@ -26,6 +26,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: ${{ env.source_dir }}
|
path: ${{ env.source_dir }}
|
||||||
fetch-depth: "0"
|
fetch-depth: "0"
|
||||||
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
|
||||||
- name: list changes for pull request
|
- name: list changes for pull request
|
||||||
id: splitter
|
id: splitter
|
||||||
@@ -50,6 +51,7 @@ jobs:
|
|||||||
source: "./source"
|
source: "./source"
|
||||||
cloud_common: "./cloudcommon"
|
cloud_common: "./cloudcommon"
|
||||||
ansible_posix: "./ansible_posix"
|
ansible_posix: "./ansible_posix"
|
||||||
|
community_general: "./community_general"
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@@ -61,7 +63,7 @@ jobs:
|
|||||||
- true
|
- true
|
||||||
- false
|
- false
|
||||||
workflow-id: ${{ fromJson(needs.splitter.outputs.test_jobs) }}
|
workflow-id: ${{ fromJson(needs.splitter.outputs.test_jobs) }}
|
||||||
name: "integration-py${{ matrix.python-version }}-${{ matrix.ansible-version }}-${{ matrix.workflow-id }}"
|
name: "integration-py${{ matrix.python-version }}-${{ matrix.ansible-version }}-${{ matrix.workflow-id }}-enable_turbo=${{ matrix.enable-turbo-mode }}"
|
||||||
steps:
|
steps:
|
||||||
- name: Read target
|
- name: Read target
|
||||||
id: read-targets
|
id: read-targets
|
||||||
@@ -118,6 +120,13 @@ jobs:
|
|||||||
path: ${{ env.ansible_posix }}
|
path: ${{ env.ansible_posix }}
|
||||||
ref: main
|
ref: main
|
||||||
|
|
||||||
|
- name: checkout ansible-collections/community.general
|
||||||
|
uses: ansible-network/github_actions/.github/actions/checkout_dependency@main
|
||||||
|
with:
|
||||||
|
repository: ansible-collections/community.general
|
||||||
|
path: ${{ env.community_general }}
|
||||||
|
ref: main
|
||||||
|
|
||||||
- name: install cloud.common collection
|
- name: install cloud.common collection
|
||||||
uses: ansible-network/github_actions/.github/actions/build_install_collection@main
|
uses: ansible-network/github_actions/.github/actions/build_install_collection@main
|
||||||
with:
|
with:
|
||||||
@@ -130,6 +139,12 @@ jobs:
|
|||||||
install_python_dependencies: true
|
install_python_dependencies: true
|
||||||
source_path: ${{ env.ansible_posix }}
|
source_path: ${{ env.ansible_posix }}
|
||||||
|
|
||||||
|
- name: install community.general collection
|
||||||
|
uses: ansible-network/github_actions/.github/actions/build_install_collection@main
|
||||||
|
with:
|
||||||
|
install_python_dependencies: false
|
||||||
|
source_path: ${{ env.community_general }}
|
||||||
|
|
||||||
- name: create kubernetes cluster
|
- name: create kubernetes cluster
|
||||||
uses: helm/kind-action@v1.8.0
|
uses: helm/kind-action@v1.8.0
|
||||||
with:
|
with:
|
||||||
|
|||||||
4
.github/workflows/linters.yaml
vendored
4
.github/workflows/linters.yaml
vendored
@@ -20,4 +20,6 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: run-ansible-lint
|
- name: run-ansible-lint
|
||||||
uses: ansible/ansible-lint@v24.12.2
|
uses: ansible/ansible-lint@main
|
||||||
|
with:
|
||||||
|
gh_action_ref: "v25.5.0"
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -21,3 +21,6 @@ tests/integration/*-chart-*.tgz
|
|||||||
# ansible-test generated file
|
# ansible-test generated file
|
||||||
tests/integration/inventory
|
tests/integration/inventory
|
||||||
tests/integration/*-*.yml
|
tests/integration/*-*.yml
|
||||||
|
|
||||||
|
# VS Code settings
|
||||||
|
.vscode/
|
||||||
|
|||||||
@@ -26,3 +26,4 @@ ignore: |
|
|||||||
.tox
|
.tox
|
||||||
.ansible
|
.ansible
|
||||||
tests/output
|
tests/output
|
||||||
|
plugins/connection/kubectl.py
|
||||||
|
|||||||
@@ -4,6 +4,55 @@ Kubernetes Collection Release Notes
|
|||||||
|
|
||||||
.. contents:: Topics
|
.. 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
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This release updates the ``helm_registry_auth`` module to match the behavior of ``helm >= 3.18.0`` which reports a successful logout regardless of the current state (i.e., no idempotency).
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- Module ``helm_registry_auth`` does not support idempotency with ``helm >= 3.18.0`` (https://github.com/ansible-collections/kubernetes.core/pull/946)
|
||||||
|
|
||||||
|
v5.3.0
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This release includes minor changes, bug fixes and also bumps ``ansible-lint`` version to ``25.1.2``.
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- 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).
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
v5.2.0
|
v5.2.0
|
||||||
======
|
======
|
||||||
|
|
||||||
@@ -102,6 +151,14 @@ Bugfixes
|
|||||||
- helm - use ``reuse-values`` when running ``helm diff`` command (https://github.com/ansible-collections/kubernetes.core/issues/680).
|
- 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).
|
- 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.3.1
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This release fixes the CI issues with the ``linters`` workflow.
|
||||||
|
|
||||||
v3.3.0
|
v3.3.0
|
||||||
======
|
======
|
||||||
|
|
||||||
|
|||||||
2
Makefile
2
Makefile
@@ -1,5 +1,5 @@
|
|||||||
# Also needs to be updated in galaxy.yml
|
# Also needs to be updated in galaxy.yml
|
||||||
VERSION = 5.2.0
|
VERSION = 5.4.1
|
||||||
|
|
||||||
TEST_ARGS ?= ""
|
TEST_ARGS ?= ""
|
||||||
PYTHON_VERSION ?= `python -c 'import platform; print(".".join(platform.python_version_tuple()[0:2]))'`
|
PYTHON_VERSION ?= `python -c 'import platform; print(".".join(platform.python_version_tuple()[0:2]))'`
|
||||||
|
|||||||
22
README.md
22
README.md
@@ -21,7 +21,7 @@ For more information about communication, see the [Ansible communication guide](
|
|||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
<!--start requires_ansible-->
|
<!--start requires_ansible-->
|
||||||
## Ansible version compatibility
|
## Ansible Version Compatibility
|
||||||
|
|
||||||
This collection has been tested against following Ansible versions: **>=2.15.0**.
|
This collection has been tested against following Ansible versions: **>=2.15.0**.
|
||||||
|
|
||||||
@@ -42,27 +42,27 @@ Note: Python2 is deprecated from [1st January 2020](https://www.python.org/doc/s
|
|||||||
|
|
||||||
This collection supports Kubernetes versions >= 1.24.
|
This collection supports Kubernetes versions >= 1.24.
|
||||||
|
|
||||||
### Included content
|
### Included Content
|
||||||
|
|
||||||
Click on the name of a plugin or module to view that content's documentation:
|
Click on the name of a plugin or module to view that content's documentation:
|
||||||
|
|
||||||
<!--start collection content-->
|
<!--start collection content-->
|
||||||
### Connection plugins
|
### Connection Plugins
|
||||||
Name | Description
|
Name | Description
|
||||||
--- | ---
|
--- | ---
|
||||||
[kubernetes.core.kubectl](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.kubectl_connection.rst)|Execute tasks in pods running on Kubernetes.
|
[kubernetes.core.kubectl](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.kubectl_connection.rst)|Execute tasks in pods running on Kubernetes.
|
||||||
|
|
||||||
### K8s filter plugins
|
### K8s filter Plugins
|
||||||
Name | Description
|
Name | Description
|
||||||
--- | ---
|
--- | ---
|
||||||
kubernetes.core.k8s_config_resource_name|Generate resource name for the given resource of type ConfigMap, Secret
|
kubernetes.core.k8s_config_resource_name|Generate resource name for the given resource of type ConfigMap, Secret
|
||||||
|
|
||||||
### Inventory plugins
|
### Inventory Plugins
|
||||||
Name | Description
|
Name | Description
|
||||||
--- | ---
|
--- | ---
|
||||||
[kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_inventory.rst)|Kubernetes (K8s) inventory source
|
[kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_inventory.rst)|Kubernetes (K8s) inventory source
|
||||||
|
|
||||||
### Lookup plugins
|
### Lookup Plugins
|
||||||
Name | Description
|
Name | Description
|
||||||
--- | ---
|
--- | ---
|
||||||
[kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_lookup.rst)|Query the K8s API
|
[kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_lookup.rst)|Query the K8s API
|
||||||
@@ -106,7 +106,7 @@ You can also include it in a `requirements.yml` file and install it via `ansible
|
|||||||
---
|
---
|
||||||
collections:
|
collections:
|
||||||
- name: kubernetes.core
|
- name: kubernetes.core
|
||||||
version: 5.2.0
|
version: 5.4.1
|
||||||
```
|
```
|
||||||
|
|
||||||
### Installing the Kubernetes Python Library
|
### Installing the Kubernetes Python Library
|
||||||
@@ -183,7 +183,7 @@ If upgrading older playbooks which were built prior to Ansible 2.10 and this col
|
|||||||
|
|
||||||
For documentation on how to use individual modules and other content included in this collection, please see the links in the 'Included content' section earlier in this README.
|
For documentation on how to use individual modules and other content included in this collection, please see the links in the 'Included content' section earlier in this README.
|
||||||
|
|
||||||
## Ansible Turbo mode Tech Preview
|
## Ansible Turbo Mode Tech Preview
|
||||||
|
|
||||||
|
|
||||||
The ``kubernetes.core`` collection supports Ansible Turbo mode as a tech preview via the ``cloud.common`` collection. By default, this feature is disabled. To enable Turbo mode for modules, set the environment variable `ENABLE_TURBO_MODE=1` on the managed node. For example:
|
The ``kubernetes.core`` collection supports Ansible Turbo mode as a tech preview via the ``cloud.common`` collection. By default, this feature is disabled. To enable Turbo mode for modules, set the environment variable `ENABLE_TURBO_MODE=1` on the managed node. For example:
|
||||||
@@ -202,7 +202,7 @@ defined in the playbook using `environment` keyword as above, you must set it us
|
|||||||
|
|
||||||
Please read more about Ansible Turbo mode - [here](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/ansible_turbo_mode.rst).
|
Please read more about Ansible Turbo mode - [here](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/ansible_turbo_mode.rst).
|
||||||
|
|
||||||
## Contributing to this collection
|
## Contributing to this Collection
|
||||||
|
|
||||||
If you want to develop new content for this collection or improve what's already here, the easiest way to work on the collection is to clone it into one of the configured [`COLLECTIONS_PATHS`](https://docs.ansible.com/ansible/latest/reference_appendices/config.html#collections-paths), and work on it there.
|
If you want to develop new content for this collection or improve what's already here, the easiest way to work on the collection is to clone it into one of the configured [`COLLECTIONS_PATHS`](https://docs.ansible.com/ansible/latest/reference_appendices/config.html#collections-paths), and work on it there.
|
||||||
|
|
||||||
@@ -252,6 +252,8 @@ The process for uploading a supported release to Automation Hub is documented se
|
|||||||
|
|
||||||
<!--List available communication channels. In addition to channels specific to your collection, we also recommend to use the following ones.-->
|
<!--List available communication channels. In addition to channels specific to your collection, we also recommend to use the following ones.-->
|
||||||
|
|
||||||
|
> **Note:** The `stable-4` branch, which handles all `4.x.y` releases of this collection, is no longer supported. This means that no backports nor releases will be performed on the `stable-4` branch.
|
||||||
|
|
||||||
We announce releases and important changes through Ansible's [The Bullhorn newsletter](https://github.com/ansible/community/wiki/News#the-bullhorn). Be sure you are [subscribed](https://eepurl.com/gZmiEP).
|
We announce releases and important changes through Ansible's [The Bullhorn newsletter](https://github.com/ansible/community/wiki/News#the-bullhorn). Be sure you are [subscribed](https://eepurl.com/gZmiEP).
|
||||||
|
|
||||||
We take part in the global quarterly [Ansible Contributor Summit](https://github.com/ansible/community/wiki/Contributor-Summit) virtually or in-person. Track [The Bullhorn newsletter](https://eepurl.com/gZmiEP) and join us.
|
We take part in the global quarterly [Ansible Contributor Summit](https://github.com/ansible/community/wiki/Contributor-Summit) virtually or in-person. Track [The Bullhorn newsletter](https://eepurl.com/gZmiEP) and join us.
|
||||||
@@ -263,7 +265,7 @@ For the latest supported versions, refer to the release notes below.
|
|||||||
If you encounter issues or have questions, you can submit a support request through the following channels:
|
If you encounter issues or have questions, you can submit a support request through the following channels:
|
||||||
- GitHub Issues: Report bugs, request features, or ask questions by opening an issue in the [GitHub repository]((https://github.com/ansible-collections/kubernetes.core/).
|
- GitHub Issues: Report bugs, request features, or ask questions by opening an issue in the [GitHub repository]((https://github.com/ansible-collections/kubernetes.core/).
|
||||||
|
|
||||||
## Release notes
|
## Release Notes
|
||||||
|
|
||||||
See the [raw generated changelog](https://github.com/ansible-collections/kubernetes.core/blob/main/CHANGELOG.rst).
|
See the [raw generated changelog](https://github.com/ansible-collections/kubernetes.core/blob/main/CHANGELOG.rst).
|
||||||
|
|
||||||
|
|||||||
@@ -900,6 +900,12 @@ releases:
|
|||||||
- 798-drain-pdb-error-message.yaml
|
- 798-drain-pdb-error-message.yaml
|
||||||
- readme_template_update.yml
|
- readme_template_update.yml
|
||||||
release_date: '2025-01-20'
|
release_date: '2025-01-20'
|
||||||
|
3.3.1:
|
||||||
|
changes:
|
||||||
|
release_summary: This release fixes the CI issues with the ``linters`` workflow.
|
||||||
|
fragments:
|
||||||
|
- release_summary.yml
|
||||||
|
release_date: '2025-03-26'
|
||||||
4.0.0:
|
4.0.0:
|
||||||
changes:
|
changes:
|
||||||
bugfixes:
|
bugfixes:
|
||||||
@@ -971,7 +977,7 @@ releases:
|
|||||||
- kustomize - kustomize plugin fails with deprecation warnings (https://github.com/ansible-collections/kubernetes.core/issues/639).
|
- 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).
|
- waiter - Fix waiting for daemonset when desired number of pods is 0. (https://github.com/ansible-collections/kubernetes.core/pull/756).
|
||||||
minor_changes:
|
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
|
- Parameter insecure_registry added to helm_template as equivalent of insecure-skip-tls-verify
|
||||||
(https://github.com/ansible-collections/kubernetes.core/pull/805).
|
(https://github.com/ansible-collections/kubernetes.core/pull/805).
|
||||||
- k8s_drain - Improve error message for pod disruption budget when draining
|
- k8s_drain - Improve error message for pod disruption budget when draining
|
||||||
@@ -1017,3 +1023,51 @@ releases:
|
|||||||
- 643-extend-hidden-fields.yaml
|
- 643-extend-hidden-fields.yaml
|
||||||
- 879-clusteroperator-waiter.py.yaml
|
- 879-clusteroperator-waiter.py.yaml
|
||||||
release_date: '2025-03-27'
|
release_date: '2025-03-27'
|
||||||
|
5.3.0:
|
||||||
|
changes:
|
||||||
|
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).
|
||||||
|
minor_changes:
|
||||||
|
- kubernetes.core - 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).
|
||||||
|
release_summary: This release includes minor changes, bug fixes and also bumps
|
||||||
|
``ansible-lint`` version to ``25.1.2``.
|
||||||
|
fragments:
|
||||||
|
- 20250324-k8s_info-templating.yaml
|
||||||
|
- 5.3.0.yml
|
||||||
|
- 694-add-insecure-skip-tls-verify.yml
|
||||||
|
- 800-helm-add-reset_then_reuse_values-support.yml
|
||||||
|
- 898-k8s-dont-delete-in-check-mode.yaml
|
||||||
|
- 919-update-ansible-lint-version.yaml
|
||||||
|
release_date: '2025-05-16'
|
||||||
|
5.4.0:
|
||||||
|
changes:
|
||||||
|
minor_changes:
|
||||||
|
- Module ``helm_registry_auth`` does not support idempotency with ``helm >= 3.18.0``
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/pull/946).
|
||||||
|
release_summary: This release updates the ``helm_registry_auth`` module to match the behavior of ``helm >= 3.18.0`` which reports a successful logout regardless of the current state (i.e., no idempotency).
|
||||||
|
fragments:
|
||||||
|
- 20250411-kubeconfig-no_log-revert.yaml
|
||||||
|
- 20250503-fix-unit-tests.yml
|
||||||
|
- 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'
|
||||||
|
|||||||
@@ -289,6 +289,29 @@ Parameters
|
|||||||
<div>Provide a URL for accessing the API. Can also be specified via <code>K8S_AUTH_HOST</code> environment variable.</div>
|
<div>Provide a URL for accessing the API. Can also be specified via <code>K8S_AUTH_HOST</code> environment variable.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>insecure_skip_tls_verify</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 5.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Skip tls certificate checks for the chart download.</div>
|
||||||
|
<div>Do not confuse with the <code>validate_certs</code> option.</div>
|
||||||
|
<div>This option is only available for helm >= 3.16.0.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: skip_tls_certs_check</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -435,6 +458,28 @@ Parameters
|
|||||||
<div>mutually exclusive with with <code>history_max</code>.</div>
|
<div>mutually exclusive with with <code>history_max</code>.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>reset_then_reuse_values</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.0.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>When upgrading package, reset the values to the ones built into the chart, apply the last release's values and merge in any overrides from parameters O(release_values), O(values_files) or O(set_values).</div>
|
||||||
|
<div>If O(reset_values) or O(reuse_values) is set to V(True), this is ignored.</div>
|
||||||
|
<div>This feature requires helm diff >= 3.9.12.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
|||||||
@@ -279,7 +279,8 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Whether or not to check tls certificate for the chart download.</div>
|
<div>Whether or not to check tls certificate for the chart download.</div>
|
||||||
<div>Requires helm >= 3.3.0.</div>
|
<div>Requires helm >= 3.3.0. Alias <code>insecure_skip_tls_verify</code> added in 5.3.0.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: insecure_skip_tls_verify</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -170,6 +170,7 @@ Parameters
|
|||||||
<div>Desired state of the registry.</div>
|
<div>Desired state of the registry.</div>
|
||||||
<div>If set to V(present) attempt to log in to the remote registry server using the URL specified in O(host).</div>
|
<div>If set to V(present) attempt to log in to the remote registry server using the URL specified in O(host).</div>
|
||||||
<div>If set to V(absent) attempt to log out from the remote registry server using the URL specified in O(host).</div>
|
<div>If set to V(absent) attempt to log out from the remote registry server using the URL specified in O(host).</div>
|
||||||
|
<div>As helm >= 3.18.0 reports successful logout even if the user is not logged in, this module will report a change regardless of the current state.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -143,6 +143,27 @@ Parameters
|
|||||||
<div>Provide a URL for accessing the API. Can also be specified via <code>K8S_AUTH_HOST</code> environment variable.</div>
|
<div>Provide a URL for accessing the API. Can also be specified via <code>K8S_AUTH_HOST</code> environment variable.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>insecure_skip_tls_verify</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 5.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Skip tls certificate checks for the repository url.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: skip_tls_certs_check</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="1">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
|||||||
@@ -512,6 +512,7 @@ Notes
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
- the tar binary is required on the container when copying from local filesystem to pod.
|
- 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.
|
- 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.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -595,6 +595,7 @@ Examples
|
|||||||
kubernetes.core.k8s_drain:
|
kubernetes.core.k8s_drain:
|
||||||
state: drain
|
state: drain
|
||||||
name: foo
|
name: foo
|
||||||
|
delete_options:
|
||||||
force: yes
|
force: yes
|
||||||
|
|
||||||
- name: Drain node "foo", but abort if there are pods not managed by a ReplicationController, Job, or DaemonSet, and use a grace period of 15 minutes.
|
- name: Drain node "foo", but abort if there are pods not managed by a ReplicationController, Job, or DaemonSet, and use a grace period of 15 minutes.
|
||||||
|
|||||||
@@ -174,8 +174,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Hide fields matching any of the field definitions in the result</div>
|
<div>Hide fields matching any of the field definitions in the result</div>
|
||||||
<div>An example might be <code>hidden_fields=[metadata.managedFields]</code></div>
|
<div>An example might be <code>hidden_fields=[metadata.managedFields]</code> or V(hidden_fields=[spec.containers[0].env[3].value]) or V(hidden_fields=[metadata.annotations[kubectl.kubernetes.io/last-applied-configuration]])</div>
|
||||||
<div>Only field definitions that don't reference list items are supported (so V(spec.containers[0]) would not work)</div>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -395,8 +395,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Hide fields matching this option in the result</div>
|
<div>Hide fields matching this option in the result</div>
|
||||||
<div>An example might be <code>hidden_fields=[metadata.managedFields]</code></div>
|
<div>An example might be <code>hidden_fields=[metadata.managedFields]</code> or V(hidden_fields=[spec.containers[0].env[3].value]) or V(hidden_fields=[metadata.annotations[kubectl.kubernetes.io/last-applied-configuration]])</div>
|
||||||
<div>Only field definitions that don't reference list items are supported (so V(spec.containers[0]) would not work)</div>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ tags:
|
|||||||
- openshift
|
- openshift
|
||||||
- okd
|
- okd
|
||||||
- cluster
|
- cluster
|
||||||
version: 5.2.0
|
version: 5.4.1
|
||||||
build_ignore:
|
build_ignore:
|
||||||
- .DS_Store
|
- .DS_Store
|
||||||
- "*.tar.gz"
|
- "*.tar.gz"
|
||||||
|
|||||||
@@ -22,33 +22,20 @@ from ansible.errors import (
|
|||||||
)
|
)
|
||||||
from ansible.module_utils._text import to_bytes, to_native, to_text
|
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.parsing.convert_bool import boolean
|
||||||
from ansible.module_utils.six import iteritems, string_types
|
|
||||||
from ansible.plugins.action import ActionBase
|
from ansible.plugins.action import ActionBase
|
||||||
|
|
||||||
|
try:
|
||||||
|
from ansible.template import trust_as_template
|
||||||
|
except ImportError:
|
||||||
|
trust_as_template = None
|
||||||
|
|
||||||
class RemoveOmit(object):
|
|
||||||
def __init__(self, buffer, omit_value):
|
def _from_yaml_to_definition(buffer):
|
||||||
try:
|
try:
|
||||||
import yaml
|
import yaml
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise AnsibleError("Failed to import the required Python library (PyYAML).")
|
raise AnsibleError("Failed to import the required Python library (PyYAML).")
|
||||||
self.data = yaml.safe_load_all(buffer)
|
return list(yaml.safe_load_all(buffer))
|
||||||
self.omit = omit_value
|
|
||||||
|
|
||||||
def remove_omit(self, data):
|
|
||||||
if isinstance(data, dict):
|
|
||||||
result = dict()
|
|
||||||
for key, value in iteritems(data):
|
|
||||||
if value == self.omit:
|
|
||||||
continue
|
|
||||||
result[key] = self.remove_omit(value)
|
|
||||||
return result
|
|
||||||
if isinstance(data, list):
|
|
||||||
return [self.remove_omit(v) for v in data if v != self.omit]
|
|
||||||
return data
|
|
||||||
|
|
||||||
def output(self):
|
|
||||||
return [self.remove_omit(d) for d in self.data]
|
|
||||||
|
|
||||||
|
|
||||||
ENV_KUBECONFIG_PATH_SEPARATOR = ";" if platform.system() == "Windows" else ":"
|
ENV_KUBECONFIG_PATH_SEPARATOR = ";" if platform.system() == "Windows" else ":"
|
||||||
@@ -112,7 +99,7 @@ class ActionModule(ActionBase):
|
|||||||
"trim_blocks": True,
|
"trim_blocks": True,
|
||||||
"lstrip_blocks": False,
|
"lstrip_blocks": False,
|
||||||
}
|
}
|
||||||
if isinstance(template, string_types):
|
if isinstance(template, str):
|
||||||
# treat this as raw_params
|
# treat this as raw_params
|
||||||
template_param["path"] = template
|
template_param["path"] = template
|
||||||
elif isinstance(template, dict):
|
elif isinstance(template, dict):
|
||||||
@@ -132,7 +119,7 @@ class ActionModule(ActionBase):
|
|||||||
):
|
):
|
||||||
if s_type in template_args:
|
if s_type in template_args:
|
||||||
value = ensure_type(template_args[s_type], "string")
|
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(
|
raise AnsibleActionFail(
|
||||||
"%s is expected to be a string, but got %s instead"
|
"%s is expected to be a string, but got %s instead"
|
||||||
% (s_type, type(value))
|
% (s_type, type(value))
|
||||||
@@ -207,9 +194,8 @@ class ActionModule(ActionBase):
|
|||||||
"'template' is only a supported parameter for the 'k8s' module."
|
"'template' is only a supported parameter for the 'k8s' module."
|
||||||
)
|
)
|
||||||
|
|
||||||
omit_value = task_vars.get("omit")
|
|
||||||
template_params = []
|
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))
|
template_params.append(self.get_template_args(template))
|
||||||
elif isinstance(template, list):
|
elif isinstance(template, list):
|
||||||
for element in template:
|
for element in template:
|
||||||
@@ -230,6 +216,7 @@ class ActionModule(ActionBase):
|
|||||||
old_vars = self._templar.available_variables
|
old_vars = self._templar.available_variables
|
||||||
|
|
||||||
default_environment = {}
|
default_environment = {}
|
||||||
|
if trust_as_template is None:
|
||||||
for key in (
|
for key in (
|
||||||
"newline_sequence",
|
"newline_sequence",
|
||||||
"variable_start_string",
|
"variable_start_string",
|
||||||
@@ -257,26 +244,35 @@ class ActionModule(ActionBase):
|
|||||||
with self.get_template_data(template_item["path"]) as template_data:
|
with self.get_template_data(template_item["path"]) as template_data:
|
||||||
# add ansible 'template' vars
|
# add ansible 'template' vars
|
||||||
temp_vars = copy.deepcopy(task_vars)
|
temp_vars = copy.deepcopy(task_vars)
|
||||||
for key, value in iteritems(template_item):
|
overrides = {}
|
||||||
|
for key, value in template_item.items():
|
||||||
if hasattr(self._templar.environment, key):
|
if hasattr(self._templar.environment, key):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
|
overrides[key] = value
|
||||||
|
if trust_as_template is None:
|
||||||
setattr(self._templar.environment, key, value)
|
setattr(self._templar.environment, key, value)
|
||||||
else:
|
elif trust_as_template is None:
|
||||||
setattr(
|
setattr(
|
||||||
self._templar.environment,
|
self._templar.environment,
|
||||||
key,
|
key,
|
||||||
default_environment.get(key),
|
default_environment.get(key),
|
||||||
)
|
)
|
||||||
self._templar.available_variables = temp_vars
|
self._templar.available_variables = temp_vars
|
||||||
|
if trust_as_template:
|
||||||
|
template_data = trust_as_template(template_data)
|
||||||
|
result = self._templar.template(
|
||||||
|
template_data,
|
||||||
|
preserve_trailing_newlines=True,
|
||||||
|
escape_backslashes=False,
|
||||||
|
overrides=overrides,
|
||||||
|
)
|
||||||
|
else:
|
||||||
result = self._templar.do_template(
|
result = self._templar.do_template(
|
||||||
template_data,
|
template_data,
|
||||||
preserve_trailing_newlines=True,
|
preserve_trailing_newlines=True,
|
||||||
escape_backslashes=False,
|
escape_backslashes=False,
|
||||||
)
|
)
|
||||||
if omit_value is not None:
|
result_template.extend(_from_yaml_to_definition(result))
|
||||||
result_template.extend(RemoveOmit(result, omit_value).output())
|
|
||||||
else:
|
|
||||||
result_template.append(result)
|
|
||||||
self._templar.available_variables = old_vars
|
self._templar.available_variables = old_vars
|
||||||
resource_definition = self._task.args.get("definition", None)
|
resource_definition = self._task.args.get("definition", None)
|
||||||
if not resource_definition:
|
if not resource_definition:
|
||||||
@@ -306,7 +302,7 @@ class ActionModule(ActionBase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def get_kubeconfig(self, kubeconfig, remote_transport, new_module_args):
|
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
|
# find the kubeconfig in the expected search path
|
||||||
if not remote_transport:
|
if not remote_transport:
|
||||||
# kubeconfig is local
|
# kubeconfig is local
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
from ansible.module_utils.six import string_types
|
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
def list_dict_str(value):
|
def list_dict_str(value):
|
||||||
if isinstance(value, (list, dict, string_types)):
|
if isinstance(value, (list, dict, str)):
|
||||||
return value
|
return value
|
||||||
raise TypeError
|
raise TypeError
|
||||||
|
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ class K8SCopy(metaclass=ABCMeta):
|
|||||||
return error, stdout, stderr
|
return error, stdout, stderr
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.module.fail_json(
|
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)
|
self.namespace, self.name, cmd, to_native(e)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -435,11 +435,21 @@ def check_pod(svc):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
result = svc.client.get(resource, name=name, namespace=namespace)
|
result = svc.client.get(resource, name=name, namespace=namespace)
|
||||||
containers = [
|
containers = dict(
|
||||||
c["name"] for c in result.to_dict()["status"]["containerStatuses"]
|
{
|
||||||
]
|
c["name"]: c
|
||||||
if container and container not in containers:
|
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))
|
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:
|
except Exception as exc:
|
||||||
_fail(exc)
|
_fail(exc)
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import tempfile
|
|||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
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 (
|
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
|
||||||
LooseVersion,
|
LooseVersion,
|
||||||
)
|
)
|
||||||
@@ -113,7 +112,7 @@ class AnsibleHelmModule(object):
|
|||||||
kubeconfig_content = None
|
kubeconfig_content = None
|
||||||
kubeconfig = self.params.get("kubeconfig")
|
kubeconfig = self.params.get("kubeconfig")
|
||||||
if kubeconfig:
|
if kubeconfig:
|
||||||
if isinstance(kubeconfig, string_types):
|
if isinstance(kubeconfig, str):
|
||||||
with open(os.path.expanduser(kubeconfig)) as fd:
|
with open(os.path.expanduser(kubeconfig)) as fd:
|
||||||
kubeconfig_content = yaml.safe_load(fd)
|
kubeconfig_content = yaml.safe_load(fd)
|
||||||
elif isinstance(kubeconfig, dict):
|
elif isinstance(kubeconfig, dict):
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import hashlib
|
|||||||
import os
|
import os
|
||||||
from typing import Any, Dict, List, Optional
|
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 (
|
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
|
||||||
AUTH_ARG_MAP,
|
AUTH_ARG_MAP,
|
||||||
AUTH_ARG_SPEC,
|
AUTH_ARG_SPEC,
|
||||||
@@ -115,7 +114,7 @@ def _load_config(auth: Dict) -> None:
|
|||||||
"persist_config": auth.get("persist_config"),
|
"persist_config": auth.get("persist_config"),
|
||||||
}
|
}
|
||||||
if kubeconfig:
|
if kubeconfig:
|
||||||
if isinstance(kubeconfig, string_types):
|
if isinstance(kubeconfig, str):
|
||||||
kubernetes.config.load_kube_config(config_file=kubeconfig, **optional_arg)
|
kubernetes.config.load_kube_config(config_file=kubeconfig, **optional_arg)
|
||||||
elif isinstance(kubeconfig, dict):
|
elif isinstance(kubeconfig, dict):
|
||||||
kubernetes.config.load_kube_config_from_dict(
|
kubernetes.config.load_kube_config_from_dict(
|
||||||
@@ -163,7 +162,7 @@ def _create_configuration(auth: Dict):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
configuration = kubernetes.client.Configuration()
|
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 in AUTH_ARG_MAP.keys() and value is not None:
|
||||||
if key == "api_key":
|
if key == "api_key":
|
||||||
setattr(
|
setattr(
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
import os
|
import os
|
||||||
from typing import Dict, Iterable, List, Optional, Union, cast
|
from typing import Dict, Iterable, List, Optional, Union, cast
|
||||||
|
|
||||||
from ansible.module_utils.six import string_types
|
|
||||||
from ansible.module_utils.urls import Request
|
from ansible.module_utils.urls import Request
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -78,11 +77,11 @@ def create_definitions(params: Dict) -> List[ResourceDefinition]:
|
|||||||
def from_yaml(definition: Union[str, List, Dict]) -> Iterable[Dict]:
|
def from_yaml(definition: Union[str, List, Dict]) -> Iterable[Dict]:
|
||||||
"""Load resource definitions from a yaml definition."""
|
"""Load resource definitions from a yaml definition."""
|
||||||
definitions: List[Dict] = []
|
definitions: List[Dict] = []
|
||||||
if isinstance(definition, string_types):
|
if isinstance(definition, str):
|
||||||
definitions += yaml.safe_load_all(definition)
|
definitions += yaml.safe_load_all(definition)
|
||||||
elif isinstance(definition, list):
|
elif isinstance(definition, list):
|
||||||
for item in definition:
|
for item in definition:
|
||||||
if isinstance(item, string_types):
|
if isinstance(item, str):
|
||||||
definitions += yaml.safe_load_all(item)
|
definitions += yaml.safe_load_all(item)
|
||||||
else:
|
else:
|
||||||
definitions.append(item)
|
definitions.append(item)
|
||||||
|
|||||||
@@ -473,7 +473,7 @@ class K8sService:
|
|||||||
if label_selectors:
|
if label_selectors:
|
||||||
params["label_selector"] = ",".join(label_selectors)
|
params["label_selector"] = ",".join(label_selectors)
|
||||||
|
|
||||||
if delete_options:
|
if delete_options and not self.module.check_mode:
|
||||||
body = {
|
body = {
|
||||||
"apiVersion": "v1",
|
"apiVersion": "v1",
|
||||||
"kind": "DeleteOptions",
|
"kind": "DeleteOptions",
|
||||||
@@ -498,8 +498,8 @@ def diff_objects(
|
|||||||
if not diff:
|
if not diff:
|
||||||
return True, result
|
return True, result
|
||||||
|
|
||||||
result["before"] = diff[0]
|
result["before"] = hide_fields(diff[0], hidden_fields)
|
||||||
result["after"] = diff[1]
|
result["after"] = hide_fields(diff[1], hidden_fields)
|
||||||
|
|
||||||
if list(result["after"].keys()) == ["metadata"] and list(
|
if list(result["after"].keys()) == ["metadata"] and list(
|
||||||
result["before"].keys()
|
result["before"].keys()
|
||||||
@@ -512,9 +512,6 @@ def diff_objects(
|
|||||||
).issubset(ignored_keys):
|
).issubset(ignored_keys):
|
||||||
return True, result
|
return True, result
|
||||||
|
|
||||||
result["before"] = hide_fields(result["before"], hidden_fields)
|
|
||||||
result["after"] = hide_fields(result["after"], hidden_fields)
|
|
||||||
|
|
||||||
return False, result
|
return False, result
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -145,6 +145,16 @@ options:
|
|||||||
required: false
|
required: false
|
||||||
default: True
|
default: True
|
||||||
version_added: 3.0.0
|
version_added: 3.0.0
|
||||||
|
reset_then_reuse_values:
|
||||||
|
description:
|
||||||
|
- When upgrading package, reset the values to the ones built into the chart, apply the last release's values and merge in any overrides from
|
||||||
|
parameters O(release_values), O(values_files) or O(set_values).
|
||||||
|
- If O(reset_values) or O(reuse_values) is set to V(True), this is ignored.
|
||||||
|
- This feature requires helm diff >= 3.9.12.
|
||||||
|
type: bool
|
||||||
|
required: false
|
||||||
|
default: False
|
||||||
|
version_added: 6.0.0
|
||||||
|
|
||||||
#Helm options
|
#Helm options
|
||||||
disable_hook:
|
disable_hook:
|
||||||
@@ -218,6 +228,15 @@ options:
|
|||||||
- mutually exclusive with with C(replace).
|
- mutually exclusive with with C(replace).
|
||||||
type: int
|
type: int
|
||||||
version_added: 2.2.0
|
version_added: 2.2.0
|
||||||
|
insecure_skip_tls_verify:
|
||||||
|
description:
|
||||||
|
- Skip tls certificate checks for the chart download.
|
||||||
|
- Do not confuse with the C(validate_certs) option.
|
||||||
|
- This option is only available for helm >= 3.16.0.
|
||||||
|
type: bool
|
||||||
|
default: False
|
||||||
|
aliases: [ skip_tls_certs_check ]
|
||||||
|
version_added: 5.3.0
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- kubernetes.core.helm_common_options
|
- kubernetes.core.helm_common_options
|
||||||
"""
|
"""
|
||||||
@@ -476,12 +495,15 @@ def run_dep_update(module, chart_ref):
|
|||||||
rc, out, err = module.run_helm_command(dep_update)
|
rc, out, err = module.run_helm_command(dep_update)
|
||||||
|
|
||||||
|
|
||||||
def fetch_chart_info(module, command, chart_ref):
|
def fetch_chart_info(module, command, chart_ref, insecure_skip_tls_verify=False):
|
||||||
"""
|
"""
|
||||||
Get chart info
|
Get chart info
|
||||||
"""
|
"""
|
||||||
inspect_command = command + f" show chart '{chart_ref}'"
|
inspect_command = command + f" show chart '{chart_ref}'"
|
||||||
|
|
||||||
|
if insecure_skip_tls_verify:
|
||||||
|
inspect_command += " --insecure-skip-tls-verify"
|
||||||
|
|
||||||
rc, out, err = module.run_helm_command(inspect_command)
|
rc, out, err = module.run_helm_command(inspect_command)
|
||||||
|
|
||||||
return yaml.safe_load(out)
|
return yaml.safe_load(out)
|
||||||
@@ -509,6 +531,8 @@ def deploy(
|
|||||||
set_value_args=None,
|
set_value_args=None,
|
||||||
reuse_values=None,
|
reuse_values=None,
|
||||||
reset_values=True,
|
reset_values=True,
|
||||||
|
reset_then_reuse_values=False,
|
||||||
|
insecure_skip_tls_verify=False,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Install/upgrade/rollback release chart
|
Install/upgrade/rollback release chart
|
||||||
@@ -526,6 +550,17 @@ def deploy(
|
|||||||
if reuse_values is not None:
|
if reuse_values is not None:
|
||||||
deploy_command += " --reuse-values=" + str(reuse_values)
|
deploy_command += " --reuse-values=" + str(reuse_values)
|
||||||
|
|
||||||
|
if reset_then_reuse_values:
|
||||||
|
helm_version = module.get_helm_version()
|
||||||
|
if LooseVersion(helm_version) < LooseVersion("3.14.0"):
|
||||||
|
module.fail_json(
|
||||||
|
msg="reset_then_reuse_values requires helm >= 3.14.0, current version is {0}".format(
|
||||||
|
helm_version
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
deploy_command += " --reset-then-reuse-values"
|
||||||
|
|
||||||
if wait:
|
if wait:
|
||||||
deploy_command += " --wait"
|
deploy_command += " --wait"
|
||||||
if wait_timeout is not None:
|
if wait_timeout is not None:
|
||||||
@@ -549,6 +584,17 @@ def deploy(
|
|||||||
if create_namespace:
|
if create_namespace:
|
||||||
deploy_command += " --create-namespace"
|
deploy_command += " --create-namespace"
|
||||||
|
|
||||||
|
if insecure_skip_tls_verify:
|
||||||
|
helm_version = module.get_helm_version()
|
||||||
|
if LooseVersion(helm_version) < LooseVersion("3.16.0"):
|
||||||
|
module.fail_json(
|
||||||
|
msg="insecure_skip_tls_verify requires helm >= 3.16.0, current version is {0}".format(
|
||||||
|
helm_version
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
deploy_command += " --insecure-skip-tls-verify"
|
||||||
|
|
||||||
if values_files:
|
if values_files:
|
||||||
for value_file in values_files:
|
for value_file in values_files:
|
||||||
deploy_command += " --values=" + value_file
|
deploy_command += " --values=" + value_file
|
||||||
@@ -642,6 +688,8 @@ def helmdiff_check(
|
|||||||
set_value_args=None,
|
set_value_args=None,
|
||||||
reuse_values=None,
|
reuse_values=None,
|
||||||
reset_values=True,
|
reset_values=True,
|
||||||
|
reset_then_reuse_values=False,
|
||||||
|
insecure_skip_tls_verify=False,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Use helm diff to determine if a release would change by upgrading a chart.
|
Use helm diff to determine if a release would change by upgrading a chart.
|
||||||
@@ -676,6 +724,27 @@ def helmdiff_check(
|
|||||||
if reuse_values:
|
if reuse_values:
|
||||||
cmd += " --reuse-values"
|
cmd += " --reuse-values"
|
||||||
|
|
||||||
|
if reset_then_reuse_values:
|
||||||
|
helm_diff_version = get_plugin_version("diff")
|
||||||
|
helm_version = module.get_helm_version()
|
||||||
|
fail_msg = ""
|
||||||
|
if LooseVersion(helm_diff_version) < LooseVersion("3.9.12"):
|
||||||
|
fail_msg = "reset_then_reuse_values requires helm diff >= 3.9.12, current version is {0}\n".format(
|
||||||
|
helm_diff_version
|
||||||
|
)
|
||||||
|
if LooseVersion(helm_version) < LooseVersion("3.14.0"):
|
||||||
|
fail_msg += "reset_then_reuse_values requires helm >= 3.14.0, current version is {0}\n".format(
|
||||||
|
helm_version
|
||||||
|
)
|
||||||
|
|
||||||
|
if fail_msg:
|
||||||
|
module.fail_json(msg=fail_msg)
|
||||||
|
else:
|
||||||
|
cmd += " --reset-then-reuse-values"
|
||||||
|
|
||||||
|
if insecure_skip_tls_verify:
|
||||||
|
cmd += " --insecure-skip-tls-verify"
|
||||||
|
|
||||||
rc, out, err = module.run_helm_command(cmd)
|
rc, out, err = module.run_helm_command(cmd)
|
||||||
return (len(out.strip()) > 0, out.strip())
|
return (len(out.strip()) > 0, out.strip())
|
||||||
|
|
||||||
@@ -735,6 +804,10 @@ def argument_spec():
|
|||||||
set_values=dict(type="list", elements="dict"),
|
set_values=dict(type="list", elements="dict"),
|
||||||
reuse_values=dict(type="bool"),
|
reuse_values=dict(type="bool"),
|
||||||
reset_values=dict(type="bool", default=True),
|
reset_values=dict(type="bool", default=True),
|
||||||
|
reset_then_reuse_values=dict(type="bool", default=False),
|
||||||
|
insecure_skip_tls_verify=dict(
|
||||||
|
type="bool", default=False, aliases=["skip_tls_certs_check"]
|
||||||
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return arg_spec
|
return arg_spec
|
||||||
@@ -787,6 +860,8 @@ def main():
|
|||||||
set_values = module.params.get("set_values")
|
set_values = module.params.get("set_values")
|
||||||
reuse_values = module.params.get("reuse_values")
|
reuse_values = module.params.get("reuse_values")
|
||||||
reset_values = module.params.get("reset_values")
|
reset_values = module.params.get("reset_values")
|
||||||
|
reset_then_reuse_values = module.params.get("reset_then_reuse_values")
|
||||||
|
insecure_skip_tls_verify = module.params.get("insecure_skip_tls_verify")
|
||||||
|
|
||||||
if update_repo_cache:
|
if update_repo_cache:
|
||||||
run_repo_update(module)
|
run_repo_update(module)
|
||||||
@@ -824,7 +899,9 @@ def main():
|
|||||||
helm_cmd += " --repo=" + chart_repo_url
|
helm_cmd += " --repo=" + chart_repo_url
|
||||||
|
|
||||||
# Fetch chart info to have real version and real name for chart_ref from archive, folder or url
|
# Fetch chart info to have real version and real name for chart_ref from archive, folder or url
|
||||||
chart_info = fetch_chart_info(module, helm_cmd, chart_ref)
|
chart_info = fetch_chart_info(
|
||||||
|
module, helm_cmd, chart_ref, insecure_skip_tls_verify
|
||||||
|
)
|
||||||
|
|
||||||
if dependency_update:
|
if dependency_update:
|
||||||
if chart_info.get("dependencies"):
|
if chart_info.get("dependencies"):
|
||||||
@@ -883,6 +960,8 @@ def main():
|
|||||||
set_value_args=set_value_args,
|
set_value_args=set_value_args,
|
||||||
reuse_values=reuse_values,
|
reuse_values=reuse_values,
|
||||||
reset_values=reset_values,
|
reset_values=reset_values,
|
||||||
|
reset_then_reuse_values=reset_then_reuse_values,
|
||||||
|
insecure_skip_tls_verify=insecure_skip_tls_verify,
|
||||||
)
|
)
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
@@ -908,6 +987,8 @@ def main():
|
|||||||
set_value_args,
|
set_value_args,
|
||||||
reuse_values=reuse_values,
|
reuse_values=reuse_values,
|
||||||
reset_values=reset_values,
|
reset_values=reset_values,
|
||||||
|
reset_then_reuse_values=reset_then_reuse_values,
|
||||||
|
insecure_skip_tls_verify=insecure_skip_tls_verify,
|
||||||
)
|
)
|
||||||
if would_change and module._diff:
|
if would_change and module._diff:
|
||||||
opt_result["diff"] = {"prepared": prepared}
|
opt_result["diff"] = {"prepared": prepared}
|
||||||
@@ -943,6 +1024,8 @@ def main():
|
|||||||
set_value_args=set_value_args,
|
set_value_args=set_value_args,
|
||||||
reuse_values=reuse_values,
|
reuse_values=reuse_values,
|
||||||
reset_values=reset_values,
|
reset_values=reset_values,
|
||||||
|
reset_then_reuse_values=reset_then_reuse_values,
|
||||||
|
insecure_skip_tls_verify=insecure_skip_tls_verify,
|
||||||
)
|
)
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
|
|||||||
@@ -75,9 +75,10 @@ options:
|
|||||||
skip_tls_certs_check:
|
skip_tls_certs_check:
|
||||||
description:
|
description:
|
||||||
- Whether or not to check tls certificate for the chart download.
|
- Whether or not to check tls certificate for the chart download.
|
||||||
- Requires helm >= 3.3.0.
|
- Requires helm >= 3.3.0. Alias C(insecure_skip_tls_verify) added in 5.3.0.
|
||||||
type: bool
|
type: bool
|
||||||
default: False
|
default: False
|
||||||
|
aliases: [ insecure_skip_tls_verify ]
|
||||||
chart_devel:
|
chart_devel:
|
||||||
description:
|
description:
|
||||||
- Use development versions, too. Equivalent to version '>0.0.0-0'.
|
- Use development versions, too. Equivalent to version '>0.0.0-0'.
|
||||||
@@ -190,7 +191,9 @@ def main():
|
|||||||
type="str", no_log=True, aliases=["password", "chart_repo_password"]
|
type="str", no_log=True, aliases=["password", "chart_repo_password"]
|
||||||
),
|
),
|
||||||
pass_credentials=dict(type="bool", default=False, no_log=False),
|
pass_credentials=dict(type="bool", default=False, no_log=False),
|
||||||
skip_tls_certs_check=dict(type="bool", default=False),
|
skip_tls_certs_check=dict(
|
||||||
|
type="bool", default=False, aliases=["insecure_skip_tls_verify"]
|
||||||
|
),
|
||||||
chart_devel=dict(type="bool"),
|
chart_devel=dict(type="bool"),
|
||||||
untar_chart=dict(type="bool", default=False),
|
untar_chart=dict(type="bool", default=False),
|
||||||
destination=dict(type="path", required=True),
|
destination=dict(type="path", required=True),
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ options:
|
|||||||
- Desired state of the registry.
|
- Desired state of the registry.
|
||||||
- If set to V(present) attempt to log in to the remote registry server using the URL specified in O(host).
|
- If set to V(present) attempt to log in to the remote registry server using the URL specified in O(host).
|
||||||
- If set to V(absent) attempt to log out from the remote registry server using the URL specified in O(host).
|
- If set to V(absent) attempt to log out from the remote registry server using the URL specified in O(host).
|
||||||
|
- As helm >= 3.18.0 reports successful logout even if the user is not logged in, this module will report a change regardless of the current state.
|
||||||
required: false
|
required: false
|
||||||
default: present
|
default: present
|
||||||
choices: ['present', 'absent']
|
choices: ['present', 'absent']
|
||||||
@@ -129,6 +130,9 @@ failed:
|
|||||||
from ansible_collections.kubernetes.core.plugins.module_utils.helm import (
|
from ansible_collections.kubernetes.core.plugins.module_utils.helm import (
|
||||||
AnsibleHelmModule,
|
AnsibleHelmModule,
|
||||||
)
|
)
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
|
||||||
|
LooseVersion,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def arg_spec():
|
def arg_spec():
|
||||||
@@ -231,6 +235,13 @@ def main():
|
|||||||
command=helm_cmd,
|
command=helm_cmd,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
helm_version = module.get_helm_version()
|
||||||
|
if LooseVersion(helm_version) >= LooseVersion("3.18.0") and state == "absent":
|
||||||
|
# https://github.com/ansible-collections/kubernetes.core/issues/944
|
||||||
|
module.warn(
|
||||||
|
"The helm_registry_auth is not idempotent with helm >= 3.18.0, always report a change."
|
||||||
|
)
|
||||||
|
|
||||||
module.exit_json(changed=changed, stdout=out, stderr=err, command=helm_cmd)
|
module.exit_json(changed=changed, stdout=out, stderr=err, command=helm_cmd)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -119,6 +119,13 @@ options:
|
|||||||
aliases: [ force ]
|
aliases: [ force ]
|
||||||
default: False
|
default: False
|
||||||
version_added: 2.4.0
|
version_added: 2.4.0
|
||||||
|
insecure_skip_tls_verify:
|
||||||
|
description:
|
||||||
|
- Skip tls certificate checks for the repository url.
|
||||||
|
type: bool
|
||||||
|
default: False
|
||||||
|
aliases: [ skip_tls_certs_check ]
|
||||||
|
version_added: "5.3.0"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
EXAMPLES = r"""
|
EXAMPLES = r"""
|
||||||
@@ -226,6 +233,7 @@ def install_repository(
|
|||||||
repository_password,
|
repository_password,
|
||||||
pass_credentials,
|
pass_credentials,
|
||||||
force_update,
|
force_update,
|
||||||
|
insecure_skip_tls_verify,
|
||||||
):
|
):
|
||||||
install_command = command + " repo add " + repository_name + " " + repository_url
|
install_command = command + " repo add " + repository_name + " " + repository_url
|
||||||
|
|
||||||
@@ -239,6 +247,9 @@ def install_repository(
|
|||||||
if force_update:
|
if force_update:
|
||||||
install_command += " --force-update"
|
install_command += " --force-update"
|
||||||
|
|
||||||
|
if insecure_skip_tls_verify:
|
||||||
|
install_command += " --insecure-skip-tls-verify"
|
||||||
|
|
||||||
return install_command
|
return install_command
|
||||||
|
|
||||||
|
|
||||||
@@ -262,6 +273,9 @@ def argument_spec():
|
|||||||
),
|
),
|
||||||
pass_credentials=dict(type="bool", default=False, no_log=True),
|
pass_credentials=dict(type="bool", default=False, no_log=True),
|
||||||
force_update=dict(type="bool", default=False, aliases=["force"]),
|
force_update=dict(type="bool", default=False, aliases=["force"]),
|
||||||
|
insecure_skip_tls_verify=dict(
|
||||||
|
type="bool", default=False, aliases=["skip_tls_certs_check"]
|
||||||
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return arg_spec
|
return arg_spec
|
||||||
@@ -290,6 +304,7 @@ def main():
|
|||||||
repo_state = module.params.get("repo_state")
|
repo_state = module.params.get("repo_state")
|
||||||
pass_credentials = module.params.get("pass_credentials")
|
pass_credentials = module.params.get("pass_credentials")
|
||||||
force_update = module.params.get("force_update")
|
force_update = module.params.get("force_update")
|
||||||
|
insecure_skip_tls_verify = module.params.get("insecure_skip_tls_verify")
|
||||||
|
|
||||||
helm_cmd = module.get_helm_binary()
|
helm_cmd = module.get_helm_binary()
|
||||||
|
|
||||||
@@ -308,6 +323,7 @@ def main():
|
|||||||
repo_password,
|
repo_password,
|
||||||
pass_credentials,
|
pass_credentials,
|
||||||
force_update,
|
force_update,
|
||||||
|
insecure_skip_tls_verify,
|
||||||
)
|
)
|
||||||
changed = True
|
changed = True
|
||||||
elif repository_status["url"] != repo_url:
|
elif repository_status["url"] != repo_url:
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ options:
|
|||||||
|
|
||||||
notes:
|
notes:
|
||||||
- the tar binary is required on the container when copying from local filesystem to pod.
|
- 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"""
|
EXAMPLES = r"""
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ helm_default_archive_name: "helm-{{ helm_version }}-{{ ansible_system | lower }}
|
|||||||
helm_binary: "/tmp/helm/{{ ansible_system | lower }}-amd64/helm"
|
helm_binary: "/tmp/helm/{{ ansible_system | lower }}-amd64/helm"
|
||||||
|
|
||||||
chart_test: "ingress-nginx"
|
chart_test: "ingress-nginx"
|
||||||
|
chart_test_oci: "oci://registry-1.docker.io/bitnamicharts/redis"
|
||||||
chart_test_local_path: "nginx-ingress"
|
chart_test_local_path: "nginx-ingress"
|
||||||
chart_test_version: 4.2.4
|
chart_test_version: 4.2.4
|
||||||
chart_test_version_local_path: 1.32.0
|
chart_test_version_local_path: 1.32.0
|
||||||
@@ -26,3 +27,5 @@ test_namespace:
|
|||||||
- "helm-from-url"
|
- "helm-from-url"
|
||||||
- "helm-reuse-values"
|
- "helm-reuse-values"
|
||||||
- "helm-chart-with-space-into-name"
|
- "helm-chart-with-space-into-name"
|
||||||
|
- "helm-reset-then-reuse-values"
|
||||||
|
- "helm-insecure"
|
||||||
|
|||||||
@@ -4,4 +4,5 @@
|
|||||||
loop_control:
|
loop_control:
|
||||||
loop_var: helm_version
|
loop_var: helm_version
|
||||||
with_items:
|
with_items:
|
||||||
- "v3.8.0"
|
- "v3.15.4"
|
||||||
|
- "v3.16.0"
|
||||||
|
|||||||
@@ -28,6 +28,9 @@
|
|||||||
- name: test helm upgrade with reuse_values
|
- name: test helm upgrade with reuse_values
|
||||||
include_tasks: test_helm_reuse_values.yml
|
include_tasks: test_helm_reuse_values.yml
|
||||||
|
|
||||||
|
- name: test helm upgrade with reset_then_reuse_values
|
||||||
|
include_tasks: test_helm_reset_then_reuse_values.yml
|
||||||
|
|
||||||
- name: test helm dependency update
|
- name: test helm dependency update
|
||||||
include_tasks: test_up_dep.yml
|
include_tasks: test_up_dep.yml
|
||||||
|
|
||||||
@@ -41,6 +44,9 @@
|
|||||||
- name: Test Skip CRDS feature in helm chart install
|
- name: Test Skip CRDS feature in helm chart install
|
||||||
include_tasks: test_crds.yml
|
include_tasks: test_crds.yml
|
||||||
|
|
||||||
|
- name: Test insecure registry flag feature
|
||||||
|
include_tasks: test_helm_insecure.yml
|
||||||
|
|
||||||
- name: Clean helm install
|
- name: Clean helm install
|
||||||
file:
|
file:
|
||||||
path: "{{ item }}"
|
path: "{{ item }}"
|
||||||
|
|||||||
@@ -3,12 +3,23 @@
|
|||||||
vars:
|
vars:
|
||||||
test_chart: "test-crds"
|
test_chart: "test-crds"
|
||||||
helm_namespace: "{{ test_namespace[0] }}"
|
helm_namespace: "{{ test_namespace[0] }}"
|
||||||
|
helm_binary: helm
|
||||||
block:
|
block:
|
||||||
- name: Create namespace
|
- name: Create namespace
|
||||||
k8s:
|
k8s:
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
name: "{{ helm_namespace }}"
|
name: "{{ helm_namespace }}"
|
||||||
|
|
||||||
|
- name: Check if CRD resource is already present
|
||||||
|
k8s_info:
|
||||||
|
namespace: default
|
||||||
|
kind: Foo
|
||||||
|
api_version: ansible.com/v1
|
||||||
|
ignore_errors: true
|
||||||
|
register: crd_check
|
||||||
|
|
||||||
|
- when: crd_check is failed
|
||||||
|
block:
|
||||||
- name: Copy test chart
|
- name: Copy test chart
|
||||||
copy:
|
copy:
|
||||||
src: "{{ test_chart }}"
|
src: "{{ test_chart }}"
|
||||||
|
|||||||
52
tests/integration/targets/helm/tasks/test_helm_insecure.yml
Normal file
52
tests/integration/targets/helm/tasks/test_helm_insecure.yml
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
---
|
||||||
|
- name: Test helm insecure
|
||||||
|
vars:
|
||||||
|
helm_namespace: "{{ test_namespace[12] }}"
|
||||||
|
block:
|
||||||
|
|
||||||
|
- name: Initial chart installation (no flag set)
|
||||||
|
helm:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
chart_ref: "{{ chart_test_oci }}"
|
||||||
|
release_name: test-secure
|
||||||
|
release_namespace: "{{ helm_namespace }}"
|
||||||
|
create_namespace: true
|
||||||
|
register: install
|
||||||
|
|
||||||
|
- name: Validate that insecure flag is not set
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- install is changed
|
||||||
|
- '"--insecure-skip-tls-verify" not in install.command'
|
||||||
|
|
||||||
|
- name: Initial chart installation (insecure flag set)
|
||||||
|
helm:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
chart_ref: "{{ chart_test_oci }}"
|
||||||
|
release_name: test-insecure
|
||||||
|
release_namespace: "{{ helm_namespace }}"
|
||||||
|
insecure_skip_tls_verify: true
|
||||||
|
register: install
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Validate that insecure flag IS set if helm version is >= 3.16.0
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- install is changed
|
||||||
|
- '"--insecure-skip-tls-verify" in install.command'
|
||||||
|
when: '"v3.16.0" <= helm_version'
|
||||||
|
|
||||||
|
- name: Validate that feature fails for helm < 3.16.0
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- install is failed
|
||||||
|
- '"insecure_skip_tls_verify requires helm >= 3.16.0" in install.msg'
|
||||||
|
when: 'helm_version < "v3.16.0"'
|
||||||
|
|
||||||
|
always:
|
||||||
|
- name: Remove helm namespace
|
||||||
|
k8s:
|
||||||
|
api_version: v1
|
||||||
|
kind: Namespace
|
||||||
|
name: "{{ helm_namespace }}"
|
||||||
|
state: absent
|
||||||
@@ -13,3 +13,11 @@
|
|||||||
that:
|
that:
|
||||||
- helm_missing_binary is failed
|
- helm_missing_binary is failed
|
||||||
- "'No such file or directory' in helm_missing_binary.msg"
|
- "'No such file or directory' in helm_missing_binary.msg"
|
||||||
|
when: ansible_version.full is version('2.20', '<')
|
||||||
|
|
||||||
|
- name: Assert that helm is not installed (ansible 2.20+)
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- helm_missing_binary is failed
|
||||||
|
- "'Error executing command' in helm_missing_binary.msg"
|
||||||
|
when: ansible_version.full is version('2.20', '>=')
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
---
|
||||||
|
- name: Test helm reset_then_reuse_values
|
||||||
|
vars:
|
||||||
|
helm_namespace: "{{ test_namespace[11] }}"
|
||||||
|
chart_release_values:
|
||||||
|
replica:
|
||||||
|
replicaCount: 3
|
||||||
|
master:
|
||||||
|
count: 1
|
||||||
|
kind: Deployment
|
||||||
|
chart_reset_then_reuse_values:
|
||||||
|
replica:
|
||||||
|
replicaCount: 1
|
||||||
|
master:
|
||||||
|
count: 3
|
||||||
|
block:
|
||||||
|
- name: Initial chart installation
|
||||||
|
helm:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
chart_ref: oci://registry-1.docker.io/bitnamicharts/redis
|
||||||
|
release_name: test-redis
|
||||||
|
release_namespace: "{{ helm_namespace }}"
|
||||||
|
create_namespace: true
|
||||||
|
release_values: "{{ chart_release_values }}"
|
||||||
|
register: install
|
||||||
|
|
||||||
|
- name: Get value set as string
|
||||||
|
helm_info:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
release_name: test-redis
|
||||||
|
release_namespace: "{{ helm_namespace }}"
|
||||||
|
register: release_value
|
||||||
|
|
||||||
|
- name: Validate that chart values are as expected
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- install is changed
|
||||||
|
- '"--reset-then-reuse-values" not in install.command'
|
||||||
|
- release_value["status"]["values"] == chart_release_values
|
||||||
|
|
||||||
|
- name: Upgrade chart using reset_then_reuse_values=true
|
||||||
|
helm:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
chart_ref: oci://registry-1.docker.io/bitnamicharts/redis
|
||||||
|
release_name: test-redis
|
||||||
|
release_namespace: "{{ helm_namespace }}"
|
||||||
|
reuse_values: false
|
||||||
|
reset_values: false
|
||||||
|
reset_then_reuse_values: true
|
||||||
|
release_values: "{{ chart_reset_then_reuse_values }}"
|
||||||
|
register: upgrade
|
||||||
|
|
||||||
|
- name: Get value set as string
|
||||||
|
helm_info:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
release_name: test-redis
|
||||||
|
release_namespace: "{{ helm_namespace }}"
|
||||||
|
register: release_value
|
||||||
|
|
||||||
|
- name: Validate that chart values are as expected
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- upgrade is changed
|
||||||
|
- '"--reset-then-reuse-values" in upgrade.command'
|
||||||
|
- '"--reuse-values " not in upgrade.command'
|
||||||
|
- '"--reset-values" not in upgrade.command'
|
||||||
|
- release_value["status"]["values"] == chart_release_values | combine(chart_reset_then_reuse_values, recursive=true)
|
||||||
|
|
||||||
|
always:
|
||||||
|
- name: Remove helm namespace
|
||||||
|
k8s:
|
||||||
|
api_version: v1
|
||||||
|
kind: Namespace
|
||||||
|
name: "{{ helm_namespace }}"
|
||||||
|
state: absent
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
binary_path: "{{ helm_binary }}"
|
binary_path: "{{ helm_binary }}"
|
||||||
state: present
|
state: present
|
||||||
plugin_path: https://github.com/databus23/helm-diff
|
plugin_path: https://github.com/databus23/helm-diff
|
||||||
plugin_version: 3.4.0
|
plugin_version: 3.9.13
|
||||||
|
|
||||||
- name: Copy test chart
|
- name: Copy test chart
|
||||||
copy:
|
copy:
|
||||||
@@ -324,3 +324,5 @@
|
|||||||
ignore_errors: true
|
ignore_errors: true
|
||||||
|
|
||||||
- include_tasks: reuse_values.yml
|
- include_tasks: reuse_values.yml
|
||||||
|
|
||||||
|
- include_tasks: reset_then_reuse_values.yml
|
||||||
|
|||||||
@@ -0,0 +1,189 @@
|
|||||||
|
---
|
||||||
|
- name: Create temporary directory for helm chart
|
||||||
|
tempfile:
|
||||||
|
suffix: .helm
|
||||||
|
state: directory
|
||||||
|
register: helm_dir
|
||||||
|
|
||||||
|
- name: Test helm diff functionality
|
||||||
|
vars:
|
||||||
|
test_chart_path: "{{ helm_dir.path }}/test-chart-reuse-values"
|
||||||
|
test_release_name: "myrelease"
|
||||||
|
|
||||||
|
block:
|
||||||
|
- name: Install helm diff
|
||||||
|
kubernetes.core.helm_plugin:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
state: present
|
||||||
|
plugin_path: https://github.com/databus23/helm-diff
|
||||||
|
plugin_version: 3.9.14
|
||||||
|
|
||||||
|
- name: Copy test chart
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "test-chart-reuse-values"
|
||||||
|
dest: "{{ helm_dir.path }}"
|
||||||
|
|
||||||
|
- name: Delete existing namespace
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
state: absent
|
||||||
|
wait: true
|
||||||
|
kind: Namespace
|
||||||
|
name: "{{ helm_namespace }}"
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Create helm release
|
||||||
|
kubernetes.core.helm:
|
||||||
|
state: present
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
chart_ref: "{{ test_chart_path }}"
|
||||||
|
release_name: "{{ test_release_name }}"
|
||||||
|
release_namespace: "{{ helm_namespace }}"
|
||||||
|
create_namespace: true
|
||||||
|
release_values:
|
||||||
|
ansible_version: devel
|
||||||
|
phase: ci
|
||||||
|
wait: true
|
||||||
|
|
||||||
|
- name: Upgrade helm release (reset_values=false and reuse_values=false and reset_then_reuse_values=true)
|
||||||
|
kubernetes.core.helm:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
chart_ref: "{{ test_chart_path }}"
|
||||||
|
reset_values: false
|
||||||
|
reuse_values: false
|
||||||
|
reset_then_reuse_values: true
|
||||||
|
release_name: "{{ test_release_name }}"
|
||||||
|
release_namespace: "{{ helm_namespace }}"
|
||||||
|
values:
|
||||||
|
ansible_version: devel
|
||||||
|
register: helm_upgrade
|
||||||
|
|
||||||
|
- name: Ensure task did not reported change
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- helm_upgrade is not changed
|
||||||
|
|
||||||
|
- name: Upgrade helm release (reset_then_reuse_values=true with default value for reset_values and reuse_values=false)
|
||||||
|
kubernetes.core.helm:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
chart_ref: "{{ test_chart_path }}"
|
||||||
|
reuse_values: false
|
||||||
|
reset_then_reuse_values: true
|
||||||
|
release_name: "{{ test_release_name }}"
|
||||||
|
release_namespace: "{{ helm_namespace }}"
|
||||||
|
values:
|
||||||
|
ansible_version: devel
|
||||||
|
register: helm_upgrade
|
||||||
|
|
||||||
|
- name: Ensure task reported change
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- helm_upgrade is changed
|
||||||
|
|
||||||
|
# Delete helm and helm diff to install older version
|
||||||
|
- name: Uninstall helm diff
|
||||||
|
helm_plugin:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
state: absent
|
||||||
|
plugin_name: diff
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Delete Helm folders
|
||||||
|
file:
|
||||||
|
path: /tmp/helm/
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Init Helm folders
|
||||||
|
file:
|
||||||
|
path: /tmp/helm
|
||||||
|
state: directory
|
||||||
|
|
||||||
|
- name: Set Helm old version
|
||||||
|
set_fact:
|
||||||
|
helm_archive_name: "helm-v3.8.0-linux-amd64.tar.gz"
|
||||||
|
helm_diff_old_version: "3.8.0"
|
||||||
|
|
||||||
|
- name: Unarchive Helm binary
|
||||||
|
unarchive:
|
||||||
|
src: "https://get.helm.sh/{{ helm_archive_name | default(helm_default_archive_name) }}"
|
||||||
|
dest: /tmp/helm/
|
||||||
|
remote_src: yes
|
||||||
|
retries: 10
|
||||||
|
delay: 5
|
||||||
|
register: result
|
||||||
|
until: result is not failed
|
||||||
|
|
||||||
|
- name: Upgrade helm release (with reset_then_reuse_values=true)
|
||||||
|
kubernetes.core.helm:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
chart_ref: "{{ test_chart_path }}"
|
||||||
|
reuse_values: false
|
||||||
|
reset_then_reuse_values: true
|
||||||
|
release_name: "{{ test_release_name }}"
|
||||||
|
release_namespace: "{{ helm_namespace }}"
|
||||||
|
values:
|
||||||
|
ansible_version: test
|
||||||
|
register: helm_upgrade
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Debug
|
||||||
|
debug:
|
||||||
|
var: helm_upgrade
|
||||||
|
|
||||||
|
- name: Ensure warning for Helm version
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- helm_upgrade is failed
|
||||||
|
- '"reset_then_reuse_values requires helm >= 3.14.0, current version is" in helm_upgrade.msg'
|
||||||
|
|
||||||
|
- name: Install helm diff
|
||||||
|
helm_plugin:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
state: present
|
||||||
|
plugin_path: https://github.com/databus23/helm-diff
|
||||||
|
plugin_version: "{{ helm_diff_old_version }}"
|
||||||
|
|
||||||
|
- name: Upgrade helm release (with reset_then_reuse_values=true)
|
||||||
|
kubernetes.core.helm:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
chart_ref: "{{ test_chart_path }}"
|
||||||
|
reuse_values: false
|
||||||
|
reset_then_reuse_values: true
|
||||||
|
release_name: "{{ test_release_name }}"
|
||||||
|
release_namespace: "{{ helm_namespace }}"
|
||||||
|
values:
|
||||||
|
ansible_version: devel
|
||||||
|
register: helm_upgrade
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Debug
|
||||||
|
debug:
|
||||||
|
var: helm_upgrade
|
||||||
|
|
||||||
|
- name: Ensure warning for Helm Diff version
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- helm_upgrade is failed
|
||||||
|
- '"reset_then_reuse_values requires helm diff >= 3.9.12, current version is" in helm_upgrade.msg'
|
||||||
|
|
||||||
|
always:
|
||||||
|
- name: Remove temporary directory
|
||||||
|
file:
|
||||||
|
path: "{{ helm_dir.path }}"
|
||||||
|
state: absent
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Uninstall helm diff
|
||||||
|
kubernetes.core.helm_plugin:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
state: absent
|
||||||
|
plugin_name: diff
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Remove helm namespace
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
api_version: v1
|
||||||
|
kind: Namespace
|
||||||
|
name: "{{ helm_namespace }}"
|
||||||
|
state: absent
|
||||||
|
wait: true
|
||||||
|
ignore_errors: true
|
||||||
@@ -90,4 +90,5 @@
|
|||||||
kind: Namespace
|
kind: Namespace
|
||||||
name: "{{ helm_namespace }}"
|
name: "{{ helm_namespace }}"
|
||||||
state: absent
|
state: absent
|
||||||
|
wait: true
|
||||||
ignore_errors: true
|
ignore_errors: true
|
||||||
|
|||||||
@@ -108,6 +108,10 @@
|
|||||||
assert:
|
assert:
|
||||||
that: "'Removing login credentials' in _helm_registry_auth_logout.stderr"
|
that: "'Removing login credentials' in _helm_registry_auth_logout.stderr"
|
||||||
|
|
||||||
|
- name: Test idempotency of logout with helm < 3.18.0
|
||||||
|
when: _helm_version.stdout is ansible.builtin.version('v3.18.0', '<')
|
||||||
|
block:
|
||||||
|
|
||||||
- name: Test logout idempotency
|
- name: Test logout idempotency
|
||||||
helm_registry_auth:
|
helm_registry_auth:
|
||||||
host: localhost:{{ registry_port }}
|
host: localhost:{{ registry_port }}
|
||||||
@@ -133,8 +137,7 @@
|
|||||||
# Helm binary prints the message to stderr
|
# Helm binary prints the message to stderr
|
||||||
ansible.builtin.assert:
|
ansible.builtin.assert:
|
||||||
that:
|
that:
|
||||||
- "'push access denied' in _save_chart.stderr"
|
- "'push access denied' in _save_chart.stderr or 'basic credential not found' in _save_chart.stderr"
|
||||||
- "'authorization failed' in _save_chart.stderr"
|
|
||||||
- "_save_chart.rc != 0"
|
- "_save_chart.rc != 0"
|
||||||
- "'localhost:{{ registry_port }}' not in _config_json.content | b64decode"
|
- "'localhost:{{ registry_port }}' not in _config_json.content | b64decode"
|
||||||
|
|
||||||
@@ -155,7 +158,8 @@
|
|||||||
- name: Assert that the registry is not logged in and auth data is not saved
|
- name: Assert that the registry is not logged in and auth data is not saved
|
||||||
ansible.builtin.assert:
|
ansible.builtin.assert:
|
||||||
that:
|
that:
|
||||||
- "'401 Unauthorized' in _helm_registry_auth_wrong.stderr"
|
- "'401' in _helm_registry_auth_wrong.stderr"
|
||||||
|
- "'unauthorized' in _helm_registry_auth_wrong.stderr | lower"
|
||||||
- "'{{ wrong_password }}' not in _helm_registry_auth_correct.command"
|
- "'{{ wrong_password }}' not in _helm_registry_auth_correct.command"
|
||||||
- "'{{ wrong_password }}' not in _helm_registry_auth_correct.stdout"
|
- "'{{ wrong_password }}' not in _helm_registry_auth_correct.stdout"
|
||||||
- "'{{ wrong_password }}' not in _helm_registry_auth_correct.stderr"
|
- "'{{ wrong_password }}' not in _helm_registry_auth_correct.stderr"
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
---
|
---
|
||||||
|
collections:
|
||||||
|
- kubernetes.core
|
||||||
dependencies:
|
dependencies:
|
||||||
- install_helm
|
- install_helm
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- repository is changed
|
- repository is changed
|
||||||
|
- '"--insecure-skip-tls-verify" not in repository.command'
|
||||||
|
|
||||||
- name: Check idempotency
|
- name: Check idempotency
|
||||||
helm_repository:
|
helm_repository:
|
||||||
@@ -78,3 +79,23 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- repository is not changed
|
- repository is not changed
|
||||||
|
|
||||||
|
- name: Add test_helm_repo chart repository as insecure
|
||||||
|
helm_repository:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
name: test_helm_repo
|
||||||
|
repo_url: "{{ chart_test_repo }}"
|
||||||
|
insecure_skip_tls_verify: true
|
||||||
|
register: repository
|
||||||
|
|
||||||
|
- name: Assert that repository added and flag set
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- repository is changed
|
||||||
|
- '"--insecure-skip-tls-verify" in repository.command'
|
||||||
|
|
||||||
|
- name: Clean test_helm_repo chart repository
|
||||||
|
helm_repository:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
name: test_helm_repo
|
||||||
|
state: absent
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
---
|
---
|
||||||
helm_version: v3.8.0
|
helm_version: v3.16.4
|
||||||
helm_install_path: /tmp/helm
|
helm_install_path: /tmp/helm
|
||||||
helm_default_archive_name: "helm-{{ helm_version }}-{{ ansible_system | lower }}-amd64.tar.gz"
|
helm_default_archive_name: "helm-{{ helm_version }}-{{ ansible_system | lower }}-amd64.tar.gz"
|
||||||
|
|||||||
@@ -26,7 +26,8 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- k8s_configmap is changed
|
- k8s_configmap is changed
|
||||||
- k8s_configmap.result.metadata.annotations|default(False)
|
- '"annotations" in k8s_configmap.result.metadata'
|
||||||
|
- k8s_configmap.result.metadata.annotations != {}
|
||||||
|
|
||||||
- name: Add same configmap again
|
- name: Add same configmap again
|
||||||
k8s:
|
k8s:
|
||||||
@@ -467,7 +468,7 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- k8s_secret is changed
|
- k8s_secret is changed
|
||||||
- k8s_secret.result.data.foo
|
- k8s_secret.result.data.foo != ""
|
||||||
|
|
||||||
- name: Add same secret
|
- name: Add same secret
|
||||||
k8s:
|
k8s:
|
||||||
@@ -748,7 +749,7 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- _create is changed
|
- _create is changed
|
||||||
- not _info.resources
|
- _info.resources | length == 0
|
||||||
|
|
||||||
# server side apply over kubernetes client releases
|
# server side apply over kubernetes client releases
|
||||||
- name: Create temporary directory
|
- name: Create temporary directory
|
||||||
|
|||||||
@@ -14,3 +14,9 @@ pod_with_two_container:
|
|||||||
|
|
||||||
pod_without_executable_find:
|
pod_without_executable_find:
|
||||||
name: openjdk-pod
|
name: openjdk-pod
|
||||||
|
|
||||||
|
pod_with_initcontainer_and_container:
|
||||||
|
name: pod-copy-2
|
||||||
|
container:
|
||||||
|
- container-20
|
||||||
|
- container-21
|
||||||
|
|||||||
@@ -18,6 +18,23 @@
|
|||||||
wait: yes
|
wait: yes
|
||||||
template: pods_definition.j2
|
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_copy_errors.yml
|
||||||
- include_tasks: test_check_mode.yml
|
- include_tasks: test_check_mode.yml
|
||||||
- include_tasks: test_copy_file.yml
|
- include_tasks: test_copy_file.yml
|
||||||
@@ -25,6 +42,7 @@
|
|||||||
- include_tasks: test_copy_directory.yml
|
- include_tasks: test_copy_directory.yml
|
||||||
- include_tasks: test_copy_large_file.yml
|
- include_tasks: test_copy_large_file.yml
|
||||||
- include_tasks: test_copy_item_with_space_in_its_name.yml
|
- include_tasks: test_copy_item_with_space_in_its_name.yml
|
||||||
|
- include_tasks: test_init_container_pod.yml
|
||||||
|
|
||||||
always:
|
always:
|
||||||
|
|
||||||
|
|||||||
@@ -67,3 +67,21 @@
|
|||||||
that:
|
that:
|
||||||
- copy_fake_container is failed
|
- copy_fake_container is failed
|
||||||
- copy_fake_container.msg == "Pod has no container this_is_a_fake_container"
|
- 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
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
- name: Assert that there are pods
|
- name: Assert that there are pods
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- pods_create.resources
|
- pods_create.resources | length > 0
|
||||||
|
|
||||||
- name: Remove the daemonset
|
- name: Remove the daemonset
|
||||||
k8s:
|
k8s:
|
||||||
@@ -74,7 +74,7 @@
|
|||||||
- name: Assert that deleting the daemonset deleted the pods
|
- name: Assert that deleting the daemonset deleted the pods
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- not pods_delete.resources
|
- pods_delete.resources | length == 0
|
||||||
|
|
||||||
# test deletion using label selector
|
# test deletion using label selector
|
||||||
- name: Deploy load balancer
|
- name: Deploy load balancer
|
||||||
@@ -152,6 +152,27 @@
|
|||||||
register: _deployment
|
register: _deployment
|
||||||
failed_when: _deployment.resources | length == 0
|
failed_when: _deployment.resources | length == 0
|
||||||
|
|
||||||
|
- name: Trying to delete nginx deployment in check mode and with deleteOptions set
|
||||||
|
k8s:
|
||||||
|
kind: Deployment
|
||||||
|
api_version: apps/v1
|
||||||
|
namespace: "{{ test_namespace }}"
|
||||||
|
name: nginx-d
|
||||||
|
state: absent
|
||||||
|
delete_options:
|
||||||
|
propagationPolicy: Foreground
|
||||||
|
check_mode: true
|
||||||
|
register: _delete
|
||||||
|
|
||||||
|
- name: Validate that Deployment nginx-d still exists
|
||||||
|
k8s_info:
|
||||||
|
kind: Deployment
|
||||||
|
api_version: apps/v1
|
||||||
|
namespace: "{{ test_namespace }}"
|
||||||
|
name: nginx-d
|
||||||
|
register: _deployment
|
||||||
|
failed_when: _deployment.resources | length != 1
|
||||||
|
|
||||||
- name: Trying to delete using delete_all=true but missing kind option
|
- name: Trying to delete using delete_all=true but missing kind option
|
||||||
k8s:
|
k8s:
|
||||||
api_version: apps/v1
|
api_version: apps/v1
|
||||||
|
|||||||
@@ -244,7 +244,7 @@
|
|||||||
kind: Pod
|
kind: Pod
|
||||||
name: '{{ drain_pod_name }}'
|
name: '{{ drain_pod_name }}'
|
||||||
register: _result
|
register: _result
|
||||||
failed_when: _result.resources
|
failed_when: _result.resources | length > 0
|
||||||
|
|
||||||
- name: assert that emptyDir pod was deleted
|
- name: assert that emptyDir pod was deleted
|
||||||
k8s_info:
|
k8s_info:
|
||||||
@@ -346,7 +346,7 @@
|
|||||||
kind: Pod
|
kind: Pod
|
||||||
name: '{{ drain_pod_name }}-01'
|
name: '{{ drain_pod_name }}-01'
|
||||||
register: _result
|
register: _result
|
||||||
failed_when: _result.resources
|
failed_when: _result.resources | length > 0
|
||||||
|
|
||||||
# test: drain using pod_selectors
|
# test: drain using pod_selectors
|
||||||
- name: Uncordon node
|
- name: Uncordon node
|
||||||
|
|||||||
@@ -394,9 +394,11 @@
|
|||||||
register: k8s_info_testing6
|
register: k8s_info_testing6
|
||||||
failed_when: not k8s_info_testing6.resources or k8s_info_testing6.resources[0].status.phase != "Active"
|
failed_when: not k8s_info_testing6.resources or k8s_info_testing6.resources[0].status.phase != "Active"
|
||||||
|
|
||||||
- name: Create large configmap data
|
- name: Create a file with specific size and attributes, to be used as swap space
|
||||||
command: dd if=/dev/urandom bs=500K count=1
|
community.general.filesize:
|
||||||
register: cmap_data
|
path: /tmp/configmap.bin
|
||||||
|
size: 500K
|
||||||
|
source: /dev/urandom
|
||||||
|
|
||||||
- name: Create configmap with large value
|
- name: Create configmap with large value
|
||||||
k8s:
|
k8s:
|
||||||
@@ -407,7 +409,7 @@
|
|||||||
name: testmap
|
name: testmap
|
||||||
namespace: testing
|
namespace: testing
|
||||||
data:
|
data:
|
||||||
testkey: "{{ cmap_data.stdout | b64encode }}"
|
testkey: "{{ lookup('file', '/tmp/configmap.bin') | b64encode }}"
|
||||||
wait: true
|
wait: true
|
||||||
register: result
|
register: result
|
||||||
|
|
||||||
@@ -424,7 +426,7 @@
|
|||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- result.resources[0].data.testkey == (cmap_data.stdout | b64encode)
|
- result.resources[0].data.testkey == (lookup('file', '/tmp/configmap.bin') | b64encode)
|
||||||
|
|
||||||
# test setting module defaults for kubernetes.core.k8s_info
|
# test setting module defaults for kubernetes.core.k8s_info
|
||||||
- block:
|
- block:
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
label_selectors:
|
label_selectors:
|
||||||
- "job=gc"
|
- "job=gc"
|
||||||
register: wait_job
|
register: wait_job
|
||||||
until: wait_job.resources
|
until: wait_job.resources | length > 0
|
||||||
retries: 5
|
retries: 5
|
||||||
delay: 10
|
delay: 10
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
label_selectors:
|
label_selectors:
|
||||||
- "job=gc"
|
- "job=gc"
|
||||||
register: wait_job
|
register: wait_job
|
||||||
until: wait_job.resources
|
until: wait_job.resources | length > 0
|
||||||
retries: 5
|
retries: 5
|
||||||
delay: 10
|
delay: 10
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@
|
|||||||
label_selectors:
|
label_selectors:
|
||||||
- "job=gc"
|
- "job=gc"
|
||||||
register: wait_job
|
register: wait_job
|
||||||
until: wait_job.resources
|
until: wait_job.resources | length > 0
|
||||||
retries: 5
|
retries: 5
|
||||||
delay: 10
|
delay: 10
|
||||||
|
|
||||||
@@ -225,7 +225,7 @@
|
|||||||
|
|
||||||
- name: Assert job is deleted
|
- name: Assert job is deleted
|
||||||
assert:
|
assert:
|
||||||
that: not job.resources
|
that: job.resources | length == 0
|
||||||
|
|
||||||
always:
|
always:
|
||||||
- name: Delete namespace
|
- name: Delete namespace
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
- "'managedFields' not in hf4.resources[0]['metadata']"
|
- "'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:
|
k8s:
|
||||||
definition: "{{ hide_fields_base_configmap | combine({'data':{'hello':'different'}}) }}"
|
definition: "{{ hide_fields_base_configmap | combine({'data':{'hello':'different'}}) }}"
|
||||||
hidden_fields:
|
hidden_fields:
|
||||||
@@ -67,10 +67,10 @@
|
|||||||
register: hf5
|
register: hf5
|
||||||
diff: true
|
diff: true
|
||||||
|
|
||||||
- name: Ensure that hidden changed field changed
|
- name: Ensure that hidden changed field not changed
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- hf5.changed
|
- not hf5.changed
|
||||||
|
|
||||||
- name: Apply works with hidden fields
|
- name: Apply works with hidden fields
|
||||||
k8s:
|
k8s:
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
- result.changed
|
- result.changed
|
||||||
- result.result.metadata.labels.label2 == "bar"
|
- result.result.metadata.labels.label2 == "bar"
|
||||||
- result.result.spec.containers[0].image == "busybox:glibc"
|
- result.result.spec.containers[0].image == "busybox:glibc"
|
||||||
- result.diff
|
- result.diff != {}
|
||||||
|
|
||||||
- name: Describe pod
|
- name: Describe pod
|
||||||
kubernetes.core.k8s_info:
|
kubernetes.core.k8s_info:
|
||||||
|
|||||||
@@ -129,7 +129,7 @@
|
|||||||
that:
|
that:
|
||||||
- scale_down is changed
|
- scale_down is changed
|
||||||
- '"duration" in scale_down'
|
- '"duration" in scale_down'
|
||||||
- scale_down.diff
|
- scale_down.diff != {}
|
||||||
|
|
||||||
- name: Scale the deployment once again (idempotency)
|
- name: Scale the deployment once again (idempotency)
|
||||||
k8s_scale:
|
k8s_scale:
|
||||||
@@ -274,7 +274,7 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- scale_down_no_wait is changed
|
- scale_down_no_wait is changed
|
||||||
- scale_down_no_wait.diff
|
- scale_down_no_wait.diff != {}
|
||||||
- scale_down_no_wait_pods.resources | length == 1
|
- scale_down_no_wait_pods.resources | length == 1
|
||||||
|
|
||||||
# scale multiple resource using label selectors
|
# scale multiple resource using label selectors
|
||||||
|
|||||||
@@ -421,7 +421,7 @@
|
|||||||
- name: Assert that taints have been removed
|
- name: Assert that taints have been removed
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- _result.resources | selectattr('spec.taints', 'undefined')
|
- _result.resources | selectattr('spec.taints', 'undefined') | list | length > 0
|
||||||
|
|
||||||
always:
|
always:
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
kubernetes.core.k8s_service:
|
kubernetes.core.k8s_service:
|
||||||
template: "pod_one.j2"
|
template: "pod_one.j2"
|
||||||
state: present
|
state: present
|
||||||
ignore_errors: yes
|
ignore_errors: true
|
||||||
register: r
|
register: r
|
||||||
|
|
||||||
- name: Check for expected failures in last tasks
|
- name: Check for expected failures in last tasks
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
k8s_pod_name_one: pod
|
k8s_pod_name_one: pod
|
||||||
k8s_pod_namespace: "{{ template_namespace }}"
|
k8s_pod_namespace: "{{ template_namespace }}"
|
||||||
register: r
|
register: r
|
||||||
ignore_errors: yes
|
ignore_errors: true
|
||||||
|
|
||||||
- name: Check if definition and template are mutually exclusive
|
- name: Check if definition and template are mutually exclusive
|
||||||
assert:
|
assert:
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
k8s_pod_name_one: pod
|
k8s_pod_name_one: pod
|
||||||
k8s_pod_namespace: "{{ template_namespace }}"
|
k8s_pod_namespace: "{{ template_namespace }}"
|
||||||
register: r
|
register: r
|
||||||
ignore_errors: yes
|
ignore_errors: true
|
||||||
|
|
||||||
- name: Check if src and template are mutually exclusive
|
- name: Check if src and template are mutually exclusive
|
||||||
assert:
|
assert:
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
- name: Create pod using template (direct specification)
|
- name: Create pod using template (direct specification)
|
||||||
kubernetes.core.k8s:
|
kubernetes.core.k8s:
|
||||||
template: "pod_one.j2"
|
template: "pod_one.j2"
|
||||||
wait: yes
|
wait: true
|
||||||
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
||||||
vars:
|
vars:
|
||||||
k8s_pod_name_one: pod-1
|
k8s_pod_name_one: pod-1
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
kubernetes.core.k8s:
|
kubernetes.core.k8s:
|
||||||
template:
|
template:
|
||||||
- default
|
- default
|
||||||
wait: yes
|
wait: true
|
||||||
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
||||||
vars:
|
vars:
|
||||||
k8s_pod_name_one: pod-2
|
k8s_pod_name_one: pod-2
|
||||||
@@ -96,7 +96,7 @@
|
|||||||
kubernetes.core.k8s:
|
kubernetes.core.k8s:
|
||||||
template:
|
template:
|
||||||
path: "pod_one.j2"
|
path: "pod_one.j2"
|
||||||
wait: yes
|
wait: true
|
||||||
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
||||||
vars:
|
vars:
|
||||||
k8s_pod_name_one: pod-3
|
k8s_pod_name_one: pod-3
|
||||||
@@ -114,12 +114,11 @@
|
|||||||
path: "pod_two.j2"
|
path: "pod_two.j2"
|
||||||
variable_start_string: '[['
|
variable_start_string: '[['
|
||||||
variable_end_string: ']]'
|
variable_end_string: ']]'
|
||||||
wait: yes
|
wait: true
|
||||||
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
||||||
vars:
|
vars:
|
||||||
k8s_pod_name_two: pod-4
|
k8s_pod_name_two: pod-4
|
||||||
k8s_pod_namespace: "[[ template_namespace ]]"
|
k8s_pod_namespace: "template-test"
|
||||||
ansible_python_interpreter: "[[ ansible_playbook_python ]]"
|
|
||||||
register: r
|
register: r
|
||||||
|
|
||||||
- name: Assert that pod creation succeeded using template
|
- name: Assert that pod creation succeeded using template
|
||||||
@@ -131,7 +130,7 @@
|
|||||||
kubernetes.core.k8s:
|
kubernetes.core.k8s:
|
||||||
template:
|
template:
|
||||||
path: "pod_three.j2"
|
path: "pod_three.j2"
|
||||||
wait: yes
|
wait: true
|
||||||
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
||||||
vars:
|
vars:
|
||||||
k8s_pod_name_three_one: pod-5
|
k8s_pod_name_three_one: pod-5
|
||||||
@@ -152,7 +151,7 @@
|
|||||||
variable_start_string: '[['
|
variable_start_string: '[['
|
||||||
variable_end_string: ']]'
|
variable_end_string: ']]'
|
||||||
- path: "pod_three.j2"
|
- path: "pod_three.j2"
|
||||||
wait: yes
|
wait: true
|
||||||
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
||||||
vars:
|
vars:
|
||||||
k8s_pod_name_one: pod-7
|
k8s_pod_name_one: pod-7
|
||||||
@@ -239,63 +238,6 @@
|
|||||||
- resource.result.results | selectattr('changed') | list | length == 1
|
- resource.result.results | selectattr('changed') | list | length == 1
|
||||||
- resource.result.results | selectattr('error', 'defined') | list | length == 1
|
- resource.result.results | selectattr('error', 'defined') | list | length == 1
|
||||||
|
|
||||||
# Test resource definition using template with 'omit'
|
|
||||||
- name: Deploy configmap using template
|
|
||||||
k8s:
|
|
||||||
namespace: "{{ template_namespace }}"
|
|
||||||
name: test-data
|
|
||||||
template: configmap.yml.j2
|
|
||||||
|
|
||||||
- name: Read configmap created
|
|
||||||
k8s_info:
|
|
||||||
kind: configmap
|
|
||||||
namespace: "{{ template_namespace }}"
|
|
||||||
name: test-data
|
|
||||||
register: _configmap
|
|
||||||
|
|
||||||
- name: Validate that the configmap does not contains annotations
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- '"annotations" not in _configmap.resources.0.metadata'
|
|
||||||
|
|
||||||
- name: Create resource once again
|
|
||||||
k8s:
|
|
||||||
namespace: "{{ template_namespace }}"
|
|
||||||
name: test-data
|
|
||||||
template: configmap.yml.j2
|
|
||||||
register: _configmap
|
|
||||||
|
|
||||||
- name: assert that nothing changed
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- _configmap is not changed
|
|
||||||
|
|
||||||
- name: Create resource once again (using description)
|
|
||||||
k8s:
|
|
||||||
namespace: "{{ template_namespace }}"
|
|
||||||
name: test-data
|
|
||||||
template: configmap.yml.j2
|
|
||||||
register: _configmap
|
|
||||||
vars:
|
|
||||||
k8s_configmap_desc: "This is a simple configmap used to test ansible k8s collection"
|
|
||||||
|
|
||||||
- name: assert that configmap was changed
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- _configmap is changed
|
|
||||||
|
|
||||||
- name: Read configmap created
|
|
||||||
k8s_info:
|
|
||||||
kind: configmap
|
|
||||||
namespace: "{{ template_namespace }}"
|
|
||||||
name: test-data
|
|
||||||
register: _configmap
|
|
||||||
|
|
||||||
- name: Validate that the configmap does not contains annotations
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- _configmap.resources.0.metadata.annotations.description == "This is a simple configmap used to test ansible k8s collection"
|
|
||||||
|
|
||||||
always:
|
always:
|
||||||
- name: Remove namespace (Cleanup)
|
- name: Remove namespace (Cleanup)
|
||||||
kubernetes.core.k8s:
|
kubernetes.core.k8s:
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
description: "{{ k8s_configmap_desc | default(omit) }}"
|
|
||||||
data:
|
|
||||||
key: "testing-template"
|
|
||||||
@@ -56,8 +56,8 @@
|
|||||||
# Without wantlist=True lookup should return mapping
|
# Without wantlist=True lookup should return mapping
|
||||||
- test5 is mapping
|
- test5 is mapping
|
||||||
- test6 is mapping
|
- test6 is mapping
|
||||||
# errors='ignore'
|
# errors='ignore' (return null with ansible-core 2.19)
|
||||||
- test7 is string
|
- test7 is string or not test7
|
||||||
- test8 is not defined
|
- test8 is not defined
|
||||||
|
|
||||||
- name: Create another namespace with label
|
- name: Create another namespace with label
|
||||||
|
|||||||
@@ -4,10 +4,17 @@
|
|||||||
namespace_to_create: "{{ item.name | default(item) }}"
|
namespace_to_create: "{{ item.name | default(item) }}"
|
||||||
namespace_labels: "{{ item.labels | default(omit) }}"
|
namespace_labels: "{{ item.labels | default(omit) }}"
|
||||||
with_items: "{{ test_namespace }}"
|
with_items: "{{ test_namespace }}"
|
||||||
when: test_namespace | type_debug == "list"
|
when:
|
||||||
|
- test_namespace is not string
|
||||||
|
- test_namespace is not mapping
|
||||||
|
- test_namespace is iterable
|
||||||
|
|
||||||
- include_tasks: tasks/create.yml
|
- include_tasks: tasks/create.yml
|
||||||
vars:
|
vars:
|
||||||
namespace_to_create: "{{ test_namespace }}"
|
namespace_to_create: "{{ test_namespace }}"
|
||||||
namespace_labels: "{{ test_namespace_labels | default(omit) }}"
|
namespace_labels: "{{ test_namespace_labels | default(omit) }}"
|
||||||
when: test_namespace | type_debug == "AnsibleUnicode"
|
when:
|
||||||
|
- test_namespace is string
|
||||||
|
- test_namespace is iterable
|
||||||
|
- test_namespace is sequence
|
||||||
|
- test_namespace is not mapping
|
||||||
|
|||||||
@@ -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/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.9!skip
|
|
||||||
plugins/module_utils/k8sdynamicclient.py import-3.10!skip
|
|
||||||
plugins/module_utils/k8sdynamicclient.py import-3.11!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/clusteroperator.yml yamllint!skip
|
|
||||||
tests/unit/module_utils/fixtures/definitions.yml yamllint!skip
|
|
||||||
tests/unit/module_utils/fixtures/deployments.yml 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/k8s_delete/files/deployments.yaml yamllint!skip
|
|
||||||
tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip
|
|
||||||
tests/integration/targets/helm_registry_auth/tasks/main.yaml yamllint!skip
|
|
||||||
tests/integration/targets/helm_diff/files/test-chart-deployment-time/templates/configmap.yaml yamllint!skip
|
|
||||||
|
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
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.11!skip
|
||||||
plugins/module_utils/client/resource.py import-3.9!skip
|
plugins/module_utils/client/discovery.py import-3.12!skip
|
||||||
plugins/module_utils/client/resource.py import-3.10!skip
|
plugins/module_utils/client/discovery.py import-3.13!skip
|
||||||
plugins/module_utils/client/resource.py import-3.11!skip
|
plugins/module_utils/client/resource.py import-3.11!skip
|
||||||
plugins/module_utils/k8sdynamicclient.py import-3.9!skip
|
plugins/module_utils/client/resource.py import-3.12!skip
|
||||||
plugins/module_utils/k8sdynamicclient.py import-3.10!skip
|
plugins/module_utils/client/resource.py import-3.13!skip
|
||||||
plugins/module_utils/k8sdynamicclient.py import-3.11!skip
|
plugins/module_utils/k8sdynamicclient.py import-3.11!skip
|
||||||
|
plugins/module_utils/k8sdynamicclient.py import-3.12!skip
|
||||||
|
plugins/module_utils/k8sdynamicclient.py import-3.13!skip
|
||||||
plugins/module_utils/version.py pylint!skip
|
plugins/module_utils/version.py pylint!skip
|
||||||
plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc
|
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_scale.py validate-modules:parameter-type-not-in-doc
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Copyright: (c) 2022, Ansible Project
|
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
from ansible_collections.kubernetes.core.plugins.action.k8s_info import RemoveOmit
|
|
||||||
|
|
||||||
|
|
||||||
def get_omit_token():
|
|
||||||
return "__omit_place_holder__%s" % datetime.now().strftime("%Y%m%d%H%M%S")
|
|
||||||
|
|
||||||
|
|
||||||
def test_remove_omit_from_str():
|
|
||||||
omit_token = get_omit_token()
|
|
||||||
src = """
|
|
||||||
project: ansible
|
|
||||||
collection: {omit}
|
|
||||||
""".format(
|
|
||||||
omit=omit_token
|
|
||||||
)
|
|
||||||
result = RemoveOmit(src, omit_value=omit_token).output()
|
|
||||||
assert len(result) == 1
|
|
||||||
assert result[0] == dict(project="ansible")
|
|
||||||
|
|
||||||
|
|
||||||
def test_remove_omit_from_list():
|
|
||||||
omit_token = get_omit_token()
|
|
||||||
src = """
|
|
||||||
items:
|
|
||||||
- {omit}
|
|
||||||
""".format(
|
|
||||||
omit=omit_token
|
|
||||||
)
|
|
||||||
result = RemoveOmit(src, omit_value=omit_token).output()
|
|
||||||
assert len(result) == 1
|
|
||||||
assert result[0] == dict(items=[])
|
|
||||||
|
|
||||||
|
|
||||||
def test_remove_omit_from_list_of_dict():
|
|
||||||
omit_token = get_omit_token()
|
|
||||||
src = """
|
|
||||||
items:
|
|
||||||
- owner: ansible
|
|
||||||
team: {omit}
|
|
||||||
- simple_list_item
|
|
||||||
""".format(
|
|
||||||
omit=omit_token
|
|
||||||
)
|
|
||||||
result = RemoveOmit(src, omit_value=omit_token).output()
|
|
||||||
assert len(result) == 1
|
|
||||||
assert result[0] == dict(items=[dict(owner="ansible"), "simple_list_item"])
|
|
||||||
|
|
||||||
|
|
||||||
def test_remove_omit_combined():
|
|
||||||
omit_token = get_omit_token()
|
|
||||||
src = """
|
|
||||||
items:
|
|
||||||
- {omit}
|
|
||||||
- list_item_a
|
|
||||||
- list_item_b
|
|
||||||
parent:
|
|
||||||
child:
|
|
||||||
subchilda: {omit}
|
|
||||||
subchildb:
|
|
||||||
name: {omit}
|
|
||||||
age: 3
|
|
||||||
""".format(
|
|
||||||
omit=omit_token
|
|
||||||
)
|
|
||||||
result = RemoveOmit(src, omit_value=omit_token).output()
|
|
||||||
assert len(result) == 1
|
|
||||||
assert result[0] == dict(
|
|
||||||
items=["list_item_a", "list_item_b"],
|
|
||||||
parent=dict(child=dict(subchildb=dict(age=3))),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_remove_omit_mutiple_documents():
|
|
||||||
omit_token = get_omit_token()
|
|
||||||
src = [
|
|
||||||
"""
|
|
||||||
project: ansible
|
|
||||||
collection: {omit}
|
|
||||||
""".format(
|
|
||||||
omit=omit_token
|
|
||||||
),
|
|
||||||
"---",
|
|
||||||
"""
|
|
||||||
project: kubernetes
|
|
||||||
environment: production
|
|
||||||
collection: {omit}""".format(
|
|
||||||
omit=omit_token
|
|
||||||
),
|
|
||||||
]
|
|
||||||
src = "\n".join(src)
|
|
||||||
print(src)
|
|
||||||
result = RemoveOmit(src, omit_value=omit_token).output()
|
|
||||||
assert len(result) == 2
|
|
||||||
assert result[0] == dict(project="ansible")
|
|
||||||
assert result[1] == dict(project="kubernetes", environment="production")
|
|
||||||
@@ -10,7 +10,6 @@ import ansible.module_utils.basic
|
|||||||
import pytest
|
import pytest
|
||||||
from ansible.module_utils._text import to_bytes
|
from ansible.module_utils._text import to_bytes
|
||||||
from ansible.module_utils.common._collections_compat import MutableMapping
|
from ansible.module_utils.common._collections_compat import MutableMapping
|
||||||
from ansible.module_utils.six import string_types
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@@ -20,7 +19,7 @@ def stdin(mocker, request):
|
|||||||
old_argv = sys.argv
|
old_argv = sys.argv
|
||||||
sys.argv = ["ansible_unittest"]
|
sys.argv = ["ansible_unittest"]
|
||||||
|
|
||||||
if isinstance(request.param, string_types):
|
if isinstance(request.param, str):
|
||||||
args = request.param
|
args = request.param
|
||||||
elif isinstance(request.param, MutableMapping):
|
elif isinstance(request.param, MutableMapping):
|
||||||
if "ANSIBLE_MODULE_ARGS" not in request.param:
|
if "ANSIBLE_MODULE_ARGS" not in request.param:
|
||||||
|
|||||||
@@ -2,50 +2,57 @@ from __future__ import absolute_import, division, print_function
|
|||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
import json
|
import re
|
||||||
|
|
||||||
import kubernetes
|
import kubernetes
|
||||||
import pytest
|
import pytest
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import (
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import (
|
||||||
AnsibleK8SModule,
|
AnsibleK8SModule,
|
||||||
)
|
)
|
||||||
|
from mock import MagicMock, patch
|
||||||
|
|
||||||
MINIMAL_K8S_VERSION = "24.2.0"
|
MINIMAL_K8S_VERSION = "24.2.0"
|
||||||
UNSUPPORTED_K8S_VERSION = "11.0.0"
|
UNSUPPORTED_K8S_VERSION = "11.0.0"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("stdin", [{}], indirect=["stdin"])
|
class FakeAnsibleModule:
|
||||||
def test_no_warn(monkeypatch, stdin, capfd):
|
def __init__(self, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def exit_json(self):
|
||||||
|
raise SystemExit(0)
|
||||||
|
|
||||||
|
|
||||||
|
@patch.object(AnsibleK8SModule, "warn")
|
||||||
|
def test_no_warn(m_ansible_k8s_module_warn, monkeypatch, capfd):
|
||||||
monkeypatch.setattr(kubernetes, "__version__", MINIMAL_K8S_VERSION)
|
monkeypatch.setattr(kubernetes, "__version__", MINIMAL_K8S_VERSION)
|
||||||
|
|
||||||
module = AnsibleK8SModule(argument_spec={})
|
m_ansible_k8s_module_warn.side_effect = print
|
||||||
|
module = AnsibleK8SModule(argument_spec={}, module_class=FakeAnsibleModule)
|
||||||
with pytest.raises(SystemExit):
|
with pytest.raises(SystemExit):
|
||||||
module.exit_json()
|
module.exit_json()
|
||||||
out, err = capfd.readouterr()
|
out, err = capfd.readouterr()
|
||||||
|
m_ansible_k8s_module_warn.assert_not_called()
|
||||||
return_value = json.loads(out)
|
|
||||||
|
|
||||||
assert return_value.get("exception") is None
|
|
||||||
assert return_value.get("warnings") is None
|
|
||||||
assert return_value.get("failed") is None
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("stdin", [{}], indirect=["stdin"])
|
@patch.object(AnsibleK8SModule, "warn")
|
||||||
def test_warn_on_k8s_version(monkeypatch, stdin, capfd):
|
def test_warn_on_k8s_version(m_ansible_k8s_module_warn, monkeypatch, capfd):
|
||||||
monkeypatch.setattr(kubernetes, "__version__", UNSUPPORTED_K8S_VERSION)
|
monkeypatch.setattr(kubernetes, "__version__", UNSUPPORTED_K8S_VERSION)
|
||||||
|
|
||||||
module = AnsibleK8SModule(argument_spec={})
|
m_ansible_k8s_module_warn.side_effect = print
|
||||||
|
module = AnsibleK8SModule(argument_spec={}, module_class=FakeAnsibleModule)
|
||||||
with pytest.raises(SystemExit):
|
with pytest.raises(SystemExit):
|
||||||
module.exit_json()
|
module.exit_json()
|
||||||
|
|
||||||
|
m_ansible_k8s_module_warn.assert_called_once()
|
||||||
out, err = capfd.readouterr()
|
out, err = capfd.readouterr()
|
||||||
|
assert (
|
||||||
return_value = json.loads(out)
|
re.search(
|
||||||
|
r"kubernetes<([0-9]+\.[0-9]+\.[0-9]+) is not supported or tested. Some features may not work.",
|
||||||
assert return_value.get("warnings") is not None
|
out,
|
||||||
warnings = return_value["warnings"]
|
)
|
||||||
assert len(warnings) == 1
|
is not None
|
||||||
assert "kubernetes" in warnings[0]
|
)
|
||||||
assert MINIMAL_K8S_VERSION in warnings[0]
|
|
||||||
|
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
@@ -58,9 +65,17 @@ dependencies = [
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"stdin,desired,actual,result", [({}, *d) for d in dependencies], indirect=["stdin"]
|
"stdin,desired,actual,result", [({}, *d) for d in dependencies], indirect=["stdin"]
|
||||||
)
|
)
|
||||||
def test_has_at_least(monkeypatch, stdin, desired, actual, result, capfd):
|
@patch.object(AnsibleK8SModule, "warn")
|
||||||
|
def test_has_at_least(
|
||||||
|
m_ansible_k8s_module_warn, monkeypatch, stdin, desired, actual, result, capfd
|
||||||
|
):
|
||||||
monkeypatch.setattr(kubernetes, "__version__", actual)
|
monkeypatch.setattr(kubernetes, "__version__", actual)
|
||||||
|
|
||||||
|
def fake_warn(x):
|
||||||
|
print(x)
|
||||||
|
raise SystemExit(1)
|
||||||
|
|
||||||
|
m_ansible_k8s_module_warn.side_effect = fake_warn
|
||||||
module = AnsibleK8SModule(argument_spec={})
|
module = AnsibleK8SModule(argument_spec={})
|
||||||
|
|
||||||
assert module.has_at_least("kubernetes", desired) is result
|
assert module.has_at_least("kubernetes", desired) is result
|
||||||
@@ -80,11 +95,18 @@ def test_requires_fails_with_message(
|
|||||||
monkeypatch, stdin, dependency, version, msg, capfd
|
monkeypatch, stdin, dependency, version, msg, capfd
|
||||||
):
|
):
|
||||||
monkeypatch.setattr(kubernetes, "__version__", "24.2.0")
|
monkeypatch.setattr(kubernetes, "__version__", "24.2.0")
|
||||||
module = AnsibleK8SModule(argument_spec={})
|
module = AnsibleK8SModule(argument_spec={}, module_class=FakeAnsibleModule)
|
||||||
|
|
||||||
|
def fake_fail_json(**kwargs):
|
||||||
|
print(f"Printing message => {kwargs}")
|
||||||
|
print(kwargs.get("msg"))
|
||||||
|
raise SystemExit(1)
|
||||||
|
|
||||||
|
module.fail_json = MagicMock()
|
||||||
|
module.fail_json.side_effect = fake_fail_json
|
||||||
|
|
||||||
with pytest.raises(SystemExit):
|
with pytest.raises(SystemExit):
|
||||||
module.requires(dependency, version)
|
module.requires(dependency, version)
|
||||||
|
module.fail_json.assert_called_once()
|
||||||
out, err = capfd.readouterr()
|
out, err = capfd.readouterr()
|
||||||
return_value = json.loads(out)
|
assert msg in out
|
||||||
|
|
||||||
assert return_value.get("failed")
|
|
||||||
assert msg in return_value.get("msg")
|
|
||||||
|
|||||||
@@ -202,8 +202,8 @@ def test_service_create_resource_warnings(
|
|||||||
result, warnings = svc.create(Mock(), pod_definition)
|
result, warnings = svc.create(Mock(), pod_definition)
|
||||||
|
|
||||||
assert result == mock_pod_resource_instance.to_dict()
|
assert result == mock_pod_resource_instance.to_dict()
|
||||||
assert warnings[0] == "test warning 1"
|
assert str(warnings[0]) == "test warning 1"
|
||||||
assert warnings[1] == "test warning 2"
|
assert str(warnings[1]) == "test warning 2"
|
||||||
|
|
||||||
|
|
||||||
def test_service_create_resource_check_mode():
|
def test_service_create_resource_check_mode():
|
||||||
@@ -289,8 +289,8 @@ def test_service_apply_existing_resource_warnings(
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert result == mock_pod_resource_instance.to_dict()
|
assert result == mock_pod_resource_instance.to_dict()
|
||||||
assert warnings[0] == "test warning 1"
|
assert str(warnings[0]) == "test warning 1"
|
||||||
assert warnings[1] == "test warning 2"
|
assert str(warnings[1]) == "test warning 2"
|
||||||
|
|
||||||
|
|
||||||
def test_service_replace_existing_resource(
|
def test_service_replace_existing_resource(
|
||||||
|
|||||||
Reference in New Issue
Block a user