mirror of
https://github.com/ansible-collections/kubernetes.core.git
synced 2026-05-11 20:12:18 +00:00
Compare commits
86 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80c33c5573 | ||
|
|
73dc94be68 | ||
|
|
1bc65230bb | ||
|
|
91427a5b6a | ||
|
|
1d1a23b1ab | ||
|
|
6edc84678d | ||
|
|
66bd8620e4 | ||
|
|
94b43dc582 | ||
|
|
3c4f9cee60 | ||
|
|
a54b4a13b6 | ||
|
|
e16b3c46b0 | ||
|
|
bc60523372 | ||
|
|
64f3f07c5a | ||
|
|
d6492b66d9 | ||
|
|
4d5388ddf8 | ||
|
|
6dadd06252 | ||
|
|
69dc7d5c5d | ||
|
|
2fa1c2c6e5 | ||
|
|
f2623dd3cf | ||
|
|
8772d8c997 | ||
|
|
a32108f64f | ||
|
|
365e5e9159 | ||
|
|
448a68da3d | ||
|
|
46acab9c4c | ||
|
|
fdb77182c8 | ||
|
|
fa3d94f793 | ||
|
|
9ec27cf37c | ||
|
|
10cb241256 | ||
|
|
92e1f581fe | ||
|
|
7f69aff0d6 | ||
|
|
8c65ac066d | ||
|
|
1d962fb932 | ||
|
|
27ce23aa72 | ||
|
|
993652b581 | ||
|
|
9bd9d22db3 | ||
|
|
0593426918 | ||
|
|
8fa5b201a4 | ||
|
|
94c1f57f36 | ||
|
|
d0b97319a5 | ||
|
|
38d5c81051 | ||
|
|
914a16ec5c | ||
|
|
cb2070c93f | ||
|
|
b594d35931 | ||
|
|
00699ac3e5 | ||
|
|
d329e7ee42 | ||
|
|
d4fc22c74e | ||
|
|
b648f45e90 | ||
|
|
2cb5d6c316 | ||
|
|
0e7229cf8d | ||
|
|
9ec6912325 | ||
|
|
7cdf0d03f5 | ||
|
|
91df2f10bc | ||
|
|
1943dfc3d9 | ||
|
|
eb731cd3a5 | ||
|
|
ecc64cace1 | ||
|
|
bc0de24cba | ||
|
|
9f60b151ba | ||
|
|
159a63af97 | ||
|
|
6efabd3418 | ||
|
|
aee847431a | ||
|
|
6609abdd5a | ||
|
|
219c747a24 | ||
|
|
7559b65946 | ||
|
|
c8a33c7180 | ||
|
|
52f2cb5587 | ||
|
|
513ff66fcf | ||
|
|
fca0dc0485 | ||
|
|
cd686316e9 | ||
|
|
b8e9873f64 | ||
|
|
4c305e73f0 | ||
|
|
c8a9326306 | ||
|
|
445d367059 | ||
|
|
fdb8af7ca9 | ||
|
|
a89f19b4e5 | ||
|
|
5bc53dba7c | ||
|
|
b07fbd6271 | ||
|
|
44a2fc392a | ||
|
|
6265a3e7ce | ||
|
|
0afd257dd0 | ||
|
|
d192157ed8 | ||
|
|
6a04f42d0b | ||
|
|
5064d722c3 | ||
|
|
fb80d973c4 | ||
|
|
8363a4debf | ||
|
|
0c5233a650 | ||
|
|
c0666a5137 |
13
.github/workflows/integration-tests.yaml
vendored
13
.github/workflows/integration-tests.yaml
vendored
@@ -55,14 +55,13 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# Ref must match a branch/tag on github.com/ansible/ansible (e.g. stable-2.18, not 2.18).
|
||||
ansible-version: ["stable-2.18", "milestone"]
|
||||
enable-turbo-mode: [true, false]
|
||||
exclude:
|
||||
- ansible-version: "milestone"
|
||||
enable-turbo-mode: true
|
||||
ansible-version:
|
||||
- milestone
|
||||
python-version:
|
||||
- "3.12"
|
||||
enable-turbo-mode:
|
||||
- true
|
||||
- false
|
||||
workflow-id: ${{ fromJson(needs.splitter.outputs.test_jobs) }}
|
||||
name: "integration-py${{ matrix.python-version }}-${{ matrix.ansible-version }}-${{ matrix.workflow-id }}-enable_turbo=${{ matrix.enable-turbo-mode }}"
|
||||
steps:
|
||||
@@ -108,7 +107,6 @@ jobs:
|
||||
source_path: ${{ env.source }}
|
||||
|
||||
- name: checkout ansible-collections/cloud.common
|
||||
if: ${{ matrix.enable-turbo-mode == true }}
|
||||
uses: ansible-network/github_actions/.github/actions/checkout_dependency@main
|
||||
with:
|
||||
repository: ansible-collections/cloud.common
|
||||
@@ -130,7 +128,6 @@ jobs:
|
||||
ref: main
|
||||
|
||||
- name: install cloud.common collection
|
||||
if: ${{ matrix.enable-turbo-mode == true }}
|
||||
uses: ansible-network/github_actions/.github/actions/build_install_collection@main
|
||||
with:
|
||||
install_python_dependencies: true
|
||||
|
||||
@@ -4,17 +4,18 @@ Kubernetes Collection Release Notes
|
||||
|
||||
.. contents:: Topics
|
||||
|
||||
v5.4.2
|
||||
v6.3.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
This release includes bugfixes such as replacing the passing of ``warnings`` to ``exit_json`` with ``AnsibleModule.warn`` as well as a security update for selectively redacting sensitive information from kubeconfig.
|
||||
This release includes bugfixes such as implementing idempotency for the ``helm_pull`` module as well as a security update for selectively redacting sensitive information from kubeconfig.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Remove deprecated import from ``ansible.module_utils._text`` (https://github.com/ansible-collections/kubernetes.core/pull/1053).
|
||||
- helm - add ``release_values`` key to ``status`` return value that can be accessed using Jinja2 dot notation (https://github.com/ansible-collections/kubernetes.core/pull/1056).
|
||||
- helm_info - add ``release_values`` key to ``status`` return value that can be accessed using Jinja2 dot notation (https://github.com/ansible-collections/kubernetes.core/pull/1056).
|
||||
|
||||
@@ -33,12 +34,64 @@ Bugfixes
|
||||
--------
|
||||
|
||||
- Add idempotency for ``helm_pull`` module (https://github.com/ansible-collections/kubernetes.core/pull/1055).
|
||||
- Fixed a bug where setting ``K8S_AUTH_VERIFY_SSL=true`` (or any string value) caused the value to be treated as a separate ``kubectl`` command argument (https://github.com/ansible-collections/kubernetes.core/pull/1049).
|
||||
- Fixed a bug where setting ``K8S_AUTH_VERIFY_SSL=true`` (or any string value) caused the value to be treated as a separate ``kubectl`` command argument. (https://github.com/ansible-collections/kubernetes.core/pull/1049).
|
||||
- Limit supported versions of Helm to <4.0.0 (https://github.com/ansible-collections/kubernetes.core/pull/1039).
|
||||
- Replace passing ``warnings`` to ``exit_json`` with ``AnsibleModule.warn`` in the ``k8s_drain``, ``k8s_rollback.py`` and ``k8s_scale.py`` modules as it deprecated in ``ansible-core>=2.19.0`` and will be removed in ``ansible-core>=2.23.0`` (https://github.com/ansible-collections/kubernetes.core/pull/1033).
|
||||
- k8s - Fix return block from the module documentation (https://github.com/ansible-collections/kubernetes.core/pull/1056).
|
||||
- meta - Add ``k8s_cluster_info``, ``k8s_json_patch`` and ``k8s_rollback`` to k8s action group (https://github.com/ansible-collections/kubernetes.core/pull/992).
|
||||
|
||||
v6.2.0
|
||||
======
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
--------------------------------
|
||||
|
||||
- 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).
|
||||
|
||||
v5.4.1
|
||||
======
|
||||
|
||||
|
||||
2
Makefile
2
Makefile
@@ -1,5 +1,5 @@
|
||||
# Also needs to be updated in galaxy.yml
|
||||
VERSION = 5.4.2
|
||||
VERSION = 6.3.0
|
||||
|
||||
TEST_ARGS ?= ""
|
||||
PYTHON_VERSION ?= `python -c 'import platform; print(".".join(platform.python_version_tuple()[0:2]))'`
|
||||
|
||||
19
README.md
19
README.md
@@ -21,12 +21,10 @@ For more information about communication, see the [Ansible communication guide](
|
||||
## Requirements
|
||||
|
||||
<!--start requires_ansible-->
|
||||
## Ansible Version Compatibility
|
||||
## Ansible version compatibility
|
||||
|
||||
This collection has been tested against following Ansible versions: **>=2.15.0**.
|
||||
This collection has been tested against 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.
|
||||
A collection may contain metadata that identifies these versions.
|
||||
PEP440 is the schema used to describe the versions of Ansible.
|
||||
@@ -51,22 +49,17 @@ This collection supports Kubernetes versions >= 1.24.
|
||||
Click on the name of a plugin or module to view that content's documentation:
|
||||
|
||||
<!--start collection content-->
|
||||
### Connection Plugins
|
||||
### Connection plugins
|
||||
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.
|
||||
|
||||
### K8s filter Plugins
|
||||
### K8s filter plugins
|
||||
Name | Description
|
||||
--- | ---
|
||||
kubernetes.core.k8s_config_resource_name|Generate resource name for the given resource of type ConfigMap, Secret
|
||||
|
||||
### Inventory Plugins
|
||||
Name | Description
|
||||
--- | ---
|
||||
[kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_inventory.rst)|Kubernetes (K8s) inventory source
|
||||
|
||||
### Lookup Plugins
|
||||
### Lookup plugins
|
||||
Name | Description
|
||||
--- | ---
|
||||
[kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_lookup.rst)|Query the K8s API
|
||||
@@ -110,7 +103,7 @@ You can also include it in a `requirements.yml` file and install it via `ansible
|
||||
---
|
||||
collections:
|
||||
- name: kubernetes.core
|
||||
version: 5.4.2
|
||||
version: 6.3.0
|
||||
```
|
||||
|
||||
### Installing the Kubernetes Python Library
|
||||
|
||||
@@ -1029,13 +1029,13 @@ releases:
|
||||
- module_utils/k8s/service - fix issue when trying to delete resource using
|
||||
`delete_options` and `check_mode=true` (https://github.com/ansible-collections/kubernetes.core/issues/892).
|
||||
minor_changes:
|
||||
- kubernetes.core - Bump version of ``ansible-lint`` to ``25.1.2`` (https://github.com/ansible-collections/kubernetes.core/pull/919).
|
||||
- Bump version of ansible-lint to 25.1.2 (https://github.com/ansible-collections/kubernetes.core/pull/919).
|
||||
- action/k8s_info - update templating mechanism with changes from ``ansible-core
|
||||
2.19`` (https://github.com/ansible-collections/kubernetes.core/pull/888).
|
||||
- helm - add ``reset_then_reuse_values`` support to helm module (https://github.com/ansible-collections/kubernetes.core/issues/803).
|
||||
- helm - add support for ``insecure_skip_tls_verify`` option to helm and ``helm_repository`` (https://github.com/ansible-collections/kubernetes.core/issues/694).
|
||||
- helm - add reset_then_reuse_values support to helm module (https://github.com/ansible-collections/kubernetes.core/issues/803).
|
||||
- helm - add support for ``insecure_skip_tls_verify`` option to helm and helm_repository(https://github.com/ansible-collections/kubernetes.core/issues/694).
|
||||
release_summary: This release includes minor changes, bug fixes and also bumps
|
||||
``ansible-lint`` version to ``25.1.2``.
|
||||
ansible-lint version to ``25.1.2``.
|
||||
fragments:
|
||||
- 20250324-k8s_info-templating.yaml
|
||||
- 5.3.0.yml
|
||||
@@ -1073,12 +1073,67 @@ releases:
|
||||
- 20250922-remove-ansible-six-imports.yaml
|
||||
- 5.4.1.yml
|
||||
release_date: '2025-10-07'
|
||||
5.4.2:
|
||||
6.0.0:
|
||||
changes:
|
||||
breaking_changes:
|
||||
- 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).
|
||||
fragments:
|
||||
- 20250121-breaking-changes-6.0.0.yml
|
||||
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'
|
||||
6.3.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Add idempotency for ``helm_pull`` module (https://github.com/ansible-collections/kubernetes.core/pull/1055).
|
||||
- Fixed a bug where setting ``K8S_AUTH_VERIFY_SSL=true`` (or any string value)
|
||||
caused the value to be treated as a separate ``kubectl`` command argument
|
||||
caused the value to be treated as a separate ``kubectl`` command argument.
|
||||
(https://github.com/ansible-collections/kubernetes.core/pull/1049).
|
||||
- Limit supported versions of Helm to <4.0.0 (https://github.com/ansible-collections/kubernetes.core/pull/1039).
|
||||
- Replace passing ``warnings`` to ``exit_json`` with ``AnsibleModule.warn``
|
||||
@@ -1096,13 +1151,14 @@ releases:
|
||||
be removed in a release after 2027-01-08. Use ``status.release_values`` instead
|
||||
(https://github.com/ansible-collections/kubernetes.core/pull/1056).
|
||||
minor_changes:
|
||||
- helm - added ``release_values`` key to ``status`` return value that can be
|
||||
accessed using Jinja2 dot notation (https://github.com/ansible-collections/kubernetes.core/pull/1056).
|
||||
- helm_info - added ``release_values`` key to ``status`` return value that can
|
||||
- Remove deprecated import from ``ansible.module_utils._text`` (https://github.com/ansible-collections/kubernetes.core/pull/1053).
|
||||
- helm - add ``release_values`` key to ``status`` return value that can be accessed
|
||||
using Jinja2 dot notation (https://github.com/ansible-collections/kubernetes.core/pull/1056).
|
||||
- helm_info - add ``release_values`` key to ``status`` return value that can
|
||||
be accessed using Jinja2 dot notation (https://github.com/ansible-collections/kubernetes.core/pull/1056).
|
||||
release_summary: This release includes various bugfixes such as replacing the
|
||||
passing of ``warnings`` to ``exit_json`` with ``AnsibleModule.warn`` as well
|
||||
as security updates for selectively redacting sensitive information from kubeconfig.
|
||||
release_summary: This release includes bugfixes such as implementing idempotency
|
||||
for the ``helm_pull`` module as well as a security update for selectively
|
||||
redacting sensitive information from kubeconfig.
|
||||
security_fixes:
|
||||
- Selectively redact sensitive info from kubeconfig instead of applying blanket
|
||||
``no_log=True`` (https://github.com/ansible-collections/kubernetes.core/pull/1014).
|
||||
@@ -1112,7 +1168,8 @@ releases:
|
||||
- 20251007-selective-kubeconfig-redaction.yaml
|
||||
- 20251115-limit-versions-of-helm.yaml
|
||||
- 20251220-fix-K8S_AUTH_VERIFY_SSL-in-kubectl-connecton-plugion.yaml
|
||||
- 20251228-1053-remove-deprecated-import.yaml
|
||||
- 20260107-add-idempodency-for-helm-pull.yaml
|
||||
- 20260108-fix-sanity-failures.yml
|
||||
- 5-4-2.yaml
|
||||
- 6-3-0.yaml
|
||||
release_date: '2026-02-03'
|
||||
|
||||
@@ -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.
|
||||
@@ -17,7 +17,7 @@ Requirements
|
||||
|
||||
To use the modules, you'll need the following:
|
||||
|
||||
- Ansible 2.9.17 or latest installed
|
||||
- Ansible 2.16.0 or latest installed
|
||||
- `Kubernetes Python client <https://pypi.org/project/kubernetes/>`_ installed on the host that will execute the modules.
|
||||
|
||||
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
.. _ansible_collections.kubernetes.core.docsite.k8s_ansible_inventory:
|
||||
|
||||
*****************************************
|
||||
Using Kubernetes dynamic inventory plugin
|
||||
*****************************************
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Kubernetes dynamic inventory plugin
|
||||
===================================
|
||||
|
||||
|
||||
The best way to interact with your Pods is to use the Kubernetes dynamic inventory plugin, which queries Kubernetes APIs using ``kubectl`` command line available on controller node and tells Ansible what Pods can be managed.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
To use the Kubernetes dynamic inventory plugins, you must install `Kubernetes Python client <https://github.com/kubernetes-client/python>`_, `kubectl <https://github.com/kubernetes/kubectl>`_ on your control node (the host running Ansible).
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install kubernetes
|
||||
|
||||
Please refer to Kubernetes official documentation for `installing kubectl <https://kubernetes.io/docs/tasks/tools/install-kubectl/>`_ on the given operating systems.
|
||||
|
||||
To use this Kubernetes dynamic inventory plugin, you need to enable it first by specifying the following in the ``ansible.cfg`` file:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[inventory]
|
||||
enable_plugins = kubernetes.core.k8s
|
||||
|
||||
Then, create a file that ends in ``.k8s.yml`` or ``.k8s.yaml`` in your working directory.
|
||||
|
||||
The ``kubernetes.core.k8s`` inventory plugin takes in the same authentication information as any other Kubernetes modules.
|
||||
|
||||
Here's an example of a valid inventory file:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
plugin: kubernetes.core.k8s
|
||||
|
||||
Executing ``ansible-inventory --list -i <filename>.k8s.yml`` will create a list of Pods that are ready to be configured using Ansible.
|
||||
|
||||
You can also provide the namespace to gather information about specific pods from the given namespace. For example, to gather information about Pods under the ``test`` namespace you will specify the ``namespaces`` parameter:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
plugin: kubernetes.core.k8s
|
||||
connections:
|
||||
- namespaces:
|
||||
- test
|
||||
|
||||
Using vaulted configuration files
|
||||
=================================
|
||||
|
||||
Since the inventory configuration file contains Kubernetes related sensitive information in plain text, a security risk, you may want to
|
||||
encrypt your entire inventory configuration file.
|
||||
|
||||
You can encrypt a valid inventory configuration file as follows:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ ansible-vault encrypt <filename>.k8s.yml
|
||||
New Vault password:
|
||||
Confirm New Vault password:
|
||||
Encryption successful
|
||||
|
||||
$ echo "MySuperSecretPassw0rd!" > /path/to/vault_password_file
|
||||
|
||||
And you can use this vaulted inventory configuration file using:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ ansible-inventory -i <filename>.k8s.yml --list --vault-password-file=/path/to/vault_password_file
|
||||
|
||||
|
||||
.. seealso::
|
||||
|
||||
`Kubernetes Python client - Issue Tracker <https://github.com/kubernetes-client/python/issues>`_
|
||||
The issue tracker for Kubernetes Python client
|
||||
`Kubectl installation <https://kubernetes.io/docs/tasks/tools/install-kubectl/>`_
|
||||
Installation guide for installing Kubectl
|
||||
:ref:`working_with_playbooks`
|
||||
An introduction to playbooks
|
||||
:ref:`playbooks_vault`
|
||||
Using Vault in playbooks
|
||||
@@ -13,6 +13,5 @@ To get started, please select one of the following topics.
|
||||
:maxdepth: 1
|
||||
|
||||
kubernetes_scenarios/k8s_intro
|
||||
kubernetes_scenarios/k8s_inventory
|
||||
kubernetes_scenarios/k8s_scenarios
|
||||
|
||||
|
||||
@@ -330,6 +330,27 @@ Parameters
|
||||
<div style="font-size: small; color: darkgreen"><br/>aliases: kubeconfig_path</div>
|
||||
</td>
|
||||
</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>
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
@@ -601,6 +622,48 @@ Parameters
|
||||
<div>Skip custom resource definitions when installing or upgrading.</div>
|
||||
</td>
|
||||
</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>
|
||||
<td colspan="2">
|
||||
<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"
|
||||
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
|
||||
- name: Deploy new-relic client chart
|
||||
kubernetes.core.helm:
|
||||
|
||||
@@ -215,6 +215,27 @@ Parameters
|
||||
<div>Pass credentials to all domains.</div>
|
||||
</td>
|
||||
</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>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
|
||||
@@ -194,6 +194,27 @@ Parameters
|
||||
<div>If the directory already exists, it will be overwritten.</div>
|
||||
</td>
|
||||
</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>
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
|
||||
@@ -701,21 +701,6 @@ Examples
|
||||
wait_sleep: 10
|
||||
wait_timeout: 360
|
||||
|
||||
- name: Wait for OpenShift bootstrap to complete
|
||||
kubernetes.core.k8s_info:
|
||||
api_version: v1
|
||||
kind: ConfigMap
|
||||
name: bootstrap
|
||||
namespace: kube-system
|
||||
register: ocp_bootstrap_status
|
||||
until: >
|
||||
ocp_bootstrap_status.resources is defined and
|
||||
(ocp_bootstrap_status.resources | length > 0) and
|
||||
(ocp_bootstrap_status.resources[0].data.status is defined) and
|
||||
(ocp_bootstrap_status.resources[0].data.status == 'complete')
|
||||
retries: 60
|
||||
delay: 15
|
||||
|
||||
|
||||
|
||||
Return Values
|
||||
|
||||
@@ -1,372 +0,0 @@
|
||||
.. _kubernetes.core.k8s_inventory:
|
||||
|
||||
|
||||
*******************
|
||||
kubernetes.core.k8s
|
||||
*******************
|
||||
|
||||
**Kubernetes (K8s) inventory source**
|
||||
|
||||
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 1
|
||||
|
||||
DEPRECATED
|
||||
----------
|
||||
:Removed in collection release after
|
||||
:Why: As discussed in https://github.com/ansible-collections/kubernetes.core/issues/31, we decided to
|
||||
remove the k8s inventory plugin in release 6.0.0.
|
||||
|
||||
:Alternative: Use :ref:`kubernetes.core.k8s_info <kubernetes.core.k8s_info_module>` and :ref:`ansible.builtin.add_host <ansible.builtin.add_host_module>` instead.
|
||||
|
||||
|
||||
|
||||
Synopsis
|
||||
--------
|
||||
- Fetch containers and services for one or more clusters.
|
||||
- Groups by cluster name, namespace, namespace_services, namespace_pods, and labels.
|
||||
- Uses the kubectl connection plugin to access the Kubernetes cluster.
|
||||
- Uses k8s.(yml|yaml) YAML configuration file to set parameter values.
|
||||
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
The below requirements are needed on the local Ansible controller node that executes this inventory.
|
||||
|
||||
- python >= 3.9
|
||||
- kubernetes >= 24.2.0
|
||||
- PyYAML >= 3.11
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<table border=0 cellpadding=0 class="documentation-table">
|
||||
<tr>
|
||||
<th colspan="2">Parameter</th>
|
||||
<th>Choices/<font color="blue">Defaults</font></th>
|
||||
<th>Configuration</th>
|
||||
<th width="100%">Comments</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>connections</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">-</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<div>Optional list of cluster connection settings. If no connections are provided, the default <em>~/.kube/config</em> and active context will be used, and objects will be returned for all namespaces the active user is authorized to access.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="elbow-placeholder"></td>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>api_key</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">-</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<div>Token used to authenticate with the API. Can also be specified via K8S_AUTH_API_KEY environment variable.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="elbow-placeholder"></td>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>ca_cert</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">-</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<div>Path to a CA certificate used to authenticate with the API. Can also be specified via K8S_AUTH_SSL_CA_CERT environment variable.</div>
|
||||
<div style="font-size: small; color: darkgreen"><br/>aliases: ssl_ca_cert</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="elbow-placeholder"></td>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>client_cert</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">-</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<div>Path to a certificate used to authenticate with the API. Can also be specified via K8S_AUTH_CERT_FILE environment variable.</div>
|
||||
<div style="font-size: small; color: darkgreen"><br/>aliases: cert_file</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="elbow-placeholder"></td>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>client_key</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">-</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<div>Path to a key file used to authenticate with the API. Can also be specified via K8S_AUTH_KEY_FILE environment variable.</div>
|
||||
<div style="font-size: small; color: darkgreen"><br/>aliases: key_file</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="elbow-placeholder"></td>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>context</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">-</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<div>The name of a context found in the config file. Can also be specified via K8S_AUTH_CONTEXT environment variable.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="elbow-placeholder"></td>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>host</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">-</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="elbow-placeholder"></td>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>kubeconfig</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">-</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="elbow-placeholder"></td>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>name</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">-</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<div>Optional name to assign to the cluster. If not provided, a name is constructed from the server and port.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="elbow-placeholder"></td>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>namespaces</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">-</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<div>List of namespaces. If not specified, will fetch all containers for all namespaces user is authorized to access.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="elbow-placeholder"></td>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>password</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">-</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<div>Provide a password for authenticating with the API. Can also be specified via K8S_AUTH_PASSWORD environment variable.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="elbow-placeholder"></td>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>username</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">-</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<div>Provide a username for authenticating with the API. Can also be specified via K8S_AUTH_USERNAME environment variable.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="elbow-placeholder"></td>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>validate_certs</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">boolean</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||
<li>no</li>
|
||||
<li>yes</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<div>Whether or not to verify the API server's SSL certificates. Can also be specified via K8S_AUTH_VERIFY_SSL environment variable.</div>
|
||||
<div style="font-size: small; color: darkgreen"><br/>aliases: verify_ssl</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>plugin</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">-</span>
|
||||
/ <span style="color: red">required</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||
<li>kubernetes.core.k8s</li>
|
||||
<li>k8s</li>
|
||||
<li>community.kubernetes.k8s</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<div>token that ensures this is a source file for the 'k8s' plugin.</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br/>
|
||||
|
||||
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# File must be named k8s.yaml or k8s.yml
|
||||
|
||||
- name: Authenticate with token, and return all pods and services for all namespaces
|
||||
plugin: kubernetes.core.k8s
|
||||
connections:
|
||||
- host: https://192.168.64.4:8443
|
||||
api_key: xxxxxxxxxxxxxxxx
|
||||
validate_certs: false
|
||||
|
||||
- name: Use default config (~/.kube/config) file and active context, and return objects for a specific namespace
|
||||
plugin: kubernetes.core.k8s
|
||||
connections:
|
||||
- namespaces:
|
||||
- testing
|
||||
|
||||
- name: Use a custom config file, and a specific context.
|
||||
plugin: kubernetes.core.k8s
|
||||
connections:
|
||||
- kubeconfig: /path/to/config
|
||||
context: 'awx/192-168-64-4:8443/developer'
|
||||
|
||||
|
||||
|
||||
|
||||
Status
|
||||
------
|
||||
|
||||
|
||||
- This inventory will be removed in version 6.0.0. *[deprecated]*
|
||||
- For more information see `DEPRECATED`_.
|
||||
|
||||
|
||||
Authors
|
||||
~~~~~~~
|
||||
|
||||
- Chris Houseknecht (@chouseknecht)
|
||||
- Fabian von Feilitzsch (@fabianvf)
|
||||
|
||||
|
||||
.. hint::
|
||||
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.
|
||||
@@ -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>
|
||||
</td>
|
||||
</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>
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
|
||||
@@ -95,6 +95,26 @@ Parameters
|
||||
<div>Enable the helm chart inflation generator</div>
|
||||
</td>
|
||||
</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>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
@@ -145,6 +165,14 @@ Examples
|
||||
kubernetes.core.k8s:
|
||||
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
|
||||
|
||||
@@ -25,7 +25,7 @@ tags:
|
||||
- openshift
|
||||
- okd
|
||||
- cluster
|
||||
version: 5.4.2
|
||||
version: 6.3.0
|
||||
build_ignore:
|
||||
- .DS_Store
|
||||
- "*.tar.gz"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
requires_ansible: '>=2.15.0'
|
||||
requires_ansible: '>=2.16.0'
|
||||
|
||||
action_groups:
|
||||
helm:
|
||||
@@ -24,11 +24,10 @@ plugin_routing:
|
||||
openshift:
|
||||
redirect: community.okd.openshift
|
||||
k8s:
|
||||
deprecation:
|
||||
tombstone:
|
||||
removal_version: 6.0.0
|
||||
warning_text: >-
|
||||
The k8s inventory plugin has been deprecated and
|
||||
will be removed in release 6.0.0.
|
||||
The k8s inventory plugin was slated for deprecation in 3.3.0 and has been removed in release 6.0.0. Use kubernetes.core.k8s_info and ansible.builtin.add_host instead.
|
||||
modules:
|
||||
k8s_auth:
|
||||
redirect: community.okd.k8s_auth
|
||||
|
||||
@@ -20,7 +20,7 @@ from ansible.errors import (
|
||||
AnsibleError,
|
||||
AnsibleFileNotFound,
|
||||
)
|
||||
from ansible.module_utils._text import to_bytes, to_native, to_text
|
||||
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
|
||||
from ansible.module_utils.parsing.convert_bool import boolean
|
||||
from ansible.plugins.action import ActionBase
|
||||
|
||||
|
||||
@@ -264,7 +264,7 @@ import subprocess
|
||||
import tempfile
|
||||
|
||||
from ansible.errors import AnsibleError, AnsibleFileNotFound
|
||||
from ansible.module_utils._text import to_bytes
|
||||
from ansible.module_utils.common.text.converters import to_bytes
|
||||
from ansible.module_utils.parsing.convert_bool import boolean
|
||||
from ansible.module_utils.six.moves import shlex_quote
|
||||
from ansible.parsing.yaml.loader import AnsibleLoader
|
||||
|
||||
@@ -1,476 +0,0 @@
|
||||
# Copyright (c) 2018 Ansible Project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
DOCUMENTATION = """
|
||||
name: k8s
|
||||
author:
|
||||
- Chris Houseknecht (@chouseknecht)
|
||||
- Fabian von Feilitzsch (@fabianvf)
|
||||
|
||||
short_description: Kubernetes (K8s) inventory source
|
||||
|
||||
description:
|
||||
- Fetch containers and services for one or more clusters.
|
||||
- Groups by cluster name, namespace, namespace_services, namespace_pods, and labels.
|
||||
- Uses the kubectl connection plugin to access the Kubernetes cluster.
|
||||
- Uses k8s.(yml|yaml) YAML configuration file to set parameter values.
|
||||
|
||||
deprecated:
|
||||
removed_in: 6.0.0
|
||||
why: |
|
||||
As discussed in U(https://github.com/ansible-collections/kubernetes.core/issues/31), we decided to
|
||||
remove the k8s inventory plugin in release 6.0.0.
|
||||
alternative: "Use M(kubernetes.core.k8s_info) and M(ansible.builtin.add_host) instead."
|
||||
|
||||
options:
|
||||
plugin:
|
||||
description: token that ensures this is a source file for the 'k8s' plugin.
|
||||
required: True
|
||||
choices: ['kubernetes.core.k8s', 'k8s', 'community.kubernetes.k8s']
|
||||
connections:
|
||||
description:
|
||||
- Optional list of cluster connection settings. If no connections are provided, the default
|
||||
I(~/.kube/config) and active context will be used, and objects will be returned for all namespaces
|
||||
the active user is authorized to access.
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Optional name to assign to the cluster. If not provided, a name is constructed from the server
|
||||
and port.
|
||||
kubeconfig:
|
||||
description:
|
||||
- Path to an existing Kubernetes config file. If not provided, and no other connection
|
||||
options are provided, the Kubernetes client will attempt to load the default
|
||||
configuration file from I(~/.kube/config). Can also be specified via K8S_AUTH_KUBECONFIG
|
||||
environment variable.
|
||||
context:
|
||||
description:
|
||||
- The name of a context found in the config file. Can also be specified via K8S_AUTH_CONTEXT environment
|
||||
variable.
|
||||
host:
|
||||
description:
|
||||
- Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.
|
||||
api_key:
|
||||
description:
|
||||
- Token used to authenticate with the API. Can also be specified via K8S_AUTH_API_KEY environment
|
||||
variable.
|
||||
username:
|
||||
description:
|
||||
- Provide a username for authenticating with the API. Can also be specified via K8S_AUTH_USERNAME
|
||||
environment variable.
|
||||
password:
|
||||
description:
|
||||
- Provide a password for authenticating with the API. Can also be specified via K8S_AUTH_PASSWORD
|
||||
environment variable.
|
||||
client_cert:
|
||||
description:
|
||||
- Path to a certificate used to authenticate with the API. Can also be specified via K8S_AUTH_CERT_FILE
|
||||
environment variable.
|
||||
aliases: [ cert_file ]
|
||||
client_key:
|
||||
description:
|
||||
- Path to a key file used to authenticate with the API. Can also be specified via K8S_AUTH_KEY_FILE
|
||||
environment variable.
|
||||
aliases: [ key_file ]
|
||||
ca_cert:
|
||||
description:
|
||||
- Path to a CA certificate used to authenticate with the API. Can also be specified via
|
||||
K8S_AUTH_SSL_CA_CERT environment variable.
|
||||
aliases: [ ssl_ca_cert ]
|
||||
validate_certs:
|
||||
description:
|
||||
- "Whether or not to verify the API server's SSL certificates. Can also be specified via
|
||||
K8S_AUTH_VERIFY_SSL environment variable."
|
||||
type: bool
|
||||
aliases: [ verify_ssl ]
|
||||
namespaces:
|
||||
description:
|
||||
- List of namespaces. If not specified, will fetch all containers for all namespaces user is authorized
|
||||
to access.
|
||||
|
||||
requirements:
|
||||
- "python >= 3.9"
|
||||
- "kubernetes >= 24.2.0"
|
||||
- "PyYAML >= 3.11"
|
||||
"""
|
||||
|
||||
EXAMPLES = r"""
|
||||
# File must be named k8s.yaml or k8s.yml
|
||||
|
||||
- name: Authenticate with token, and return all pods and services for all namespaces
|
||||
plugin: kubernetes.core.k8s
|
||||
connections:
|
||||
- host: https://192.168.64.4:8443
|
||||
api_key: xxxxxxxxxxxxxxxx
|
||||
validate_certs: false
|
||||
|
||||
- name: Use default config (~/.kube/config) file and active context, and return objects for a specific namespace
|
||||
plugin: kubernetes.core.k8s
|
||||
connections:
|
||||
- namespaces:
|
||||
- testing
|
||||
|
||||
- name: Use a custom config file, and a specific context.
|
||||
plugin: kubernetes.core.k8s
|
||||
connections:
|
||||
- kubeconfig: /path/to/config
|
||||
context: 'awx/192-168-64-4:8443/developer'
|
||||
"""
|
||||
|
||||
import json
|
||||
|
||||
from ansible.errors import AnsibleError
|
||||
from ansible.plugins.inventory import BaseInventoryPlugin, Cacheable, Constructable
|
||||
|
||||
try:
|
||||
from kubernetes.dynamic.exceptions import DynamicApiError
|
||||
|
||||
HAS_K8S_MODULE_HELPER = True
|
||||
k8s_import_exception = None
|
||||
except ImportError as e:
|
||||
HAS_K8S_MODULE_HELPER = False
|
||||
k8s_import_exception = e
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
||||
get_api_client,
|
||||
)
|
||||
|
||||
|
||||
def format_dynamic_api_exc(exc):
|
||||
if exc.body:
|
||||
if exc.headers and exc.headers.get("Content-Type") == "application/json":
|
||||
message = json.loads(exc.body).get("message")
|
||||
if message:
|
||||
return message
|
||||
return exc.body
|
||||
else:
|
||||
return "%s Reason: %s" % (exc.status, exc.reason)
|
||||
|
||||
|
||||
class K8sInventoryException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
NAME = "kubernetes.core.k8s"
|
||||
|
||||
connection_plugin = "kubernetes.core.kubectl"
|
||||
transport = "kubectl"
|
||||
|
||||
def parse(self, inventory, loader, path, cache=True):
|
||||
super(InventoryModule, self).parse(inventory, loader, path)
|
||||
|
||||
self.display.deprecated(
|
||||
"The 'k8s' inventory plugin has been deprecated and will be removed in release 6.0.0",
|
||||
version="6.0.0",
|
||||
collection_name="kubernetes.core",
|
||||
)
|
||||
cache_key = self._get_cache_prefix(path)
|
||||
config_data = self._read_config_data(path)
|
||||
self.setup(config_data, cache, cache_key)
|
||||
|
||||
def setup(self, config_data, cache, cache_key):
|
||||
connections = config_data.get("connections")
|
||||
|
||||
if not HAS_K8S_MODULE_HELPER:
|
||||
raise K8sInventoryException(
|
||||
"This module requires the Kubernetes Python client. Try `pip install kubernetes`. Detail: {0}".format(
|
||||
k8s_import_exception
|
||||
)
|
||||
)
|
||||
|
||||
source_data = None
|
||||
if cache and cache_key in self._cache:
|
||||
try:
|
||||
source_data = self._cache[cache_key]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
if not source_data:
|
||||
self.fetch_objects(connections)
|
||||
|
||||
def fetch_objects(self, connections):
|
||||
if connections:
|
||||
if not isinstance(connections, list):
|
||||
raise K8sInventoryException("Expecting connections to be a list.")
|
||||
|
||||
for connection in connections:
|
||||
if not isinstance(connection, dict):
|
||||
raise K8sInventoryException(
|
||||
"Expecting connection to be a dictionary."
|
||||
)
|
||||
client = get_api_client(**connection)
|
||||
name = connection.get(
|
||||
"name", self.get_default_host_name(client.configuration.host)
|
||||
)
|
||||
if connection.get("namespaces"):
|
||||
namespaces = connection["namespaces"]
|
||||
else:
|
||||
namespaces = self.get_available_namespaces(client)
|
||||
for namespace in namespaces:
|
||||
self.get_pods_for_namespace(client, name, namespace)
|
||||
self.get_services_for_namespace(client, name, namespace)
|
||||
else:
|
||||
client = get_api_client()
|
||||
name = self.get_default_host_name(client.configuration.host)
|
||||
namespaces = self.get_available_namespaces(client)
|
||||
for namespace in namespaces:
|
||||
self.get_pods_for_namespace(client, name, namespace)
|
||||
self.get_services_for_namespace(client, name, namespace)
|
||||
|
||||
@staticmethod
|
||||
def get_default_host_name(host):
|
||||
return (
|
||||
host.replace("https://", "")
|
||||
.replace("http://", "")
|
||||
.replace(".", "-")
|
||||
.replace(":", "_")
|
||||
)
|
||||
|
||||
def get_available_namespaces(self, client):
|
||||
v1_namespace = client.resources.get(api_version="v1", kind="Namespace")
|
||||
try:
|
||||
obj = v1_namespace.get()
|
||||
except DynamicApiError as exc:
|
||||
self.display.debug(exc)
|
||||
raise K8sInventoryException(
|
||||
"Error fetching Namespace list: %s" % format_dynamic_api_exc(exc)
|
||||
)
|
||||
return [namespace.metadata.name for namespace in obj.items]
|
||||
|
||||
def get_pods_for_namespace(self, client, name, namespace):
|
||||
v1_pod = client.resources.get(api_version="v1", kind="Pod")
|
||||
try:
|
||||
obj = v1_pod.get(namespace=namespace)
|
||||
except DynamicApiError as exc:
|
||||
self.display.debug(exc)
|
||||
raise K8sInventoryException(
|
||||
"Error fetching Pod list: %s" % format_dynamic_api_exc(exc)
|
||||
)
|
||||
|
||||
namespace_group = "namespace_{0}".format(namespace)
|
||||
namespace_pods_group = "{0}_pods".format(namespace_group)
|
||||
|
||||
self.inventory.add_group(name)
|
||||
self.inventory.add_group(namespace_group)
|
||||
self.inventory.add_child(name, namespace_group)
|
||||
self.inventory.add_group(namespace_pods_group)
|
||||
self.inventory.add_child(namespace_group, namespace_pods_group)
|
||||
|
||||
for pod in obj.items:
|
||||
pod_name = pod.metadata.name
|
||||
pod_groups = []
|
||||
pod_annotations = (
|
||||
{} if not pod.metadata.annotations else dict(pod.metadata.annotations)
|
||||
)
|
||||
|
||||
if pod.metadata.labels:
|
||||
# create a group for each label_value
|
||||
for key, value in pod.metadata.labels:
|
||||
group_name = "label_{0}_{1}".format(key, value)
|
||||
if group_name not in pod_groups:
|
||||
pod_groups.append(group_name)
|
||||
self.inventory.add_group(group_name)
|
||||
pod_labels = dict(pod.metadata.labels)
|
||||
else:
|
||||
pod_labels = {}
|
||||
|
||||
if not pod.status.containerStatuses:
|
||||
continue
|
||||
|
||||
for container in pod.status.containerStatuses:
|
||||
# add each pod_container to the namespace group, and to each label_value group
|
||||
container_name = "{0}_{1}".format(pod.metadata.name, container.name)
|
||||
self.inventory.add_host(container_name)
|
||||
self.inventory.add_child(namespace_pods_group, container_name)
|
||||
if pod_groups:
|
||||
for group in pod_groups:
|
||||
self.inventory.add_child(group, container_name)
|
||||
|
||||
# Add hostvars
|
||||
self.inventory.set_variable(container_name, "object_type", "pod")
|
||||
self.inventory.set_variable(container_name, "labels", pod_labels)
|
||||
self.inventory.set_variable(
|
||||
container_name, "annotations", pod_annotations
|
||||
)
|
||||
self.inventory.set_variable(
|
||||
container_name, "cluster_name", pod.metadata.clusterName
|
||||
)
|
||||
self.inventory.set_variable(
|
||||
container_name, "pod_node_name", pod.spec.nodeName
|
||||
)
|
||||
self.inventory.set_variable(container_name, "pod_name", pod.spec.name)
|
||||
self.inventory.set_variable(
|
||||
container_name, "pod_host_ip", pod.status.hostIP
|
||||
)
|
||||
self.inventory.set_variable(
|
||||
container_name, "pod_phase", pod.status.phase
|
||||
)
|
||||
self.inventory.set_variable(container_name, "pod_ip", pod.status.podIP)
|
||||
self.inventory.set_variable(
|
||||
container_name, "pod_self_link", pod.metadata.selfLink
|
||||
)
|
||||
self.inventory.set_variable(
|
||||
container_name, "pod_resource_version", pod.metadata.resourceVersion
|
||||
)
|
||||
self.inventory.set_variable(container_name, "pod_uid", pod.metadata.uid)
|
||||
self.inventory.set_variable(
|
||||
container_name, "container_name", container.image
|
||||
)
|
||||
self.inventory.set_variable(
|
||||
container_name, "container_image", container.image
|
||||
)
|
||||
if container.state.running:
|
||||
self.inventory.set_variable(
|
||||
container_name, "container_state", "Running"
|
||||
)
|
||||
if container.state.terminated:
|
||||
self.inventory.set_variable(
|
||||
container_name, "container_state", "Terminated"
|
||||
)
|
||||
if container.state.waiting:
|
||||
self.inventory.set_variable(
|
||||
container_name, "container_state", "Waiting"
|
||||
)
|
||||
self.inventory.set_variable(
|
||||
container_name, "container_ready", container.ready
|
||||
)
|
||||
self.inventory.set_variable(
|
||||
container_name, "ansible_remote_tmp", "/tmp/"
|
||||
)
|
||||
self.inventory.set_variable(
|
||||
container_name, "ansible_connection", self.connection_plugin
|
||||
)
|
||||
self.inventory.set_variable(
|
||||
container_name, "ansible_{0}_pod".format(self.transport), pod_name
|
||||
)
|
||||
self.inventory.set_variable(
|
||||
container_name,
|
||||
"ansible_{0}_container".format(self.transport),
|
||||
container.name,
|
||||
)
|
||||
self.inventory.set_variable(
|
||||
container_name,
|
||||
"ansible_{0}_namespace".format(self.transport),
|
||||
namespace,
|
||||
)
|
||||
|
||||
def get_services_for_namespace(self, client, name, namespace):
|
||||
v1_service = client.resources.get(api_version="v1", kind="Service")
|
||||
try:
|
||||
obj = v1_service.get(namespace=namespace)
|
||||
except DynamicApiError as exc:
|
||||
self.display.debug(exc)
|
||||
raise K8sInventoryException(
|
||||
"Error fetching Service list: %s" % format_dynamic_api_exc(exc)
|
||||
)
|
||||
|
||||
namespace_group = "namespace_{0}".format(namespace)
|
||||
namespace_services_group = "{0}_services".format(namespace_group)
|
||||
|
||||
self.inventory.add_group(name)
|
||||
self.inventory.add_group(namespace_group)
|
||||
self.inventory.add_child(name, namespace_group)
|
||||
self.inventory.add_group(namespace_services_group)
|
||||
self.inventory.add_child(namespace_group, namespace_services_group)
|
||||
|
||||
for service in obj.items:
|
||||
service_name = service.metadata.name
|
||||
service_labels = (
|
||||
{} if not service.metadata.labels else dict(service.metadata.labels)
|
||||
)
|
||||
service_annotations = (
|
||||
{}
|
||||
if not service.metadata.annotations
|
||||
else dict(service.metadata.annotations)
|
||||
)
|
||||
|
||||
self.inventory.add_host(service_name)
|
||||
|
||||
if service.metadata.labels:
|
||||
# create a group for each label_value
|
||||
for key, value in service.metadata.labels:
|
||||
group_name = "label_{0}_{1}".format(key, value)
|
||||
self.inventory.add_group(group_name)
|
||||
self.inventory.add_child(group_name, service_name)
|
||||
|
||||
try:
|
||||
self.inventory.add_child(namespace_services_group, service_name)
|
||||
except AnsibleError:
|
||||
raise
|
||||
|
||||
ports = [
|
||||
{
|
||||
"name": port.name,
|
||||
"port": port.port,
|
||||
"protocol": port.protocol,
|
||||
"targetPort": port.targetPort,
|
||||
"nodePort": port.nodePort,
|
||||
}
|
||||
for port in service.spec.ports or []
|
||||
]
|
||||
|
||||
# add hostvars
|
||||
self.inventory.set_variable(service_name, "object_type", "service")
|
||||
self.inventory.set_variable(service_name, "labels", service_labels)
|
||||
self.inventory.set_variable(
|
||||
service_name, "annotations", service_annotations
|
||||
)
|
||||
self.inventory.set_variable(
|
||||
service_name, "cluster_name", service.metadata.clusterName
|
||||
)
|
||||
self.inventory.set_variable(service_name, "ports", ports)
|
||||
self.inventory.set_variable(service_name, "type", service.spec.type)
|
||||
self.inventory.set_variable(
|
||||
service_name, "self_link", service.metadata.selfLink
|
||||
)
|
||||
self.inventory.set_variable(
|
||||
service_name, "resource_version", service.metadata.resourceVersion
|
||||
)
|
||||
self.inventory.set_variable(service_name, "uid", service.metadata.uid)
|
||||
|
||||
if service.spec.externalTrafficPolicy:
|
||||
self.inventory.set_variable(
|
||||
service_name,
|
||||
"external_traffic_policy",
|
||||
service.spec.externalTrafficPolicy,
|
||||
)
|
||||
if service.spec.externalIPs:
|
||||
self.inventory.set_variable(
|
||||
service_name, "external_ips", service.spec.externalIPs
|
||||
)
|
||||
|
||||
if service.spec.externalName:
|
||||
self.inventory.set_variable(
|
||||
service_name, "external_name", service.spec.externalName
|
||||
)
|
||||
|
||||
if service.spec.healthCheckNodePort:
|
||||
self.inventory.set_variable(
|
||||
service_name,
|
||||
"health_check_node_port",
|
||||
service.spec.healthCheckNodePort,
|
||||
)
|
||||
if service.spec.loadBalancerIP:
|
||||
self.inventory.set_variable(
|
||||
service_name, "load_balancer_ip", service.spec.loadBalancerIP
|
||||
)
|
||||
if service.spec.selector:
|
||||
self.inventory.set_variable(
|
||||
service_name, "selector", dict(service.spec.selector)
|
||||
)
|
||||
|
||||
if (
|
||||
hasattr(service.status.loadBalancer, "ingress")
|
||||
and service.status.loadBalancer.ingress
|
||||
):
|
||||
load_balancer = [
|
||||
{"hostname": ingress.hostname, "ip": ingress.ip}
|
||||
for ingress in service.status.loadBalancer.ingress
|
||||
]
|
||||
self.inventory.set_variable(
|
||||
service_name, "load_balancer", load_balancer
|
||||
)
|
||||
@@ -34,6 +34,13 @@ DOCUMENTATION = """
|
||||
description:
|
||||
- Enable the helm chart inflation generator
|
||||
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:
|
||||
- "python >= 3.6"
|
||||
@@ -55,6 +62,14 @@ EXAMPLES = """
|
||||
- name: Create kubernetes resources for lookup output with `--enable-helm` set
|
||||
kubernetes.core.k8s:
|
||||
definition: "{{ lookup('kubernetes.core.kustomize', dir='/path/to/kustomization', enable_helm=True) }}"
|
||||
|
||||
- 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 = """
|
||||
@@ -72,6 +87,7 @@ RETURN = """
|
||||
key1: val1
|
||||
"""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from ansible.errors import AnsibleLookupError
|
||||
@@ -92,8 +108,10 @@ def get_binary_from_path(name, opt_dirs=None):
|
||||
return None
|
||||
|
||||
|
||||
def run_command(command):
|
||||
cmd = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
def run_command(command, environ=None):
|
||||
cmd = subprocess.Popen(
|
||||
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=environ
|
||||
)
|
||||
stdout, stderr = cmd.communicate()
|
||||
return cmd.returncode, stdout, stderr
|
||||
|
||||
@@ -107,6 +125,7 @@ class LookupModule(LookupBase):
|
||||
binary_path=None,
|
||||
opt_dirs=None,
|
||||
enable_helm=False,
|
||||
environment=None,
|
||||
**kwargs
|
||||
):
|
||||
executable_path = binary_path
|
||||
@@ -141,7 +160,21 @@ class LookupModule(LookupBase):
|
||||
if 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 err:
|
||||
raise AnsibleLookupError(
|
||||
|
||||
@@ -23,7 +23,7 @@ import base64
|
||||
import os
|
||||
from tempfile import NamedTemporaryFile
|
||||
|
||||
from ansible.module_utils._text import to_bytes, to_native, to_text
|
||||
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
|
||||
from ansible.module_utils.urls import Request
|
||||
|
||||
try:
|
||||
|
||||
@@ -23,7 +23,7 @@ from abc import ABCMeta, abstractmethod
|
||||
from select import select
|
||||
from tempfile import NamedTemporaryFile, TemporaryFile
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
|
||||
# from ansible_collections.kubernetes.core.plugins.module_utils.ansiblemodule import AnsibleModule
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from typing import Dict
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
||||
get_api_client,
|
||||
)
|
||||
|
||||
@@ -237,6 +237,27 @@ options:
|
||||
default: False
|
||||
aliases: [ skip_tls_certs_check ]
|
||||
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:
|
||||
- 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"
|
||||
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
|
||||
- name: Deploy new-relic client chart
|
||||
kubernetes.core.helm:
|
||||
@@ -505,7 +532,9 @@ def run_dep_update(module, chart_ref):
|
||||
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
|
||||
"""
|
||||
@@ -514,6 +543,17 @@ def fetch_chart_info(module, command, chart_ref, insecure_skip_tls_verify=False)
|
||||
if 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)
|
||||
|
||||
return yaml.safe_load(out)
|
||||
@@ -543,6 +583,9 @@ def deploy(
|
||||
reset_values=True,
|
||||
reset_then_reuse_values=False,
|
||||
insecure_skip_tls_verify=False,
|
||||
plain_http=False,
|
||||
take_ownership=False,
|
||||
skip_schema_validation=False,
|
||||
):
|
||||
"""
|
||||
Install/upgrade/rollback release chart
|
||||
@@ -556,6 +599,8 @@ def deploy(
|
||||
deploy_command = command + " upgrade -i" # install/upgrade
|
||||
if reset_values:
|
||||
deploy_command += " --reset-values"
|
||||
if take_ownership:
|
||||
deploy_command += " --take-ownership"
|
||||
|
||||
if reuse_values is not None:
|
||||
deploy_command += " --reuse-values=" + str(reuse_values)
|
||||
@@ -605,6 +650,9 @@ def deploy(
|
||||
else:
|
||||
deploy_command += " --insecure-skip-tls-verify"
|
||||
|
||||
if plain_http:
|
||||
deploy_command += " --plain-http"
|
||||
|
||||
if values_files:
|
||||
for value_file in values_files:
|
||||
deploy_command += " --values=" + value_file
|
||||
@@ -628,6 +676,17 @@ def deploy(
|
||||
if 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}'"
|
||||
return deploy_command
|
||||
|
||||
@@ -700,6 +759,8 @@ def helmdiff_check(
|
||||
reset_values=True,
|
||||
reset_then_reuse_values=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.
|
||||
@@ -755,6 +816,28 @@ def helmdiff_check(
|
||||
if 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)
|
||||
return (len(out.strip()) > 0, out.strip())
|
||||
|
||||
@@ -818,6 +901,9 @@ def argument_spec():
|
||||
insecure_skip_tls_verify=dict(
|
||||
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
|
||||
@@ -875,6 +961,9 @@ def main():
|
||||
reset_values = module.params.get("reset_values")
|
||||
reset_then_reuse_values = module.params.get("reset_then_reuse_values")
|
||||
insecure_skip_tls_verify = module.params.get("insecure_skip_tls_verify")
|
||||
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:
|
||||
run_repo_update(module)
|
||||
@@ -884,6 +973,33 @@ def main():
|
||||
release_status = get_release_status(module, release_name, all_status=all_status)
|
||||
|
||||
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 = {}
|
||||
if release_state == "absent" and release_status is not None:
|
||||
# skip release statuses 'uninstalled' and 'uninstalling'
|
||||
@@ -913,7 +1029,7 @@ def main():
|
||||
|
||||
# Fetch chart info to have real version and real name for chart_ref from archive, folder or url
|
||||
chart_info = fetch_chart_info(
|
||||
module, helm_cmd, chart_ref, insecure_skip_tls_verify
|
||||
module, helm_cmd, chart_ref, insecure_skip_tls_verify, plain_http
|
||||
)
|
||||
|
||||
if dependency_update:
|
||||
@@ -975,6 +1091,8 @@ def main():
|
||||
reset_values=reset_values,
|
||||
reset_then_reuse_values=reset_then_reuse_values,
|
||||
insecure_skip_tls_verify=insecure_skip_tls_verify,
|
||||
plain_http=plain_http,
|
||||
skip_schema_validation=skip_schema_validation,
|
||||
)
|
||||
changed = True
|
||||
|
||||
@@ -1002,6 +1120,8 @@ def main():
|
||||
reset_values=reset_values,
|
||||
reset_then_reuse_values=reset_then_reuse_values,
|
||||
insecure_skip_tls_verify=insecure_skip_tls_verify,
|
||||
plain_http=plain_http,
|
||||
skip_schema_validation=skip_schema_validation,
|
||||
)
|
||||
if would_change and module._diff:
|
||||
opt_result["diff"] = {"prepared": prepared}
|
||||
@@ -1039,6 +1159,9 @@ def main():
|
||||
reset_values=reset_values,
|
||||
reset_then_reuse_values=reset_then_reuse_values,
|
||||
insecure_skip_tls_verify=insecure_skip_tls_verify,
|
||||
plain_http=plain_http,
|
||||
take_ownership=take_ownership,
|
||||
skip_schema_validation=skip_schema_validation,
|
||||
)
|
||||
changed = True
|
||||
|
||||
|
||||
@@ -122,6 +122,13 @@ options:
|
||||
- The path of a helm binary to use.
|
||||
required: false
|
||||
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"""
|
||||
@@ -353,6 +360,7 @@ def main():
|
||||
chart_ssl_cert_file=dict(type="path"),
|
||||
chart_ssl_key_file=dict(type="path"),
|
||||
binary_path=dict(type="path"),
|
||||
plain_http=dict(type="bool", default=False),
|
||||
)
|
||||
module = AnsibleHelmModule(
|
||||
argument_spec=argspec,
|
||||
@@ -374,6 +382,7 @@ def main():
|
||||
chart_ca_cert="3.1.0",
|
||||
chart_ssl_cert_file="3.1.0",
|
||||
chart_ssl_key_file="3.1.0",
|
||||
plain_http="3.13.0",
|
||||
)
|
||||
|
||||
def test_version_requirement(opt):
|
||||
@@ -413,6 +422,7 @@ def main():
|
||||
skip_tls_certs_check=dict(key="insecure-skip-tls-verify"),
|
||||
chart_devel=dict(key="devel"),
|
||||
untar_chart=dict(key="untar"),
|
||||
plain_http=dict(key="plain-http"),
|
||||
)
|
||||
|
||||
for k, v in helm_flag_args.items():
|
||||
|
||||
@@ -147,6 +147,13 @@ options:
|
||||
- json
|
||||
- file
|
||||
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"""
|
||||
@@ -218,6 +225,9 @@ from ansible.module_utils.basic import missing_required_lib
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.helm import (
|
||||
AnsibleHelmModule,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
|
||||
LooseVersion,
|
||||
)
|
||||
|
||||
|
||||
def template(
|
||||
@@ -236,6 +246,7 @@ def template(
|
||||
values_files=None,
|
||||
include_crds=False,
|
||||
set_values=None,
|
||||
plain_http=False,
|
||||
):
|
||||
cmd += " template "
|
||||
|
||||
@@ -262,6 +273,9 @@ def template(
|
||||
if insecure_registry:
|
||||
cmd += " --insecure-skip-tls-verify"
|
||||
|
||||
if plain_http:
|
||||
cmd += " --plain-http"
|
||||
|
||||
if show_only:
|
||||
for template in show_only:
|
||||
cmd += " -s " + template
|
||||
@@ -307,6 +321,7 @@ def main():
|
||||
values_files=dict(type="list", default=[], elements="str"),
|
||||
update_repo_cache=dict(type="bool", default=False),
|
||||
set_values=dict(type="list", elements="dict"),
|
||||
plain_http=dict(type="bool", default=False),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
@@ -327,6 +342,7 @@ def main():
|
||||
values_files = module.params.get("values_files")
|
||||
update_repo_cache = module.params.get("update_repo_cache")
|
||||
set_values = module.params.get("set_values")
|
||||
plain_http = module.params.get("plain_http")
|
||||
|
||||
if not IMP_YAML:
|
||||
module.fail_json(msg=missing_required_lib("yaml"), exception=IMP_YAML_ERR)
|
||||
@@ -336,6 +352,15 @@ def main():
|
||||
|
||||
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:
|
||||
update_cmd = helm_cmd + " repo update"
|
||||
module.run_helm_command(update_cmd)
|
||||
@@ -360,6 +385,7 @@ def main():
|
||||
values_files=values_files,
|
||||
include_crds=include_crds,
|
||||
set_values=set_values_args,
|
||||
plain_http=plain_http,
|
||||
)
|
||||
|
||||
if not check_mode:
|
||||
|
||||
@@ -140,7 +140,7 @@ result:
|
||||
|
||||
import copy
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.ansiblemodule import (
|
||||
AnsibleModule,
|
||||
)
|
||||
|
||||
@@ -149,7 +149,7 @@ import time
|
||||
import traceback
|
||||
from datetime import datetime
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.ansiblemodule import (
|
||||
AnsibleModule,
|
||||
)
|
||||
|
||||
@@ -131,7 +131,7 @@ except ImportError:
|
||||
# ImportError are managed by the common module already.
|
||||
pass
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.ansiblemodule import (
|
||||
AnsibleModule,
|
||||
)
|
||||
|
||||
@@ -120,21 +120,6 @@ EXAMPLES = r"""
|
||||
namespace: default
|
||||
wait_sleep: 10
|
||||
wait_timeout: 360
|
||||
|
||||
- name: Wait for OpenShift bootstrap to complete
|
||||
kubernetes.core.k8s_info:
|
||||
api_version: v1
|
||||
kind: ConfigMap
|
||||
name: bootstrap
|
||||
namespace: kube-system
|
||||
register: ocp_bootstrap_status
|
||||
until: >
|
||||
ocp_bootstrap_status.resources is defined and
|
||||
(ocp_bootstrap_status.resources | length > 0) and
|
||||
(ocp_bootstrap_status.resources[0].data.status is defined) and
|
||||
(ocp_bootstrap_status.resources[0].data.status == 'complete')
|
||||
retries: 60
|
||||
delay: 15
|
||||
"""
|
||||
|
||||
RETURN = r"""
|
||||
|
||||
@@ -33,6 +33,14 @@ options:
|
||||
aliases:
|
||||
- api
|
||||
- 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:
|
||||
description:
|
||||
- Use to specify an object model.
|
||||
@@ -127,8 +135,8 @@ error:
|
||||
import copy
|
||||
import traceback
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils.basic import missing_required_lib
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.ansiblemodule import (
|
||||
AnsibleModule,
|
||||
)
|
||||
@@ -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 (
|
||||
diff_objects,
|
||||
hide_fields,
|
||||
)
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.waiter import (
|
||||
get_waiter,
|
||||
@@ -174,6 +183,7 @@ JSON_PATCH_ARGS = {
|
||||
"namespace": {"type": "str"},
|
||||
"name": {"type": "str", "required": True},
|
||||
"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")
|
||||
patch = module.params.get("patch")
|
||||
|
||||
hidden_fields = module.params.get("hidden_fields")
|
||||
wait = module.params.get("wait")
|
||||
wait_sleep = module.params.get("wait_sleep")
|
||||
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="")
|
||||
|
||||
success = True
|
||||
result = {"result": obj}
|
||||
result = {"result": hide_fields(obj, hidden_fields)}
|
||||
if wait and not module.check_mode:
|
||||
waiter = get_waiter(client, resource, condition=wait_condition)
|
||||
success, result["result"], result["duration"] = waiter.wait(
|
||||
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
|
||||
if module._diff:
|
||||
result["diff"] = diffs
|
||||
|
||||
@@ -149,7 +149,7 @@ except ImportError:
|
||||
# Handled in module setup
|
||||
pass
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.ansiblemodule import (
|
||||
AnsibleModule,
|
||||
)
|
||||
|
||||
@@ -126,7 +126,7 @@ result:
|
||||
|
||||
import copy
|
||||
|
||||
from ansible.module_utils._text import to_native
|
||||
from ansible.module_utils.common.text.converters import to_native
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.ansiblemodule import (
|
||||
AnsibleModule,
|
||||
)
|
||||
|
||||
@@ -29,3 +29,5 @@ test_namespace:
|
||||
- "helm-chart-with-space-into-name"
|
||||
- "helm-reset-then-reuse-values"
|
||||
- "helm-insecure"
|
||||
- "helm-test-take-ownership"
|
||||
- "helm-skip-schema-validation"
|
||||
|
||||
@@ -52,6 +52,12 @@
|
||||
- name: Test insecure registry flag feature
|
||||
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: Test helm version
|
||||
include_tasks: test_helm_version.yml
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
- name: Test helm reuse_values
|
||||
vars:
|
||||
helm_namespace: "{{ test_namespace[12] }}"
|
||||
helm_namespace: "{{ test_namespace[14] }}"
|
||||
chart_release_values:
|
||||
replica:
|
||||
replicaCount: 3
|
||||
|
||||
@@ -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 "$@"
|
||||
@@ -1,3 +0,0 @@
|
||||
context/target
|
||||
time=42
|
||||
k8s
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
- name: Create inventory files
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
|
||||
collections:
|
||||
- kubernetes.core
|
||||
|
||||
roles:
|
||||
- role: setup_kubeconfig
|
||||
kubeconfig_operation: 'save'
|
||||
|
||||
tasks:
|
||||
- name: Create inventory files
|
||||
copy:
|
||||
content: "{{ item.content }}"
|
||||
dest: "{{ item.path }}"
|
||||
vars:
|
||||
hostname: "{{ lookup('file', user_credentials_dir + '/host_data.txt') }}"
|
||||
test_cert_file: "{{ user_credentials_dir | realpath + '/cert_file_data.txt' }}"
|
||||
test_key_file: "{{ user_credentials_dir | realpath + '/key_file_data.txt' }}"
|
||||
test_ca_cert: "{{ user_credentials_dir | realpath + '/ssl_ca_cert_data.txt' }}"
|
||||
with_items:
|
||||
- path: "test_inventory_aliases_with_ssl_k8s.yml"
|
||||
content: |
|
||||
---
|
||||
plugin: kubernetes.core.k8s
|
||||
connections:
|
||||
- namespaces:
|
||||
- inventory
|
||||
host: "{{ hostname }}"
|
||||
cert_file: "{{ test_cert_file }}"
|
||||
key_file: "{{ test_key_file }}"
|
||||
verify_ssl: true
|
||||
ssl_ca_cert: "{{ test_ca_cert }}"
|
||||
- path: "test_inventory_aliases_no_ssl_k8s.yml"
|
||||
content: |
|
||||
---
|
||||
plugin: kubernetes.core.k8s
|
||||
connections:
|
||||
- namespaces:
|
||||
- inventory
|
||||
host: "{{ hostname }}"
|
||||
cert_file: "{{ test_cert_file }}"
|
||||
key_file: "{{ test_key_file }}"
|
||||
verify_ssl: false
|
||||
@@ -1,30 +0,0 @@
|
||||
---
|
||||
- name: Delete inventory namespace
|
||||
hosts: localhost
|
||||
connection: local
|
||||
gather_facts: true
|
||||
|
||||
roles:
|
||||
- role: setup_kubeconfig
|
||||
kubeconfig_operation: 'revert'
|
||||
|
||||
tasks:
|
||||
- name: Delete temporary files
|
||||
file:
|
||||
state: absent
|
||||
path: "{{ user_credentials_dir ~ '/' ~ item }}"
|
||||
ignore_errors: true
|
||||
with_items:
|
||||
- test_inventory_aliases_with_ssl_k8s.yml
|
||||
- test_inventory_aliases_no_ssl_k8s.yml
|
||||
- ssl_ca_cert_data.txt
|
||||
- key_file_data.txt
|
||||
- cert_file_data.txt
|
||||
- host_data.txt
|
||||
|
||||
- name: Remove inventory namespace
|
||||
k8s:
|
||||
api_version: v1
|
||||
kind: Namespace
|
||||
name: inventory
|
||||
state: absent
|
||||
@@ -1,90 +0,0 @@
|
||||
---
|
||||
- name: Converge
|
||||
hosts: localhost
|
||||
connection: local
|
||||
|
||||
collections:
|
||||
- kubernetes.core
|
||||
|
||||
vars_files:
|
||||
- vars/main.yml
|
||||
|
||||
tasks:
|
||||
- name: Delete existing namespace
|
||||
k8s:
|
||||
api_version: v1
|
||||
kind: Namespace
|
||||
name: inventory
|
||||
wait: yes
|
||||
state: absent
|
||||
|
||||
- name: Ensure namespace exists
|
||||
k8s:
|
||||
api_version: v1
|
||||
kind: Namespace
|
||||
name: inventory
|
||||
|
||||
- name: Add a deployment
|
||||
k8s:
|
||||
definition:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: inventory
|
||||
namespace: inventory
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: "{{ k8s_pod_name }}"
|
||||
template: "{{ k8s_pod_template }}"
|
||||
wait: yes
|
||||
wait_timeout: 400
|
||||
vars:
|
||||
k8s_pod_name: inventory
|
||||
k8s_pod_image: python
|
||||
k8s_pod_command:
|
||||
- python
|
||||
- '-m'
|
||||
- http.server
|
||||
k8s_pod_env:
|
||||
- name: TEST
|
||||
value: test
|
||||
|
||||
- meta: refresh_inventory
|
||||
|
||||
- name: Verify inventory and connection plugins
|
||||
hosts: namespace_inventory_pods
|
||||
gather_facts: no
|
||||
|
||||
vars:
|
||||
file_content: |
|
||||
Hello world
|
||||
|
||||
tasks:
|
||||
- name: End play if host not running (TODO should we not add these to the inventory?)
|
||||
meta: end_host
|
||||
when: pod_phase != "Running"
|
||||
|
||||
- debug: var=hostvars
|
||||
- setup:
|
||||
|
||||
- debug: var=ansible_facts
|
||||
|
||||
- name: Assert the TEST environment variable was retrieved
|
||||
assert:
|
||||
that: ansible_facts.env.TEST == 'test'
|
||||
|
||||
- name: Copy a file into the host
|
||||
copy:
|
||||
content: '{{ file_content }}'
|
||||
dest: /tmp/test_file
|
||||
|
||||
- name: Retrieve the file from the host
|
||||
slurp:
|
||||
src: /tmp/test_file
|
||||
register: slurped_file
|
||||
|
||||
- name: Assert the file content matches expectations
|
||||
assert:
|
||||
that: (slurped_file.content|b64decode) == file_content
|
||||
@@ -1,2 +0,0 @@
|
||||
---
|
||||
plugin: kubernetes.core.k8s
|
||||
@@ -1,38 +0,0 @@
|
||||
---
|
||||
k8s_pod_metadata:
|
||||
labels:
|
||||
app: "{{ k8s_pod_name }}"
|
||||
|
||||
k8s_pod_spec:
|
||||
serviceAccount: "{{ k8s_pod_service_account }}"
|
||||
containers:
|
||||
- image: "{{ k8s_pod_image }}"
|
||||
imagePullPolicy: Always
|
||||
name: "{{ k8s_pod_name }}"
|
||||
command: "{{ k8s_pod_command }}"
|
||||
readinessProbe:
|
||||
initialDelaySeconds: 15
|
||||
exec:
|
||||
command:
|
||||
- /bin/true
|
||||
resources: "{{ k8s_pod_resources }}"
|
||||
ports: "{{ k8s_pod_ports }}"
|
||||
env: "{{ k8s_pod_env }}"
|
||||
|
||||
|
||||
k8s_pod_service_account: default
|
||||
|
||||
k8s_pod_resources:
|
||||
limits:
|
||||
cpu: "100m"
|
||||
memory: "100Mi"
|
||||
|
||||
k8s_pod_command: []
|
||||
|
||||
k8s_pod_ports: []
|
||||
|
||||
k8s_pod_env: []
|
||||
|
||||
k8s_pod_template:
|
||||
metadata: "{{ k8s_pod_metadata }}"
|
||||
spec: "{{ k8s_pod_spec }}"
|
||||
@@ -1,30 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eux
|
||||
|
||||
export ANSIBLE_ROLES_PATH="../"
|
||||
USER_CREDENTIALS_DIR=$(pwd)
|
||||
|
||||
ansible-playbook playbooks/delete_resources.yml -e "user_credentials_dir=${USER_CREDENTIALS_DIR}" "$@"
|
||||
|
||||
{
|
||||
export ANSIBLE_CALLBACKS_ENABLED=profile_tasks
|
||||
export ANSIBLE_INVENTORY_ENABLED=kubernetes.core.k8s,yaml
|
||||
export ANSIBLE_PYTHON_INTERPRETER=auto_silent
|
||||
|
||||
ansible-playbook playbooks/play.yml -i playbooks/test.inventory_k8s.yml "$@" &&
|
||||
|
||||
ansible-playbook playbooks/create_resources.yml -e "user_credentials_dir=${USER_CREDENTIALS_DIR}" "$@" &&
|
||||
|
||||
ansible-inventory -i playbooks/test_inventory_aliases_with_ssl_k8s.yml --list "$@" &&
|
||||
|
||||
ansible-inventory -i playbooks/test_inventory_aliases_no_ssl_k8s.yml --list "$@" &&
|
||||
|
||||
unset ANSIBLE_INVENTORY_ENABLED &&
|
||||
|
||||
ansible-playbook playbooks/delete_resources.yml -e "user_credentials_dir=${USER_CREDENTIALS_DIR}" "$@"
|
||||
|
||||
} || {
|
||||
ansible-playbook playbooks/delete_resources.yml -e "user_credentials_dir=${USER_CREDENTIALS_DIR}" "$@"
|
||||
exit 1
|
||||
}
|
||||
@@ -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:
|
||||
- containerPort: 80
|
||||
|
||||
|
||||
- name: Crash the existing deployment
|
||||
k8s:
|
||||
state: present
|
||||
@@ -228,7 +227,7 @@
|
||||
hostPath:
|
||||
path: /var/lib/docker/containers
|
||||
register: crash
|
||||
ignore_errors: true
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Assert that the Daemonset failed
|
||||
assert:
|
||||
|
||||
@@ -94,6 +94,52 @@
|
||||
namespace: "{{ kustomize_ns }}"
|
||||
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:
|
||||
- name: Delete namespace
|
||||
k8s:
|
||||
@@ -105,4 +151,11 @@
|
||||
- name: Delete temporary directory
|
||||
file:
|
||||
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
|
||||
|
||||
@@ -31,4 +31,4 @@ plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
||||
tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip
|
||||
tests/integration/targets/helm_registry_auth/tasks/main.yaml yamllint!skip
|
||||
tests/integration/targets/helm_diff/files/test-chart-deployment-time/templates/configmap.yaml yamllint!skip
|
||||
tests/integration/targets/helm_diff/files/test-chart-deployment-time/templates/configmap.yaml yamllint!skip
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
plugins/module_utils/client/discovery.py import-3.11!skip
|
||||
plugins/module_utils/client/discovery.py import-3.12!skip
|
||||
plugins/module_utils/client/discovery.py import-3.13!skip
|
||||
plugins/module_utils/client/discovery.py import-3.14!skip
|
||||
plugins/module_utils/client/resource.py import-3.11!skip
|
||||
plugins/module_utils/client/resource.py import-3.12!skip
|
||||
plugins/module_utils/client/resource.py import-3.13!skip
|
||||
plugins/module_utils/client/resource.py import-3.14!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.11!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.12!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.13!skip
|
||||
plugins/module_utils/k8sdynamicclient.py import-3.14!skip
|
||||
plugins/module_utils/version.py pylint!skip
|
||||
plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/k8s_scale.py validate-modules:parameter-type-not-in-doc
|
||||
plugins/modules/k8s_service.py validate-modules:parameter-type-not-in-doc
|
||||
tests/unit/module_utils/fixtures/clusteroperator.yml yamllint!skip
|
||||
tests/unit/module_utils/fixtures/definitions.yml yamllint!skip
|
||||
tests/unit/module_utils/fixtures/deployments.yml yamllint!skip
|
||||
tests/integration/targets/k8s_delete/files/deployments.yaml yamllint!skip
|
||||
tests/unit/module_utils/fixtures/pods.yml yamllint!skip
|
||||
tests/integration/targets/helm/files/appversionless-chart-v2/templates/configmap.yaml yamllint!skip
|
||||
tests/integration/targets/helm/files/appversionless-chart/templates/configmap.yaml yamllint!skip
|
||||
tests/integration/targets/helm/files/test-chart-v2/templates/configmap.yaml yamllint!skip
|
||||
tests/integration/targets/helm/files/test-chart/templates/configmap.yaml yamllint!skip
|
||||
tests/integration/targets/helm_diff/files/test-chart/templates/configmap.yaml yamllint!skip
|
||||
tests/integration/targets/k8s_scale/files/deployment.yaml yamllint!skip
|
||||
plugins/modules/k8s.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_scale.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
||||
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
||||
tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip
|
||||
tests/integration/targets/helm_diff/files/test-chart-deployment-time/templates/configmap.yaml yamllint!skip
|
||||
plugins/modules/helm.py validate-modules:bad-return-value-key
|
||||
plugins/modules/helm_info.py validate-modules:bad-return-value-key
|
||||
@@ -8,8 +8,8 @@ from io import BytesIO
|
||||
|
||||
import ansible.module_utils.basic
|
||||
import pytest
|
||||
from ansible.module_utils._text import to_bytes
|
||||
from ansible.module_utils.common._collections_compat import MutableMapping
|
||||
from ansible.module_utils.common.text.converters import to_bytes
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
Reference in New Issue
Block a user