mirror of
https://github.com/ansible-collections/kubernetes.core.git
synced 2026-05-12 12:32:05 +00:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6dadd06252 | ||
|
|
69dc7d5c5d | ||
|
|
2fa1c2c6e5 | ||
|
|
f2623dd3cf | ||
|
|
8772d8c997 | ||
|
|
a32108f64f | ||
|
|
365e5e9159 | ||
|
|
448a68da3d | ||
|
|
46acab9c4c | ||
|
|
fdb77182c8 | ||
|
|
fa3d94f793 | ||
|
|
9ec27cf37c | ||
|
|
10cb241256 | ||
|
|
92e1f581fe | ||
|
|
7f69aff0d6 | ||
|
|
8c65ac066d | ||
|
|
1d962fb932 | ||
|
|
27ce23aa72 | ||
|
|
993652b581 | ||
|
|
9bd9d22db3 | ||
|
|
0593426918 |
@@ -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]
|
||||||
|
|||||||
1
.github/workflows/integration-tests.yaml
vendored
1
.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
|
||||||
|
|||||||
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@v25.1.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,13 +4,51 @@ Kubernetes Collection Release Notes
|
|||||||
|
|
||||||
.. contents:: Topics
|
.. contents:: Topics
|
||||||
|
|
||||||
v6.0.0
|
v6.2.0
|
||||||
======
|
======
|
||||||
|
|
||||||
Release Summary
|
Release Summary
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
This major release removes the deprecated ``k8s`` inventory plugin and also removes ``ansible-core<2.16`` support.
|
This release adds minor changes and bugfixes, including support of skip-schema-validation in ``helm`` module and removing deprecated ``ansible.module_utils.six`` imports.
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- Add support of skip-schema-validation in ``helm`` module (https://github.com/ansible-collections/kubernetes.core/pull/995)
|
||||||
|
- kustomize - Add support of local environ (https://github.com/ansible-collections/kubernetes.core/pull/786).
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
v6.1.0
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This release adds ``plain_http`` and ``take_ownership`` parameters for helm modules, support for ``hidden_fields`` in ``k8s_json_patch``, documented lack of idempotency support in ``helm_registry_auth`` with ``helm ≥ 3.18.0``, and improved ``k8s_rollback`` test coverage.
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- Module helm_registry_auth do not support idempotency with `helm >= 3.18.0` (https://github.com/ansible-collections/kubernetes.core/pull/946)
|
||||||
|
- Module k8s_json_patch - Add support for `hidden_fields` (https://github.com/ansible-collections/kubernetes.core/pull/964).
|
||||||
|
- helm - Parameter plain_http added for working with insecure OCI registries (https://github.com/ansible-collections/kubernetes.core/pull/934).
|
||||||
|
- helm - Parameter take_ownership added (https://github.com/ansible-collections/kubernetes.core/pull/957).
|
||||||
|
- helm_pull - Parameter plain_http added for working with insecure OCI registries (https://github.com/ansible-collections/kubernetes.core/pull/934).
|
||||||
|
- helm_template - Parameter plain_http added for working with insecure OCI registries (https://github.com/ansible-collections/kubernetes.core/pull/934).
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- module_utils/k8s/service - hide fields first before creating diffs (https://github.com/ansible-collections/kubernetes.core/pull/915).
|
||||||
|
|
||||||
|
v6.0.0
|
||||||
|
======
|
||||||
|
|
||||||
Breaking Changes / Porting Guide
|
Breaking Changes / Porting Guide
|
||||||
--------------------------------
|
--------------------------------
|
||||||
@@ -18,6 +56,34 @@ Breaking Changes / Porting Guide
|
|||||||
- Remove deprecated ``k8s`` invetory plugin (https://github.com/ansible-collections/kubernetes.core/pull/867).
|
- Remove deprecated ``k8s`` invetory plugin (https://github.com/ansible-collections/kubernetes.core/pull/867).
|
||||||
- Remove support for ``ansible-core<2.16`` (https://github.com/ansible-collections/kubernetes.core/pull/867).
|
- Remove support for ``ansible-core<2.16`` (https://github.com/ansible-collections/kubernetes.core/pull/867).
|
||||||
|
|
||||||
|
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
|
v5.3.0
|
||||||
======
|
======
|
||||||
|
|
||||||
@@ -29,15 +95,15 @@ This release includes minor changes, bug fixes and also bumps ``ansible-lint`` v
|
|||||||
Minor Changes
|
Minor Changes
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
- kubernetes.core - Bump version of ``ansible-lint`` to ``25.1.2`` (https://github.com/ansible-collections/kubernetes.core/pull/919).
|
- Bump version of ``ansible-lint`` to 25.1.2 (https://github.com/ansible-collections/kubernetes.core/pull/919).
|
||||||
- action/k8s_info - update templating mechanism with changes from ``ansible-core 2.19`` (https://github.com/ansible-collections/kubernetes.core/pull/888).
|
- 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 ``reset_then_reuse_values`` support to helm module (https://github.com/ansible-collections/kubernetes.core/issues/803).
|
||||||
- helm - add support for ``insecure_skip_tls_verify`` option to helm and ``helm_repository`` (https://github.com/ansible-collections/kubernetes.core/issues/694).
|
- helm - add support for ``insecure_skip_tls_verify`` option to helm and helm_repository(https://github.com/ansible-collections/kubernetes.core/issues/694).
|
||||||
|
|
||||||
Bugfixes
|
Bugfixes
|
||||||
--------
|
--------
|
||||||
|
|
||||||
- module_utils/k8s/service - Fix issue when trying to delete resource using ``delete_options`` and ``check_mode=true`` (https://github.com/ansible-collections/kubernetes.core/issues/892).
|
- module_utils/k8s/service - fix issue when trying to delete resource using ``delete_options`` and ``check_mode=true`` (https://github.com/ansible-collections/kubernetes.core/issues/892).
|
||||||
|
|
||||||
v5.2.0
|
v5.2.0
|
||||||
======
|
======
|
||||||
@@ -65,7 +131,7 @@ This release came with new module ``helm_registry_auth``, improvements to the er
|
|||||||
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 (https://github.com/ansible-collections/kubernetes.core/pull/805).
|
- Parameter insecure_registry added to helm_template as equivalent of insecure-skip-tls-verify (https://github.com/ansible-collections/kubernetes.core/pull/805).
|
||||||
- k8s_drain - Improve error message for pod disruption budget when draining a node (https://github.com/ansible-collections/kubernetes.core/issues/797).
|
- k8s_drain - Improve error message for pod disruption budget when draining a node (https://github.com/ansible-collections/kubernetes.core/issues/797).
|
||||||
|
|
||||||
|
|||||||
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 = 6.0.0
|
VERSION = 6.2.0
|
||||||
|
|
||||||
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]))'`
|
||||||
|
|||||||
14
README.md
14
README.md
@@ -21,12 +21,10 @@ 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.16.0**.
|
This collection has been tested against the following Ansible versions: **>=2.16.0**.
|
||||||
|
|
||||||
For collections that support Ansible 2.9, please ensure you update your `network_os` to use the
|
|
||||||
fully qualified collection name (for example, `cisco.ios.ios`).
|
|
||||||
Plugins and modules within a collection may be tested with only specific Ansible versions.
|
Plugins and modules within a collection may be tested with only specific Ansible versions.
|
||||||
A collection may contain metadata that identifies these versions.
|
A collection may contain metadata that identifies these versions.
|
||||||
PEP440 is the schema used to describe the versions of Ansible.
|
PEP440 is the schema used to describe the versions of Ansible.
|
||||||
@@ -47,17 +45,17 @@ This collection supports Kubernetes versions >= 1.24.
|
|||||||
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
|
||||||
|
|
||||||
### 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
|
||||||
@@ -101,7 +99,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: 6.0.0
|
version: 6.2.0
|
||||||
```
|
```
|
||||||
|
|
||||||
### Installing the Kubernetes Python Library
|
### Installing the Kubernetes Python Library
|
||||||
|
|||||||
@@ -977,7 +977,7 @@ releases:
|
|||||||
- kustomize - kustomize plugin fails with deprecation warnings (https://github.com/ansible-collections/kubernetes.core/issues/639).
|
- 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
|
||||||
@@ -1044,6 +1044,33 @@ releases:
|
|||||||
- 898-k8s-dont-delete-in-check-mode.yaml
|
- 898-k8s-dont-delete-in-check-mode.yaml
|
||||||
- 919-update-ansible-lint-version.yaml
|
- 919-update-ansible-lint-version.yaml
|
||||||
release_date: '2025-05-16'
|
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'
|
||||||
6.0.0:
|
6.0.0:
|
||||||
changes:
|
changes:
|
||||||
breaking_changes:
|
breaking_changes:
|
||||||
@@ -1052,3 +1079,51 @@ releases:
|
|||||||
fragments:
|
fragments:
|
||||||
- 20250121-breaking-changes-6.0.0.yml
|
- 20250121-breaking-changes-6.0.0.yml
|
||||||
release_date: '2025-05-19'
|
release_date: '2025-05-19'
|
||||||
|
6.1.0:
|
||||||
|
changes:
|
||||||
|
bugfixes:
|
||||||
|
- module_utils/k8s/service - hide fields first before creating diffs (https://github.com/ansible-collections/kubernetes.core/pull/915).
|
||||||
|
minor_changes:
|
||||||
|
- Module helm_registry_auth do not support idempotency with `helm >= 3.18.0`
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/pull/946)
|
||||||
|
- Module k8s_json_patch - Add support for `hidden_fields` (https://github.com/ansible-collections/kubernetes.core/pull/964).
|
||||||
|
- helm - Parameter plain_http added for working with insecure OCI registries
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/pull/934).
|
||||||
|
- helm - Parameter take_ownership added (https://github.com/ansible-collections/kubernetes.core/pull/957).
|
||||||
|
- helm_pull - Parameter plain_http added for working with insecure OCI registries
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/pull/934).
|
||||||
|
- helm_template - Parameter plain_http added for working with insecure OCI registries
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/pull/934).
|
||||||
|
release_summary: "This release adds ``plain_http`` and ``take_ownership`` parameters
|
||||||
|
for helm modules, support for ``hidden_fields`` in ``k8s_json_patch``, documented
|
||||||
|
lack of idempotency support in ``helm_registry_auth`` with ``helm \u2265 3.18.0``,
|
||||||
|
and improved ``k8s_rollback`` test coverage."
|
||||||
|
fragments:
|
||||||
|
- 20250411-kubeconfig-no_log-revert.yaml
|
||||||
|
- 20250428-k8s-service-hide-fields-first.yaml
|
||||||
|
- 20250522-add-plain-http-for-oci-registries.yaml
|
||||||
|
- 20250605-fix-helm_registry_auth-integration_test.yaml
|
||||||
|
- 20250704-k8s-rollback-integration-test-coverage.yaml
|
||||||
|
- 20250720-k8s-patch-add-hidden-fields.yaml
|
||||||
|
- 20250911-add-support-helm-take-ownership.yaml
|
||||||
|
- release_summary.yml
|
||||||
|
release_date: '2025-08-12'
|
||||||
|
6.2.0:
|
||||||
|
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).
|
||||||
|
minor_changes:
|
||||||
|
- Add support of skip-schema-validation in ``helm`` module (https://github.com/ansible-collections/kubernetes.core/pull/995)
|
||||||
|
- kustomize - Add support of local environ (https://github.com/ansible-collections/kubernetes.core/pull/786).
|
||||||
|
release_summary: This release adds minor changes and bugfixes, including support
|
||||||
|
of skip-schema-validation in ``helm`` module and removing deprecated
|
||||||
|
``ansible.module_utils.six`` imports.
|
||||||
|
|
||||||
|
fragments:
|
||||||
|
- 20241030-support-of-evrion-for-kustomize-lookup-plugin.yaml
|
||||||
|
- 20250731-fix-k8s_cp-initcontainers.yaml
|
||||||
|
- 20250916-skip-schema-validation.yaml
|
||||||
|
- 20250922-remove-ansible-six-imports.yaml
|
||||||
|
- 6_2_0.yml
|
||||||
|
release_date: '2025-10-07'
|
||||||
|
|||||||
@@ -1,147 +0,0 @@
|
|||||||
.. _ansible_turbo_mode:
|
|
||||||
|
|
||||||
|
|
||||||
******************
|
|
||||||
Ansible Turbo mode
|
|
||||||
******************
|
|
||||||
|
|
||||||
Following document provides overview of Ansible Turbo mode in ``kubernetes.core`` collection.
|
|
||||||
|
|
||||||
.. contents::
|
|
||||||
:local:
|
|
||||||
:depth: 1
|
|
||||||
|
|
||||||
|
|
||||||
Synopsis
|
|
||||||
--------
|
|
||||||
- A brief introduction about Ansible Turbo mode in ``kuberentes.core`` collection.
|
|
||||||
- Ansible Turbo mode is an optional performance optimization. It can be enabled by installing the cloud.common collection and setting the ``ENABLE_TURBO_MODE`` environment variable.
|
|
||||||
|
|
||||||
Requirements
|
|
||||||
------------
|
|
||||||
|
|
||||||
The following requirement is needed on the host that executes this module.
|
|
||||||
|
|
||||||
- The ``cloud.common`` collection (https://github.com/ansible-collections/cloud.common)
|
|
||||||
|
|
||||||
You will also need to set the environment variable ``ENABLE_TURBO_MODE=1`` on the managed host. This can be done in the same ways you would usually do so, for example::
|
|
||||||
|
|
||||||
---
|
|
||||||
- hosts: remote
|
|
||||||
environment:
|
|
||||||
ENABLE_TURBO_MODE: 1
|
|
||||||
tasks:
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
Installation
|
|
||||||
------------
|
|
||||||
|
|
||||||
You can install ``cloud.common`` collection using following command::
|
|
||||||
|
|
||||||
# ansible-galaxy collection install cloud.common
|
|
||||||
|
|
||||||
|
|
||||||
Current situation without Ansible Turbo mode
|
|
||||||
============================================
|
|
||||||
|
|
||||||
The traditional execution flow of an Ansible module includes the following steps:
|
|
||||||
|
|
||||||
- Upload of a ZIP archive with the module and its dependencies
|
|
||||||
- Execution of the module
|
|
||||||
- Ansible collects the results once the script is finished
|
|
||||||
|
|
||||||
These steps happen for each task of a playbook, and on every host.
|
|
||||||
|
|
||||||
Most of the time, the execution of a module is fast enough for
|
|
||||||
the user. However, sometime the module requires significant amount of time,
|
|
||||||
just to initialize itself. This is a common situation with the API based modules.
|
|
||||||
|
|
||||||
A classic initialization involves the following steps:
|
|
||||||
|
|
||||||
- Load a Python library to access the remote resource (via SDK)
|
|
||||||
- Open a client
|
|
||||||
- Load a bunch of Python modules.
|
|
||||||
- Request a new TCP connection.
|
|
||||||
- Create a session.
|
|
||||||
- Authenticate the client.
|
|
||||||
|
|
||||||
All these steps are time consuming and the same operations will be running again and again.
|
|
||||||
|
|
||||||
For instance, here:
|
|
||||||
|
|
||||||
- ``import openstack``: takes 0.569s
|
|
||||||
- ``client = openstack.connect()``: takes 0.065s
|
|
||||||
- ``client.authorize()``: takes 1.360s,
|
|
||||||
|
|
||||||
These numbers are from test running against VexxHost public cloud.
|
|
||||||
|
|
||||||
In this case, it's a 2s-ish overhead per task. If the playbook
|
|
||||||
comes with 10 tasks, the execution time cannot go below 20s.
|
|
||||||
|
|
||||||
How Ansible Turbo Module improve the situation
|
|
||||||
==============================================
|
|
||||||
|
|
||||||
``AnsibleTurboModule`` is actually a class that inherites from
|
|
||||||
the standard ``AnsibleModule`` class that your modules probably
|
|
||||||
already use.
|
|
||||||
The big difference is that when a module starts, it also spawns
|
|
||||||
a little Python daemon. If a daemon already exists, it will just
|
|
||||||
reuse it.
|
|
||||||
All the module logic is run inside this Python daemon. This means:
|
|
||||||
|
|
||||||
- Python modules are actually loaded one time
|
|
||||||
- Ansible module can reuse an existing authenticated session.
|
|
||||||
|
|
||||||
The background service
|
|
||||||
======================
|
|
||||||
|
|
||||||
The daemon kills itself after 15s, and communication are done
|
|
||||||
through an Unix socket.
|
|
||||||
It runs in one single process and uses ``asyncio`` internally.
|
|
||||||
Consequently you can use the ``async`` keyword in your Ansible module.
|
|
||||||
This will be handy if you interact with a lot of remote systems
|
|
||||||
at the same time.
|
|
||||||
|
|
||||||
Security impact
|
|
||||||
===============
|
|
||||||
|
|
||||||
``ansible_module.turbo`` open an Unix socket to interact with the background service.
|
|
||||||
We use this service to open the connection toward the different target systems.
|
|
||||||
|
|
||||||
This is similar to what SSH does with the sockets.
|
|
||||||
|
|
||||||
Keep in mind that:
|
|
||||||
|
|
||||||
- All the modules can access the same cache. Soon an isolation will be done at the collection level (https://github.com/ansible-collections/cloud.common/pull/17)
|
|
||||||
- A task can load a different version of a library and impact the next tasks.
|
|
||||||
- If the same user runs two ``ansible-playbook`` at the same time, they will have access to the same cache.
|
|
||||||
|
|
||||||
When a module stores a session in a cache, it's a good idea to use a hash of the authentication information to identify the session.
|
|
||||||
|
|
||||||
Error management
|
|
||||||
================
|
|
||||||
|
|
||||||
``ansible_module.turbo`` uses exceptions to communicate a result back to the module.
|
|
||||||
|
|
||||||
- ``EmbeddedModuleFailure`` is raised when ``json_fail()`` is called.
|
|
||||||
- ``EmbeddedModuleSuccess`` is raised in case of success and returns the result to the origin module process.
|
|
||||||
|
|
||||||
These exceptions are defined in ``ansible_collections.cloud.common.plugins.module_utils.turbo.exceptions``.
|
|
||||||
You can raise ``EmbeddedModuleFailure`` exception yourself, for instance from a module in ``module_utils``.
|
|
||||||
|
|
||||||
.. note:: Be careful with the ``except Exception:`` blocks.
|
|
||||||
Not only they are bad practice, but also may interface with this
|
|
||||||
mechanism.
|
|
||||||
|
|
||||||
|
|
||||||
Troubleshooting
|
|
||||||
===============
|
|
||||||
|
|
||||||
You may want to manually start the server. This can be done with the following command:
|
|
||||||
|
|
||||||
.. code-block:: shell
|
|
||||||
|
|
||||||
PYTHONPATH=$HOME/.ansible/collections python -m ansible_collections.cloud.common.plugins.module_utils.turbo.server --socket-path $HOME/.ansible/tmp/turbo_mode.kubernetes.core.socket
|
|
||||||
|
|
||||||
You can use the ``--help`` argument to get a list of the optional parameters.
|
|
||||||
@@ -330,6 +330,27 @@ Parameters
|
|||||||
<div style="font-size: small; color: darkgreen"><br/>aliases: kubeconfig_path</div>
|
<div style="font-size: small; color: darkgreen"><br/>aliases: kubeconfig_path</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>plain_http</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.1.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>Use HTTP instead of HTTPS when working with OCI registries</div>
|
||||||
|
<div>Requires Helm >= 3.13.0</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -601,6 +622,48 @@ Parameters
|
|||||||
<div>Skip custom resource definitions when installing or upgrading.</div>
|
<div>Skip custom resource definitions when installing or upgrading.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>skip_schema_validation</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.2.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>Disables JSON schema validation for Chart and values.</div>
|
||||||
|
<div>This feature requires helm >= 3.16.0</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>take_ownership</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.1.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, Helm will ignore the check for helm annotations and take ownership of the existing resources</div>
|
||||||
|
<div>This feature requires helm >= 3.17.0</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -810,6 +873,12 @@ Examples
|
|||||||
chart_ref: "https://github.com/grafana/helm-charts/releases/download/grafana-5.6.0/grafana-5.6.0.tgz"
|
chart_ref: "https://github.com/grafana/helm-charts/releases/download/grafana-5.6.0/grafana-5.6.0.tgz"
|
||||||
release_namespace: monitoring
|
release_namespace: monitoring
|
||||||
|
|
||||||
|
- name: Deploy Bitnami's MongoDB latest chart from OCI registry
|
||||||
|
kubernetes.core.helm:
|
||||||
|
name: test
|
||||||
|
chart_ref: "oci://registry-1.docker.io/bitnamicharts/mongodb"
|
||||||
|
release_namespace: database
|
||||||
|
|
||||||
# Using complex Values
|
# Using complex Values
|
||||||
- name: Deploy new-relic client chart
|
- name: Deploy new-relic client chart
|
||||||
kubernetes.core.helm:
|
kubernetes.core.helm:
|
||||||
|
|||||||
@@ -193,6 +193,27 @@ Parameters
|
|||||||
<div>Pass credentials to all domains.</div>
|
<div>Pass credentials to all domains.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>plain_http</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.1.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>Use HTTP instead of HTTPS when working with OCI registries</div>
|
||||||
|
<div>Requires Helm >= 3.13.0</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="1">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -194,6 +194,27 @@ Parameters
|
|||||||
<div>If the directory already exists, it will be overwritten.</div>
|
<div>If the directory already exists, it will be overwritten.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>plain_http</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.1.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>Use HTTP instead of HTTPS when working with OCI registries</div>
|
||||||
|
<div>Requires Helm >= 3.13.0</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<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.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -140,6 +140,25 @@ Parameters
|
|||||||
<div>The name of a context found in the config file. Can also be specified via K8S_AUTH_CONTEXT environment variable.</div>
|
<div>The name of a context found in the config file. Can also be specified via K8S_AUTH_CONTEXT environment variable.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>hidden_fields</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.1.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<b>Default:</b><br/><div style="color: blue">[]</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>List of fields to hide from the diff output.</div>
|
||||||
|
<div>This is useful for fields that are not relevant to the patch operation, such as `metadata.managedFields`.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
|||||||
@@ -95,6 +95,26 @@ Parameters
|
|||||||
<div>Enable the helm chart inflation generator</div>
|
<div>Enable the helm chart inflation generator</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>environment</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">raw</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.2.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<b>Default:</b><br/><div style="color: blue">{}</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The environment variables to pass to the kustomize or kubectl command.</div>
|
||||||
|
<div>This can be a dictionary or a string in the format key=value, multiple pairs separated by space.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="1">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -145,6 +165,14 @@ Examples
|
|||||||
kubernetes.core.k8s:
|
kubernetes.core.k8s:
|
||||||
definition: "{{ lookup('kubernetes.core.kustomize', dir='/path/to/kustomization', enable_helm=True) }}"
|
definition: "{{ lookup('kubernetes.core.kustomize', dir='/path/to/kustomization', enable_helm=True) }}"
|
||||||
|
|
||||||
|
- name: Create kubernetes resources for lookup output with environment variables in string format
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
definition: "{{ lookup('kubernetes.core.kustomize', binary_path='/path/to/kubectl', environment='HTTP_PROXY=http://proxy.example.com:3128') }}"
|
||||||
|
|
||||||
|
- name: Create kubernetes resources for lookup output with environment variables in dict format
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
definition: "{{ lookup('kubernetes.core.kustomize', binary_path='/path/to/kubectl', environment={'HTTP_PROXY': 'http://proxy.example.com:3128'}) }}"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Return Values
|
Return Values
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ tags:
|
|||||||
- openshift
|
- openshift
|
||||||
- okd
|
- okd
|
||||||
- cluster
|
- cluster
|
||||||
version: 6.0.0
|
version: 6.2.0
|
||||||
build_ignore:
|
build_ignore:
|
||||||
- .DS_Store
|
- .DS_Store
|
||||||
- "*.tar.gz"
|
- "*.tar.gz"
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ from ansible.errors import (
|
|||||||
)
|
)
|
||||||
from ansible.module_utils._text import to_bytes, to_native, to_text
|
from ansible.module_utils._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:
|
try:
|
||||||
@@ -100,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):
|
||||||
@@ -120,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))
|
||||||
@@ -196,7 +195,7 @@ class ActionModule(ActionBase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
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:
|
||||||
@@ -246,7 +245,7 @@ class ActionModule(ActionBase):
|
|||||||
# add ansible 'template' vars
|
# add ansible 'template' vars
|
||||||
temp_vars = copy.deepcopy(task_vars)
|
temp_vars = copy.deepcopy(task_vars)
|
||||||
overrides = {}
|
overrides = {}
|
||||||
for key, value in iteritems(template_item):
|
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
|
overrides[key] = value
|
||||||
@@ -303,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
|
||||||
|
|||||||
@@ -34,6 +34,13 @@ DOCUMENTATION = """
|
|||||||
description:
|
description:
|
||||||
- Enable the helm chart inflation generator
|
- Enable the helm chart inflation generator
|
||||||
default: "False"
|
default: "False"
|
||||||
|
environment:
|
||||||
|
description:
|
||||||
|
- The environment variables to pass to the kustomize or kubectl command.
|
||||||
|
- This can be a dictionary or a string in the format key=value, multiple pairs separated by space.
|
||||||
|
type: raw
|
||||||
|
default: {}
|
||||||
|
version_added: 6.2.0
|
||||||
|
|
||||||
requirements:
|
requirements:
|
||||||
- "python >= 3.6"
|
- "python >= 3.6"
|
||||||
@@ -55,6 +62,14 @@ EXAMPLES = """
|
|||||||
- name: Create kubernetes resources for lookup output with `--enable-helm` set
|
- name: Create kubernetes resources for lookup output with `--enable-helm` set
|
||||||
kubernetes.core.k8s:
|
kubernetes.core.k8s:
|
||||||
definition: "{{ lookup('kubernetes.core.kustomize', dir='/path/to/kustomization', enable_helm=True) }}"
|
definition: "{{ lookup('kubernetes.core.kustomize', dir='/path/to/kustomization', enable_helm=True) }}"
|
||||||
|
|
||||||
|
- name: Create kubernetes resources for lookup output with environment variables in string format
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
definition: "{{ lookup('kubernetes.core.kustomize', binary_path='/path/to/kubectl', environment='HTTP_PROXY=http://proxy.example.com:3128') }}"
|
||||||
|
|
||||||
|
- name: Create kubernetes resources for lookup output with environment variables in dict format
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
definition: "{{ lookup('kubernetes.core.kustomize', binary_path='/path/to/kubectl', environment={'HTTP_PROXY': 'http://proxy.example.com:3128'}) }}"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
RETURN = """
|
RETURN = """
|
||||||
@@ -72,6 +87,7 @@ RETURN = """
|
|||||||
key1: val1
|
key1: val1
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from ansible.errors import AnsibleLookupError
|
from ansible.errors import AnsibleLookupError
|
||||||
@@ -92,8 +108,10 @@ def get_binary_from_path(name, opt_dirs=None):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def run_command(command):
|
def run_command(command, environ=None):
|
||||||
cmd = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
cmd = subprocess.Popen(
|
||||||
|
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=environ
|
||||||
|
)
|
||||||
stdout, stderr = cmd.communicate()
|
stdout, stderr = cmd.communicate()
|
||||||
return cmd.returncode, stdout, stderr
|
return cmd.returncode, stdout, stderr
|
||||||
|
|
||||||
@@ -107,6 +125,7 @@ class LookupModule(LookupBase):
|
|||||||
binary_path=None,
|
binary_path=None,
|
||||||
opt_dirs=None,
|
opt_dirs=None,
|
||||||
enable_helm=False,
|
enable_helm=False,
|
||||||
|
environment=None,
|
||||||
**kwargs
|
**kwargs
|
||||||
):
|
):
|
||||||
executable_path = binary_path
|
executable_path = binary_path
|
||||||
@@ -141,7 +160,21 @@ class LookupModule(LookupBase):
|
|||||||
if enable_helm:
|
if enable_helm:
|
||||||
command += ["--enable-helm"]
|
command += ["--enable-helm"]
|
||||||
|
|
||||||
(ret, out, err) = run_command(command)
|
environ = None
|
||||||
|
if environment:
|
||||||
|
environ = os.environ.copy()
|
||||||
|
if isinstance(environment, str):
|
||||||
|
if not all(env.count("=") == 1 for env in environment.split(" ")):
|
||||||
|
raise AnsibleLookupError(
|
||||||
|
"environment should be dict or string in the format key=value, multiple pairs separated by space"
|
||||||
|
)
|
||||||
|
for env in environment.split(" "):
|
||||||
|
key, value = env.split("=")
|
||||||
|
environ[key] = value
|
||||||
|
if isinstance(environment, dict):
|
||||||
|
environ.update(environment)
|
||||||
|
|
||||||
|
(ret, out, err) = run_command(command, environ=environ)
|
||||||
if ret != 0:
|
if ret != 0:
|
||||||
if err:
|
if err:
|
||||||
raise AnsibleLookupError(
|
raise AnsibleLookupError(
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -237,6 +237,27 @@ options:
|
|||||||
default: False
|
default: False
|
||||||
aliases: [ skip_tls_certs_check ]
|
aliases: [ skip_tls_certs_check ]
|
||||||
version_added: 5.3.0
|
version_added: 5.3.0
|
||||||
|
plain_http:
|
||||||
|
description:
|
||||||
|
- Use HTTP instead of HTTPS when working with OCI registries
|
||||||
|
- Requires Helm >= 3.13.0
|
||||||
|
type: bool
|
||||||
|
default: False
|
||||||
|
version_added: 6.1.0
|
||||||
|
take_ownership:
|
||||||
|
description:
|
||||||
|
- When upgrading, Helm will ignore the check for helm annotations and take ownership of the existing resources
|
||||||
|
- This feature requires helm >= 3.17.0
|
||||||
|
type: bool
|
||||||
|
default: False
|
||||||
|
version_added: 6.1.0
|
||||||
|
skip_schema_validation:
|
||||||
|
description:
|
||||||
|
- Disables JSON schema validation for Chart and values.
|
||||||
|
- This feature requires helm >= 3.16.0
|
||||||
|
type: bool
|
||||||
|
default: False
|
||||||
|
version_added: 6.2.0
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- kubernetes.core.helm_common_options
|
- kubernetes.core.helm_common_options
|
||||||
"""
|
"""
|
||||||
@@ -319,6 +340,12 @@ EXAMPLES = r"""
|
|||||||
chart_ref: "https://github.com/grafana/helm-charts/releases/download/grafana-5.6.0/grafana-5.6.0.tgz"
|
chart_ref: "https://github.com/grafana/helm-charts/releases/download/grafana-5.6.0/grafana-5.6.0.tgz"
|
||||||
release_namespace: monitoring
|
release_namespace: monitoring
|
||||||
|
|
||||||
|
- name: Deploy Bitnami's MongoDB latest chart from OCI registry
|
||||||
|
kubernetes.core.helm:
|
||||||
|
name: test
|
||||||
|
chart_ref: "oci://registry-1.docker.io/bitnamicharts/mongodb"
|
||||||
|
release_namespace: database
|
||||||
|
|
||||||
# Using complex Values
|
# Using complex Values
|
||||||
- name: Deploy new-relic client chart
|
- name: Deploy new-relic client chart
|
||||||
kubernetes.core.helm:
|
kubernetes.core.helm:
|
||||||
@@ -495,7 +522,9 @@ 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, insecure_skip_tls_verify=False):
|
def fetch_chart_info(
|
||||||
|
module, command, chart_ref, insecure_skip_tls_verify=False, plain_http=False
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
Get chart info
|
Get chart info
|
||||||
"""
|
"""
|
||||||
@@ -504,6 +533,17 @@ def fetch_chart_info(module, command, chart_ref, insecure_skip_tls_verify=False)
|
|||||||
if insecure_skip_tls_verify:
|
if insecure_skip_tls_verify:
|
||||||
inspect_command += " --insecure-skip-tls-verify"
|
inspect_command += " --insecure-skip-tls-verify"
|
||||||
|
|
||||||
|
if plain_http:
|
||||||
|
helm_version = module.get_helm_version()
|
||||||
|
if LooseVersion(helm_version) < LooseVersion("3.13.0"):
|
||||||
|
module.fail_json(
|
||||||
|
msg="plain_http requires helm >= 3.13.0, current version is {0}".format(
|
||||||
|
helm_version
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
inspect_command += " --plain-http"
|
||||||
|
|
||||||
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)
|
||||||
@@ -533,6 +573,9 @@ def deploy(
|
|||||||
reset_values=True,
|
reset_values=True,
|
||||||
reset_then_reuse_values=False,
|
reset_then_reuse_values=False,
|
||||||
insecure_skip_tls_verify=False,
|
insecure_skip_tls_verify=False,
|
||||||
|
plain_http=False,
|
||||||
|
take_ownership=False,
|
||||||
|
skip_schema_validation=False,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Install/upgrade/rollback release chart
|
Install/upgrade/rollback release chart
|
||||||
@@ -546,6 +589,8 @@ def deploy(
|
|||||||
deploy_command = command + " upgrade -i" # install/upgrade
|
deploy_command = command + " upgrade -i" # install/upgrade
|
||||||
if reset_values:
|
if reset_values:
|
||||||
deploy_command += " --reset-values"
|
deploy_command += " --reset-values"
|
||||||
|
if take_ownership:
|
||||||
|
deploy_command += " --take-ownership"
|
||||||
|
|
||||||
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)
|
||||||
@@ -595,6 +640,9 @@ def deploy(
|
|||||||
else:
|
else:
|
||||||
deploy_command += " --insecure-skip-tls-verify"
|
deploy_command += " --insecure-skip-tls-verify"
|
||||||
|
|
||||||
|
if plain_http:
|
||||||
|
deploy_command += " --plain-http"
|
||||||
|
|
||||||
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
|
||||||
@@ -618,6 +666,17 @@ def deploy(
|
|||||||
if set_value_args:
|
if set_value_args:
|
||||||
deploy_command += " " + set_value_args
|
deploy_command += " " + set_value_args
|
||||||
|
|
||||||
|
if skip_schema_validation:
|
||||||
|
helm_version = module.get_helm_version()
|
||||||
|
if LooseVersion(helm_version) < LooseVersion("3.16.0"):
|
||||||
|
module.fail_json(
|
||||||
|
msg="skip_schema_validation requires helm >= 3.16.0, current version is {0}".format(
|
||||||
|
helm_version
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
deploy_command += " --skip-schema-validation"
|
||||||
|
|
||||||
deploy_command += " " + release_name + f" '{chart_name}'"
|
deploy_command += " " + release_name + f" '{chart_name}'"
|
||||||
return deploy_command
|
return deploy_command
|
||||||
|
|
||||||
@@ -690,6 +749,8 @@ def helmdiff_check(
|
|||||||
reset_values=True,
|
reset_values=True,
|
||||||
reset_then_reuse_values=False,
|
reset_then_reuse_values=False,
|
||||||
insecure_skip_tls_verify=False,
|
insecure_skip_tls_verify=False,
|
||||||
|
plain_http=False,
|
||||||
|
skip_schema_validation=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.
|
||||||
@@ -745,6 +806,28 @@ def helmdiff_check(
|
|||||||
if insecure_skip_tls_verify:
|
if insecure_skip_tls_verify:
|
||||||
cmd += " --insecure-skip-tls-verify"
|
cmd += " --insecure-skip-tls-verify"
|
||||||
|
|
||||||
|
if skip_schema_validation:
|
||||||
|
helm_version = module.get_helm_version()
|
||||||
|
if LooseVersion(helm_version) < LooseVersion("3.16.0"):
|
||||||
|
module.fail_json(
|
||||||
|
msg="skip_schema_validation requires helm >= 3.16.0, current version is {0}".format(
|
||||||
|
helm_version
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
cmd += " --skip-schema-validation"
|
||||||
|
|
||||||
|
if plain_http:
|
||||||
|
helm_version = module.get_helm_version()
|
||||||
|
if LooseVersion(helm_version) < LooseVersion("3.13.0"):
|
||||||
|
module.fail_json(
|
||||||
|
msg="plain_http requires helm >= 3.13.0, current version is {0}".format(
|
||||||
|
helm_version
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
cmd += " --plain-http"
|
||||||
|
|
||||||
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())
|
||||||
|
|
||||||
@@ -808,6 +891,9 @@ def argument_spec():
|
|||||||
insecure_skip_tls_verify=dict(
|
insecure_skip_tls_verify=dict(
|
||||||
type="bool", default=False, aliases=["skip_tls_certs_check"]
|
type="bool", default=False, aliases=["skip_tls_certs_check"]
|
||||||
),
|
),
|
||||||
|
plain_http=dict(type="bool", default=False),
|
||||||
|
take_ownership=dict(type="bool", default=False),
|
||||||
|
skip_schema_validation=dict(type="bool", default=False),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return arg_spec
|
return arg_spec
|
||||||
@@ -862,6 +948,9 @@ def main():
|
|||||||
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")
|
reset_then_reuse_values = module.params.get("reset_then_reuse_values")
|
||||||
insecure_skip_tls_verify = module.params.get("insecure_skip_tls_verify")
|
insecure_skip_tls_verify = module.params.get("insecure_skip_tls_verify")
|
||||||
|
plain_http = module.params.get("plain_http")
|
||||||
|
take_ownership = module.params.get("take_ownership")
|
||||||
|
skip_schema_validation = module.params.get("skip_schema_validation")
|
||||||
|
|
||||||
if update_repo_cache:
|
if update_repo_cache:
|
||||||
run_repo_update(module)
|
run_repo_update(module)
|
||||||
@@ -871,6 +960,33 @@ def main():
|
|||||||
release_status = get_release_status(module, release_name, all_status=all_status)
|
release_status = get_release_status(module, release_name, all_status=all_status)
|
||||||
|
|
||||||
helm_cmd = module.get_helm_binary()
|
helm_cmd = module.get_helm_binary()
|
||||||
|
|
||||||
|
if plain_http:
|
||||||
|
helm_version = module.get_helm_version()
|
||||||
|
if LooseVersion(helm_version) < LooseVersion("3.13.0"):
|
||||||
|
module.fail_json(
|
||||||
|
msg="plain_http requires helm >= 3.13.0, current version is {0}".format(
|
||||||
|
helm_version
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if take_ownership:
|
||||||
|
helm_version = module.get_helm_version()
|
||||||
|
if LooseVersion(helm_version) < LooseVersion("3.17.0"):
|
||||||
|
module.fail_json(
|
||||||
|
msg="take_ownership requires helm >= 3.17.0, current version is {0}".format(
|
||||||
|
helm_version
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if skip_schema_validation:
|
||||||
|
helm_version = module.get_helm_version()
|
||||||
|
if LooseVersion(helm_version) < LooseVersion("3.16.0"):
|
||||||
|
module.fail_json(
|
||||||
|
msg="skip_schema_validation requires helm >= 3.16.0, current version is {0}".format(
|
||||||
|
helm_version
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
opt_result = {}
|
opt_result = {}
|
||||||
if release_state == "absent" and release_status is not None:
|
if release_state == "absent" and release_status is not None:
|
||||||
# skip release statuses 'uninstalled' and 'uninstalling'
|
# skip release statuses 'uninstalled' and 'uninstalling'
|
||||||
@@ -900,7 +1016,7 @@ def main():
|
|||||||
|
|
||||||
# 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(
|
chart_info = fetch_chart_info(
|
||||||
module, helm_cmd, chart_ref, insecure_skip_tls_verify
|
module, helm_cmd, chart_ref, insecure_skip_tls_verify, plain_http
|
||||||
)
|
)
|
||||||
|
|
||||||
if dependency_update:
|
if dependency_update:
|
||||||
@@ -962,6 +1078,8 @@ def main():
|
|||||||
reset_values=reset_values,
|
reset_values=reset_values,
|
||||||
reset_then_reuse_values=reset_then_reuse_values,
|
reset_then_reuse_values=reset_then_reuse_values,
|
||||||
insecure_skip_tls_verify=insecure_skip_tls_verify,
|
insecure_skip_tls_verify=insecure_skip_tls_verify,
|
||||||
|
plain_http=plain_http,
|
||||||
|
skip_schema_validation=skip_schema_validation,
|
||||||
)
|
)
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
@@ -989,6 +1107,8 @@ def main():
|
|||||||
reset_values=reset_values,
|
reset_values=reset_values,
|
||||||
reset_then_reuse_values=reset_then_reuse_values,
|
reset_then_reuse_values=reset_then_reuse_values,
|
||||||
insecure_skip_tls_verify=insecure_skip_tls_verify,
|
insecure_skip_tls_verify=insecure_skip_tls_verify,
|
||||||
|
plain_http=plain_http,
|
||||||
|
skip_schema_validation=skip_schema_validation,
|
||||||
)
|
)
|
||||||
if would_change and module._diff:
|
if would_change and module._diff:
|
||||||
opt_result["diff"] = {"prepared": prepared}
|
opt_result["diff"] = {"prepared": prepared}
|
||||||
@@ -1026,6 +1146,9 @@ def main():
|
|||||||
reset_values=reset_values,
|
reset_values=reset_values,
|
||||||
reset_then_reuse_values=reset_then_reuse_values,
|
reset_then_reuse_values=reset_then_reuse_values,
|
||||||
insecure_skip_tls_verify=insecure_skip_tls_verify,
|
insecure_skip_tls_verify=insecure_skip_tls_verify,
|
||||||
|
plain_http=plain_http,
|
||||||
|
take_ownership=take_ownership,
|
||||||
|
skip_schema_validation=skip_schema_validation,
|
||||||
)
|
)
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
|
|||||||
@@ -114,6 +114,13 @@ options:
|
|||||||
- The path of a helm binary to use.
|
- The path of a helm binary to use.
|
||||||
required: false
|
required: false
|
||||||
type: path
|
type: path
|
||||||
|
plain_http:
|
||||||
|
description:
|
||||||
|
- Use HTTP instead of HTTPS when working with OCI registries
|
||||||
|
- Requires Helm >= 3.13.0
|
||||||
|
type: bool
|
||||||
|
default: False
|
||||||
|
version_added: 6.1.0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
EXAMPLES = r"""
|
EXAMPLES = r"""
|
||||||
@@ -201,6 +208,7 @@ def main():
|
|||||||
chart_ssl_cert_file=dict(type="path"),
|
chart_ssl_cert_file=dict(type="path"),
|
||||||
chart_ssl_key_file=dict(type="path"),
|
chart_ssl_key_file=dict(type="path"),
|
||||||
binary_path=dict(type="path"),
|
binary_path=dict(type="path"),
|
||||||
|
plain_http=dict(type="bool", default=False),
|
||||||
)
|
)
|
||||||
module = AnsibleHelmModule(
|
module = AnsibleHelmModule(
|
||||||
argument_spec=argspec,
|
argument_spec=argspec,
|
||||||
@@ -225,6 +233,7 @@ def main():
|
|||||||
chart_ca_cert="3.1.0",
|
chart_ca_cert="3.1.0",
|
||||||
chart_ssl_cert_file="3.1.0",
|
chart_ssl_cert_file="3.1.0",
|
||||||
chart_ssl_key_file="3.1.0",
|
chart_ssl_key_file="3.1.0",
|
||||||
|
plain_http="3.13.0",
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_version_requirement(opt):
|
def test_version_requirement(opt):
|
||||||
@@ -264,6 +273,7 @@ def main():
|
|||||||
skip_tls_certs_check=dict(key="insecure-skip-tls-verify"),
|
skip_tls_certs_check=dict(key="insecure-skip-tls-verify"),
|
||||||
chart_devel=dict(key="devel"),
|
chart_devel=dict(key="devel"),
|
||||||
untar_chart=dict(key="untar"),
|
untar_chart=dict(key="untar"),
|
||||||
|
plain_http=dict(key="plain-http"),
|
||||||
)
|
)
|
||||||
|
|
||||||
for k, v in helm_flag_args.items():
|
for k, v in helm_flag_args.items():
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -147,6 +147,13 @@ options:
|
|||||||
- json
|
- json
|
||||||
- file
|
- file
|
||||||
version_added: 2.4.0
|
version_added: 2.4.0
|
||||||
|
plain_http:
|
||||||
|
description:
|
||||||
|
- Use HTTP instead of HTTPS when working with OCI registries
|
||||||
|
- Requires Helm >= 3.13.0
|
||||||
|
type: bool
|
||||||
|
default: False
|
||||||
|
version_added: 6.1.0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
EXAMPLES = r"""
|
EXAMPLES = r"""
|
||||||
@@ -218,6 +225,9 @@ from ansible.module_utils.basic import missing_required_lib
|
|||||||
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 template(
|
def template(
|
||||||
@@ -236,6 +246,7 @@ def template(
|
|||||||
values_files=None,
|
values_files=None,
|
||||||
include_crds=False,
|
include_crds=False,
|
||||||
set_values=None,
|
set_values=None,
|
||||||
|
plain_http=False,
|
||||||
):
|
):
|
||||||
cmd += " template "
|
cmd += " template "
|
||||||
|
|
||||||
@@ -262,6 +273,9 @@ def template(
|
|||||||
if insecure_registry:
|
if insecure_registry:
|
||||||
cmd += " --insecure-skip-tls-verify"
|
cmd += " --insecure-skip-tls-verify"
|
||||||
|
|
||||||
|
if plain_http:
|
||||||
|
cmd += " --plain-http"
|
||||||
|
|
||||||
if show_only:
|
if show_only:
|
||||||
for template in show_only:
|
for template in show_only:
|
||||||
cmd += " -s " + template
|
cmd += " -s " + template
|
||||||
@@ -307,6 +321,7 @@ def main():
|
|||||||
values_files=dict(type="list", default=[], elements="str"),
|
values_files=dict(type="list", default=[], elements="str"),
|
||||||
update_repo_cache=dict(type="bool", default=False),
|
update_repo_cache=dict(type="bool", default=False),
|
||||||
set_values=dict(type="list", elements="dict"),
|
set_values=dict(type="list", elements="dict"),
|
||||||
|
plain_http=dict(type="bool", default=False),
|
||||||
),
|
),
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
)
|
)
|
||||||
@@ -327,12 +342,22 @@ def main():
|
|||||||
values_files = module.params.get("values_files")
|
values_files = module.params.get("values_files")
|
||||||
update_repo_cache = module.params.get("update_repo_cache")
|
update_repo_cache = module.params.get("update_repo_cache")
|
||||||
set_values = module.params.get("set_values")
|
set_values = module.params.get("set_values")
|
||||||
|
plain_http = module.params.get("plain_http")
|
||||||
|
|
||||||
if not IMP_YAML:
|
if not IMP_YAML:
|
||||||
module.fail_json(msg=missing_required_lib("yaml"), exception=IMP_YAML_ERR)
|
module.fail_json(msg=missing_required_lib("yaml"), exception=IMP_YAML_ERR)
|
||||||
|
|
||||||
helm_cmd = module.get_helm_binary()
|
helm_cmd = module.get_helm_binary()
|
||||||
|
|
||||||
|
if plain_http:
|
||||||
|
helm_version = module.get_helm_version()
|
||||||
|
if LooseVersion(helm_version) < LooseVersion("3.13.0"):
|
||||||
|
module.fail_json(
|
||||||
|
msg="plain_http requires helm >= 3.13.0, current version is {0}".format(
|
||||||
|
helm_version
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if update_repo_cache:
|
if update_repo_cache:
|
||||||
update_cmd = helm_cmd + " repo update"
|
update_cmd = helm_cmd + " repo update"
|
||||||
module.run_helm_command(update_cmd)
|
module.run_helm_command(update_cmd)
|
||||||
@@ -357,6 +382,7 @@ def main():
|
|||||||
values_files=values_files,
|
values_files=values_files,
|
||||||
include_crds=include_crds,
|
include_crds=include_crds,
|
||||||
set_values=set_values_args,
|
set_values=set_values_args,
|
||||||
|
plain_http=plain_http,
|
||||||
)
|
)
|
||||||
|
|
||||||
if not check_mode:
|
if not check_mode:
|
||||||
|
|||||||
@@ -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"""
|
||||||
|
|||||||
@@ -33,6 +33,14 @@ options:
|
|||||||
aliases:
|
aliases:
|
||||||
- api
|
- api
|
||||||
- version
|
- version
|
||||||
|
hidden_fields:
|
||||||
|
description:
|
||||||
|
- List of fields to hide from the diff output.
|
||||||
|
- This is useful for fields that are not relevant to the patch operation, such as `metadata.managedFields`.
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
default: []
|
||||||
|
version_added: 6.1.0
|
||||||
kind:
|
kind:
|
||||||
description:
|
description:
|
||||||
- Use to specify an object model.
|
- Use to specify an object model.
|
||||||
@@ -147,6 +155,7 @@ from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions imp
|
|||||||
)
|
)
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.service import (
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.service import (
|
||||||
diff_objects,
|
diff_objects,
|
||||||
|
hide_fields,
|
||||||
)
|
)
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.waiter import (
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.waiter import (
|
||||||
get_waiter,
|
get_waiter,
|
||||||
@@ -174,6 +183,7 @@ JSON_PATCH_ARGS = {
|
|||||||
"namespace": {"type": "str"},
|
"namespace": {"type": "str"},
|
||||||
"name": {"type": "str", "required": True},
|
"name": {"type": "str", "required": True},
|
||||||
"patch": {"type": "list", "required": True, "elements": "dict"},
|
"patch": {"type": "list", "required": True, "elements": "dict"},
|
||||||
|
"hidden_fields": {"type": "list", "elements": "str", "default": []},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -203,6 +213,7 @@ def execute_module(module, client):
|
|||||||
namespace = module.params.get("namespace")
|
namespace = module.params.get("namespace")
|
||||||
patch = module.params.get("patch")
|
patch = module.params.get("patch")
|
||||||
|
|
||||||
|
hidden_fields = module.params.get("hidden_fields")
|
||||||
wait = module.params.get("wait")
|
wait = module.params.get("wait")
|
||||||
wait_sleep = module.params.get("wait_sleep")
|
wait_sleep = module.params.get("wait_sleep")
|
||||||
wait_timeout = module.params.get("wait_timeout")
|
wait_timeout = module.params.get("wait_timeout")
|
||||||
@@ -260,13 +271,13 @@ def execute_module(module, client):
|
|||||||
module.fail_json(msg=msg, error=to_native(exc), status="", reason="")
|
module.fail_json(msg=msg, error=to_native(exc), status="", reason="")
|
||||||
|
|
||||||
success = True
|
success = True
|
||||||
result = {"result": obj}
|
result = {"result": hide_fields(obj, hidden_fields)}
|
||||||
if wait and not module.check_mode:
|
if wait and not module.check_mode:
|
||||||
waiter = get_waiter(client, resource, condition=wait_condition)
|
waiter = get_waiter(client, resource, condition=wait_condition)
|
||||||
success, result["result"], result["duration"] = waiter.wait(
|
success, result["result"], result["duration"] = waiter.wait(
|
||||||
wait_timeout, wait_sleep, name, namespace
|
wait_timeout, wait_sleep, name, namespace
|
||||||
)
|
)
|
||||||
match, diffs = diff_objects(existing.to_dict(), obj)
|
match, diffs = diff_objects(existing.to_dict(), obj, hidden_fields)
|
||||||
result["changed"] = not match
|
result["changed"] = not match
|
||||||
if module._diff:
|
if module._diff:
|
||||||
result["diff"] = diffs
|
result["diff"] = diffs
|
||||||
|
|||||||
@@ -29,3 +29,5 @@ test_namespace:
|
|||||||
- "helm-chart-with-space-into-name"
|
- "helm-chart-with-space-into-name"
|
||||||
- "helm-reset-then-reuse-values"
|
- "helm-reset-then-reuse-values"
|
||||||
- "helm-insecure"
|
- "helm-insecure"
|
||||||
|
- "helm-test-take-ownership"
|
||||||
|
- "helm-skip-schema-validation"
|
||||||
|
|||||||
@@ -6,3 +6,4 @@
|
|||||||
with_items:
|
with_items:
|
||||||
- "v3.15.4"
|
- "v3.15.4"
|
||||||
- "v3.16.0"
|
- "v3.16.0"
|
||||||
|
- "v3.17.0"
|
||||||
|
|||||||
@@ -47,6 +47,12 @@
|
|||||||
- name: Test insecure registry flag feature
|
- name: Test insecure registry flag feature
|
||||||
include_tasks: test_helm_insecure.yml
|
include_tasks: test_helm_insecure.yml
|
||||||
|
|
||||||
|
- name: Test take ownership flag feature
|
||||||
|
include_tasks: test_helm_take_ownership.yml
|
||||||
|
|
||||||
|
- name: Test helm skip_schema_validation
|
||||||
|
include_tasks: test_skip_schema_validation.yml
|
||||||
|
|
||||||
- name: Clean helm install
|
- name: Clean helm install
|
||||||
file:
|
file:
|
||||||
path: "{{ item }}"
|
path: "{{ item }}"
|
||||||
|
|||||||
@@ -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,81 @@
|
|||||||
|
---
|
||||||
|
- name: Test helm take ownership
|
||||||
|
vars:
|
||||||
|
helm_namespace: "{{ test_namespace[13] }}"
|
||||||
|
block:
|
||||||
|
|
||||||
|
- name: Initial chart installation (no flag set)
|
||||||
|
helm:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
chart_ref: "{{ chart_test_oci }}"
|
||||||
|
release_name: test-take-ownership
|
||||||
|
release_namespace: "{{ helm_namespace }}"
|
||||||
|
create_namespace: true
|
||||||
|
register: install
|
||||||
|
|
||||||
|
- name: Validate that take-ownership flag is not set
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- install is changed
|
||||||
|
- '"--take-ownership" not in install.command'
|
||||||
|
|
||||||
|
- name: Upgrade chart (take-onwership flag set)
|
||||||
|
helm:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
chart_ref: "{{ chart_test_oci }}"
|
||||||
|
release_name: test-take-ownership
|
||||||
|
release_namespace: "{{ helm_namespace }}"
|
||||||
|
take_ownership: true
|
||||||
|
values:
|
||||||
|
commonLabels:
|
||||||
|
take-onwership: "set"
|
||||||
|
register: upgrade
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Validate that take-ownership flag IS set if helm version is >= 3.17.0
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- upgrade is changed
|
||||||
|
- '"--take-ownership" in upgrade.command'
|
||||||
|
when: '"v3.17.0" <= helm_version'
|
||||||
|
|
||||||
|
- name: Validate that feature fails for helm < 3.17.0
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- upgrade is failed
|
||||||
|
- '"take_ownership requires helm >= 3.17.0" in upgrade.msg'
|
||||||
|
when: 'helm_version < "v3.17.0"'
|
||||||
|
|
||||||
|
- name: Upgrade chart (take-onwership flag not set)
|
||||||
|
helm:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
chart_ref: "{{ chart_test_oci }}"
|
||||||
|
release_name: test-take-ownership
|
||||||
|
release_namespace: "{{ helm_namespace }}"
|
||||||
|
values:
|
||||||
|
commonLabels:
|
||||||
|
take-onwership: "not-set"
|
||||||
|
register: upgrade
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Validate that take-ownership flag IS set if helm version is >= 3.17.0
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- upgrade is changed
|
||||||
|
- '"--take-ownership" not in upgrade.command'
|
||||||
|
when: '"v3.17.0" <= helm_version'
|
||||||
|
|
||||||
|
- name: Validate that feature fails for helm < 3.17.0
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- upgrade is changed
|
||||||
|
- upgrade.msg is not defined
|
||||||
|
when: 'helm_version < "v3.17.0"'
|
||||||
|
|
||||||
|
always:
|
||||||
|
- name: Remove helm namespace
|
||||||
|
k8s:
|
||||||
|
api_version: v1
|
||||||
|
kind: Namespace
|
||||||
|
name: "{{ helm_namespace }}"
|
||||||
|
state: absent
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
- name: Test helm skip_schema_validation
|
||||||
|
vars:
|
||||||
|
helm_namespace: "{{ test_namespace[14] }}"
|
||||||
|
chart_release_values:
|
||||||
|
replica:
|
||||||
|
replicaCount: 3
|
||||||
|
master:
|
||||||
|
count: 1
|
||||||
|
kind: Deployment
|
||||||
|
block:
|
||||||
|
- name: 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 }}"
|
||||||
|
skip_schema_validation: true
|
||||||
|
register: install
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Debug install result
|
||||||
|
debug:
|
||||||
|
var: install
|
||||||
|
|
||||||
|
- name: Validate skip_schema_validation with helm >= 3.16.0 works
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- install is changed
|
||||||
|
- "'--skip-schema-validation' in install.command"
|
||||||
|
when: "helm_version is ansible.builtin.version('v3.16.0', '>=')"
|
||||||
|
|
||||||
|
- name: Validate skip_schema_validation with helm < 3.16.0 fails
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- install is failed
|
||||||
|
- "'skip_schema_validation requires helm >= 3.16.0' in install.msg"
|
||||||
|
when: "helm_version is ansible.builtin.version('v3.16.0', '<')"
|
||||||
|
|
||||||
|
always:
|
||||||
|
- name: Remove helm namespace
|
||||||
|
k8s:
|
||||||
|
api_version: v1
|
||||||
|
kind: Namespace
|
||||||
|
name: "{{ helm_namespace }}"
|
||||||
|
state: absent
|
||||||
3
tests/integration/targets/helm_plain_http/aliases
Normal file
3
tests/integration/targets/helm_plain_http/aliases
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
helm_template
|
||||||
|
helm_pull
|
||||||
|
helm
|
||||||
3
tests/integration/targets/helm_plain_http/inventory.ini
Normal file
3
tests/integration/targets/helm_plain_http/inventory.ini
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[all]
|
||||||
|
helm-3.12.3 helm_version=v3.12.3 test_namespace=helm-plain-http-v3-12-3 tests_should_failed=true
|
||||||
|
helm-3.18.2 helm_version=v3.18.2 test_namespace=helm-plain-http-v3-18-2 tests_should_failed=false
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
- name: Run test for helm plain http option
|
||||||
|
hosts: all
|
||||||
|
gather_facts: true
|
||||||
|
|
||||||
|
vars:
|
||||||
|
ansible_connection: local
|
||||||
|
ansible_python_interpreter: "{{ ansible_playbook_python }}"
|
||||||
|
chart_test_oci: "oci://registry-1.docker.io/bitnamicharts/redis"
|
||||||
|
|
||||||
|
roles:
|
||||||
|
- setup_namespace
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- ansible.builtin.include_tasks: tasks/test.yaml
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
---
|
||||||
|
- name: Run test for helm
|
||||||
|
block:
|
||||||
|
- name: Create temporary directory to install chart In
|
||||||
|
ansible.builtin.tempfile:
|
||||||
|
state: directory
|
||||||
|
suffix: .helm
|
||||||
|
register: install_path
|
||||||
|
|
||||||
|
- name: Install required helm version
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: install_helm
|
||||||
|
vars:
|
||||||
|
helm_install_path: "{{ install_path.path }}"
|
||||||
|
|
||||||
|
- name: Set helm binary path
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
helm_binary: "{{ install_path.path }}/{{ ansible_system | lower }}-amd64/helm"
|
||||||
|
|
||||||
|
# helm
|
||||||
|
- name: Run helm with plain_http
|
||||||
|
kubernetes.core.helm:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
chart_ref: "{{ chart_test_oci }}"
|
||||||
|
release_name: test-secure
|
||||||
|
release_namespace: "{{ test_namespace }}"
|
||||||
|
create_namespace: true
|
||||||
|
plain_http: true
|
||||||
|
register: install_chart
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Ensure module failed as expected
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- install_chart is failed
|
||||||
|
- '"plain_http requires helm >= 3.13.0" in install_chart.msg'
|
||||||
|
when: tests_should_failed | bool
|
||||||
|
|
||||||
|
- name: Ensure the result command contains the expected option
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- install_chart is not failed
|
||||||
|
- '"--plain-http" in install_chart.command'
|
||||||
|
when: not (tests_should_failed | bool)
|
||||||
|
|
||||||
|
# helm_pull
|
||||||
|
- name: Trying to download helm chart with option plain_http
|
||||||
|
kubernetes.core.helm_pull:
|
||||||
|
chart_ref: "{{ chart_test_oci }}"
|
||||||
|
destination: "{{ playbook_dir }}"
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
plain_http: true
|
||||||
|
register: pull_chart
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Ensure module failed as expected
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- pull_chart is failed
|
||||||
|
- '"plain_http requires helm >= 3.13.0" in pull_chart.msg'
|
||||||
|
when: tests_should_failed | bool
|
||||||
|
|
||||||
|
- name: Ensure the result command contains the expected option
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- pull_chart is not failed
|
||||||
|
- '"--plain-http" in pull_chart.command'
|
||||||
|
when: not (tests_should_failed | bool)
|
||||||
|
|
||||||
|
# helm_template
|
||||||
|
- name: Test helm render template
|
||||||
|
kubernetes.core.helm_template:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
chart_ref: "{{ chart_test_oci }}"
|
||||||
|
output_dir: "{{ playbook_dir }}"
|
||||||
|
plain_http: true
|
||||||
|
register: template
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Ensure module failed as expected
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- template is failed
|
||||||
|
- '"plain_http requires helm >= 3.13.0" in template.msg'
|
||||||
|
when: tests_should_failed | bool
|
||||||
|
|
||||||
|
- name: Ensure the result command contains the expected option
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- template is not failed
|
||||||
|
- '"--plain-http" in template.command'
|
||||||
|
when: not (tests_should_failed | bool)
|
||||||
|
|
||||||
|
always:
|
||||||
|
- name: Delete temporary file
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ install_path.path }}"
|
||||||
|
state: absent
|
||||||
|
ignore_errors: true
|
||||||
4
tests/integration/targets/helm_plain_http/runme.sh
Executable file
4
tests/integration/targets/helm_plain_http/runme.sh
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -eux
|
||||||
|
export ANSIBLE_ROLES_PATH=../
|
||||||
|
ansible-playbook playbooks/play.yaml -i inventory.ini "$@"
|
||||||
@@ -108,15 +108,19 @@
|
|||||||
assert:
|
assert:
|
||||||
that: "'Removing login credentials' in _helm_registry_auth_logout.stderr"
|
that: "'Removing login credentials' in _helm_registry_auth_logout.stderr"
|
||||||
|
|
||||||
- name: Test logout idempotency
|
- name: Test idempotency of logout with helm < 3.18.0
|
||||||
helm_registry_auth:
|
when: _helm_version.stdout is ansible.builtin.version('v3.18.0', '<')
|
||||||
host: localhost:{{ registry_port }}
|
block:
|
||||||
state: absent
|
|
||||||
register: _helm_registry_auth_logout_idempotency
|
|
||||||
|
|
||||||
- name: Assert logout operation did not report change
|
- name: Test logout idempotency
|
||||||
ansible.builtin.assert:
|
helm_registry_auth:
|
||||||
that: _helm_registry_auth_logout_idempotency is not changed
|
host: localhost:{{ registry_port }}
|
||||||
|
state: absent
|
||||||
|
register: _helm_registry_auth_logout_idempotency
|
||||||
|
|
||||||
|
- name: Assert logout operation did not report change
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that: _helm_registry_auth_logout_idempotency is not changed
|
||||||
|
|
||||||
- name: Ensure that not able to push to the registry
|
- name: Ensure that not able to push to the registry
|
||||||
ansible.builtin.shell: >-
|
ansible.builtin.shell: >-
|
||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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:
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
k8s_json_patch
|
||||||
|
k8s
|
||||||
|
time=33
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
---
|
||||||
|
test_namespace: "k8s-hide-fields"
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
dependencies:
|
||||||
|
- setup_namespace
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
- connection: local
|
||||||
|
gather_facts: false
|
||||||
|
hosts: localhost
|
||||||
|
roles:
|
||||||
|
- k8s_json_patch_hide_fields
|
||||||
5
tests/integration/targets/k8s_json_patch_hide_fields/runme.sh
Executable file
5
tests/integration/targets/k8s_json_patch_hide_fields/runme.sh
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -eux
|
||||||
|
export ANSIBLE_CALLBACKS_ENABLED=profile_tasks
|
||||||
|
export ANSIBLE_ROLES_PATH=../
|
||||||
|
ansible-playbook playbook.yaml "$@"
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
- vars:
|
||||||
|
pod: json-patch
|
||||||
|
k8s_wait_timeout: 400
|
||||||
|
|
||||||
|
block:
|
||||||
|
- name: Create a simple pod
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
definition:
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
namespace: "{{ test_namespace }}"
|
||||||
|
name: "{{ pod }}"
|
||||||
|
labels:
|
||||||
|
label1: foo
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- image: busybox:musl
|
||||||
|
name: busybox
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- while true; do echo $(date); sleep 10; done
|
||||||
|
wait: yes
|
||||||
|
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
||||||
|
|
||||||
|
|
||||||
|
- name: Add a label, and hide some fields
|
||||||
|
kubernetes.core.k8s_json_patch:
|
||||||
|
kind: Pod
|
||||||
|
namespace: "{{ test_namespace }}"
|
||||||
|
name: "{{ pod }}"
|
||||||
|
patch:
|
||||||
|
- op: add
|
||||||
|
path: /metadata/labels/label2
|
||||||
|
value: bar
|
||||||
|
hidden_fields:
|
||||||
|
- metadata.managedFields
|
||||||
|
register: hf1
|
||||||
|
|
||||||
|
- name: Ensure hidden fields are not present
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- "'managedFields' not in hf1.result['metadata']"
|
||||||
|
|
||||||
|
|
||||||
|
- name: Add a label, without hiding our fields
|
||||||
|
kubernetes.core.k8s_json_patch:
|
||||||
|
kind: Pod
|
||||||
|
namespace: "{{ test_namespace }}"
|
||||||
|
name: "{{ pod }}"
|
||||||
|
patch:
|
||||||
|
- op: add
|
||||||
|
path: /metadata/labels/label3
|
||||||
|
value: bar
|
||||||
|
hidden_fields:
|
||||||
|
- something.else
|
||||||
|
register: hf2
|
||||||
|
|
||||||
|
- name: Ensure hidden fields are present
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- "'managedFields' in hf2.result['metadata']"
|
||||||
|
|
||||||
|
|
||||||
|
- name: Patching the same resource with missing hidden fields should have no effect
|
||||||
|
kubernetes.core.k8s_json_patch:
|
||||||
|
kind: Pod
|
||||||
|
namespace: "{{ test_namespace }}"
|
||||||
|
name: "{{ pod }}"
|
||||||
|
patch:
|
||||||
|
- op: add
|
||||||
|
path: /metadata/labels/label2
|
||||||
|
value: bar
|
||||||
|
hidden_fields:
|
||||||
|
- does.not.exist
|
||||||
|
register: hf2
|
||||||
|
|
||||||
|
- name: Ensure no change with missing hidden fields
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- not hf2.changed
|
||||||
|
|
||||||
|
|
||||||
|
always:
|
||||||
|
- name: Remove namespace
|
||||||
|
k8s:
|
||||||
|
kind: Namespace
|
||||||
|
name: "{{ test_namespace }}"
|
||||||
|
state: absent
|
||||||
|
ignore_errors: true
|
||||||
@@ -33,7 +33,6 @@
|
|||||||
ports:
|
ports:
|
||||||
- containerPort: 80
|
- containerPort: 80
|
||||||
|
|
||||||
|
|
||||||
- name: Crash the existing deployment
|
- name: Crash the existing deployment
|
||||||
k8s:
|
k8s:
|
||||||
state: present
|
state: present
|
||||||
@@ -228,7 +227,7 @@
|
|||||||
hostPath:
|
hostPath:
|
||||||
path: /var/lib/docker/containers
|
path: /var/lib/docker/containers
|
||||||
register: crash
|
register: crash
|
||||||
ignore_errors: true
|
ignore_errors: yes
|
||||||
|
|
||||||
- name: Assert that the Daemonset failed
|
- name: Assert that the Daemonset failed
|
||||||
assert:
|
assert:
|
||||||
@@ -291,6 +290,297 @@
|
|||||||
that:
|
that:
|
||||||
- failed_version | int + 1 == result.resources[0].metadata.annotations['deprecated.daemonset.template.generation'] | int
|
- failed_version | int + 1 == result.resources[0].metadata.annotations['deprecated.daemonset.template.generation'] | int
|
||||||
|
|
||||||
|
- name: Create deployment with specific labels for selector testing
|
||||||
|
k8s:
|
||||||
|
state: present
|
||||||
|
wait: yes
|
||||||
|
wait_timeout: "{{ k8s_wait_timeout }}"
|
||||||
|
definition:
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: nginx-labeled
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
test-group: label-selector-test
|
||||||
|
spec:
|
||||||
|
replicas: 2
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: nginx-labeled
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx-labeled
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:1.17
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
|
||||||
|
- name: Update deployment to create second revision
|
||||||
|
k8s:
|
||||||
|
state: present
|
||||||
|
wait: yes
|
||||||
|
wait_timeout: 30
|
||||||
|
definition:
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: nginx-labeled
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
test-group: label-selector-test
|
||||||
|
spec:
|
||||||
|
replicas: 2
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: nginx-labeled
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx-labeled
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:1.18
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
|
||||||
|
- name: Test rollback with label selectors
|
||||||
|
k8s_rollback:
|
||||||
|
api_version: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
name: nginx-labeled
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
label_selectors:
|
||||||
|
- "test-group=label-selector-test"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert label selector rollback worked
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
- result.rollback_info | length == 1
|
||||||
|
- result.rollback_info[0].method == "patch"
|
||||||
|
|
||||||
|
- name: Create deployment with single revision
|
||||||
|
k8s:
|
||||||
|
state: present
|
||||||
|
wait: yes
|
||||||
|
wait_timeout: 30
|
||||||
|
definition:
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: single-revision
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: single-revision
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: single-revision
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:1.17
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
|
||||||
|
- name: Try to rollback deployment with no previous revisions
|
||||||
|
k8s_rollback:
|
||||||
|
api_version: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
name: single-revision
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert warning is returned for no rollout history
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- not result.changed
|
||||||
|
- result.rollback_info[0].warnings is defined
|
||||||
|
- "'No rollout history found' in result.rollback_info[0].warnings[0]"
|
||||||
|
|
||||||
|
- name: Create a service for unsupported resource test
|
||||||
|
k8s:
|
||||||
|
state: present
|
||||||
|
definition:
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: test-service
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: nginx
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 80
|
||||||
|
|
||||||
|
- name: Test rollback on unsupported resource type
|
||||||
|
k8s_rollback:
|
||||||
|
api_version: v1
|
||||||
|
kind: Service
|
||||||
|
name: test-service
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
register: result
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Assert error message for unsupported resource
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- not result.changed
|
||||||
|
- "'Cannot perform rollback on resource of kind Service' in result.msg"
|
||||||
|
|
||||||
|
- name: Test rollback on non-existent deployment
|
||||||
|
k8s_rollback:
|
||||||
|
api_version: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
name: non-existent
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert no resources found
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- not result.changed
|
||||||
|
- result.rollback_info | length == 0
|
||||||
|
|
||||||
|
- name: Create multiple deployments with same label
|
||||||
|
k8s:
|
||||||
|
state: present
|
||||||
|
wait: yes
|
||||||
|
wait_timeout: 30
|
||||||
|
definition:
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: "multi-{{ item }}"
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
labels:
|
||||||
|
group: multi-test
|
||||||
|
app: multi
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: "multi-{{ item }}"
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: "multi-{{ item }}"
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:1.17
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
loop: [1, 2, 3]
|
||||||
|
|
||||||
|
- name: Update multiple deployments to create second revisions
|
||||||
|
k8s:
|
||||||
|
state: present
|
||||||
|
wait: yes
|
||||||
|
wait_timeout: 30
|
||||||
|
definition:
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: "multi-{{ item }}"
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
labels:
|
||||||
|
group: multi-test
|
||||||
|
app: multi
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: "multi-{{ item }}"
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: "multi-{{ item }}"
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:1.18
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
loop: [1, 2, 3]
|
||||||
|
|
||||||
|
- name: Rollback multiple deployments using label selector
|
||||||
|
k8s_rollback:
|
||||||
|
api_version: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
name: "multi-{{ item }}"
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
label_selectors:
|
||||||
|
- "group=multi-test"
|
||||||
|
register: result
|
||||||
|
loop: [1, 2, 3]
|
||||||
|
|
||||||
|
- name: Assert multiple resources were rolled back
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result.results | length == 3
|
||||||
|
- result.results | selectattr('changed', 'equalto', true) | list | length == 3
|
||||||
|
- result.results | selectattr('rollback_info', 'defined') | list | length == 3
|
||||||
|
- result.results | map(attribute='rollback_info') | map('first') | map(attribute='method') | select('equalto', 'patch') | list | length == 3
|
||||||
|
|
||||||
|
- name: Validate rollback_info structure for deployment
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result.results is defined
|
||||||
|
- result.results[0].rollback_info is defined
|
||||||
|
- result.results[0].rollback_info | length > 0
|
||||||
|
- result.results[0].rollback_info[0].method == "patch"
|
||||||
|
- result.results[0].rollback_info[0].body is defined
|
||||||
|
- result.results[0].rollback_info[0].resources is defined
|
||||||
|
- result.results[0].rollback_info[0].resources.metadata is defined
|
||||||
|
- result.results[0].rollback_info[0].resources.spec is defined
|
||||||
|
|
||||||
|
- name: Test rollback with field selectors
|
||||||
|
k8s_rollback:
|
||||||
|
api_version: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
name: multi-1
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
field_selectors:
|
||||||
|
- "metadata.name=multi-1"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Assert field selector rollback worked
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
- result.rollback_info | length == 1
|
||||||
|
- result.rollback_info[0].resources.metadata.name == "multi-1"
|
||||||
|
|
||||||
|
- name: Test check mode return values
|
||||||
|
k8s_rollback:
|
||||||
|
api_version: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
name: multi-2
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
register: result
|
||||||
|
check_mode: yes
|
||||||
|
|
||||||
|
- name: Validate check mode returns expected structure
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
- result.rollback_info is defined
|
||||||
|
- result.rollback_info[0].method == "patch"
|
||||||
|
- result.rollback_info[0].body is defined
|
||||||
|
|
||||||
always:
|
always:
|
||||||
- name: Delete {{ namespace }} namespace
|
- name: Delete {{ namespace }} namespace
|
||||||
k8s:
|
k8s:
|
||||||
|
|||||||
@@ -94,6 +94,52 @@
|
|||||||
namespace: "{{ kustomize_ns }}"
|
namespace: "{{ kustomize_ns }}"
|
||||||
definition: "{{ lookup('kubernetes.core.kustomize', dir=kustomize_dir, opt_dirs=tmp_dir_path) }}"
|
definition: "{{ lookup('kubernetes.core.kustomize', dir=kustomize_dir, opt_dirs=tmp_dir_path) }}"
|
||||||
|
|
||||||
|
- name: Create temporarly directory for test
|
||||||
|
ansible.builtin.tempfile:
|
||||||
|
state: directory
|
||||||
|
suffix: .testkustomize
|
||||||
|
register: _tmp_dir_kustomize
|
||||||
|
|
||||||
|
- name: Download helloWorld example
|
||||||
|
ansible.builtin.get_url:
|
||||||
|
url: "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/refs/heads/master/examples/loadHttp/kustomization.yaml"
|
||||||
|
dest: "{{ _tmp_dir_kustomize.path }}"
|
||||||
|
|
||||||
|
- name: Run tinyproxy in docker
|
||||||
|
# Replace the 'app: hello' with 'app: ${TEST_APP}'
|
||||||
|
ansible.builtin.command: "docker run --rm -d -p 8888:8888 --name=tinyproxy dannydirect/tinyproxy ANY"
|
||||||
|
|
||||||
|
- name: Ensure that tinyproxy is running
|
||||||
|
ansible.builtin.wait_for:
|
||||||
|
host: localhost
|
||||||
|
port: 8888
|
||||||
|
state: started
|
||||||
|
|
||||||
|
- name: Test kustomize lookup plugin with environment variables in the string format
|
||||||
|
set_fact:
|
||||||
|
resource_kustomize: "{{ lookup('kubernetes.core.kustomize', dir=_tmp_dir_kustomize.path, environment='HTTPS_PROXY=http://localhost:8888 VAR2=Flase') }}"
|
||||||
|
|
||||||
|
- name: Test kustomize lookup plugin with environment variables in the dict format
|
||||||
|
set_fact:
|
||||||
|
resource_kustomize: "{{ lookup('kubernetes.core.kustomize', dir=_tmp_dir_kustomize.path, environment={'HTTPS_PROXY': 'http://localhost:8888', 'VAR2': 'Flase'}) }}"
|
||||||
|
|
||||||
|
|
||||||
|
- name: Stop tinyproxy
|
||||||
|
ansible.builtin.command: "docker stop tinyproxy"
|
||||||
|
|
||||||
|
- name: Ensure kustomize lookup plugin fail with proxy down
|
||||||
|
set_fact:
|
||||||
|
resource_kustomize: "{{ lookup('kubernetes.core.kustomize', dir=_tmp_dir_kustomize.path, environment='HTTPS_PROXY=http://localhost:8888 VAR2=Flase') }}"
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Assert that kustomize lookup plugin failed
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- result.failed
|
||||||
|
- "'proxyconnect tcp: dial' in result.msg"
|
||||||
|
- "'connection refused' in result.msg"
|
||||||
|
|
||||||
always:
|
always:
|
||||||
- name: Delete namespace
|
- name: Delete namespace
|
||||||
k8s:
|
k8s:
|
||||||
@@ -105,4 +151,11 @@
|
|||||||
- name: Delete temporary directory
|
- name: Delete temporary directory
|
||||||
file:
|
file:
|
||||||
state: absent
|
state: absent
|
||||||
path: "{{ tmp_dir_path }}"
|
path: "{{ item }}"
|
||||||
|
with_items:
|
||||||
|
- "{{ tmp_dir_path }}"
|
||||||
|
- "{{ _tmp_dir_kustomize.path }}"
|
||||||
|
|
||||||
|
- name: Stop tinyproxy
|
||||||
|
ansible.builtin.command: "docker stop tinyproxy"
|
||||||
|
ignore_errors: true
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user