Compare commits

44 Commits
6.0.0 ... 6.4.0

Author SHA1 Message Date
Bianca Henderson
90bc4c4b3b Release prep for 6.4.0 (#1101)
SUMMARY

Prep kubernetes.core 6.4.0 release

COMPONENT NAME

Multiple

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
Reviewed-by: Yuriy Novostavskiy <yuriy@novostavskiy.kyiv.ua>
Reviewed-by: Bikouo Aubin
Reviewed-by: Hannah DeFazio <h2defazio@gmail.com>
2026-04-22 21:04:10 +00:00
patchback[bot]
1590c6a4cc Update URL reference in integration-test CI file (#1112) (#1114)
(cherry picked from commit 210467b26d)

Co-authored-by: Bianca Henderson <bianca@redhat.com>
2026-04-22 14:14:06 -04:00
patchback[bot]
76eccacab6 ci: conditionally test turbo mode and cloud.common (#1109) (#1111)
The cloud.common collection is incompatible with ansible-core >= 2.19.0.
With the current testing matrix using Python 3.12 and the ansible
milestone (currently 2.22), this incompatibility causes integration
tests to fail.

Instead of completely removing turbo mode from the testing matrix, this
commit adds ansible-core 2.18 to the matrix and excludes the combination
of the ansible milestone and turbo mode. The checkout and installation
of the cloud.common collection are now conditionally executed only when
turbo mode is enabled.

(cherry picked from commit 11f619b69e)

Co-authored-by: Yuriy Novostavskiy <yuriy@novostavskiy.kiev.ua>
2026-04-21 14:37:48 -04:00
patchback[bot]
620abbac26 trivial(doc): post #1090 cosmetic update (#1097) (#1107)
SUMMARY
Name of the Helm plays in the integration test framework test updated to reflect the actual version of Helm (addressed comments #1090 (review))
Updated documentation for the modules updated in the PR with the https://github.com/ansible-network/collection_prep, as per CONTRIBUTING.md
ISSUE TYPE

Docs Pull Request

COMPONENT NAME

tests/integration/targets/helm_v3_*/play.yaml
docs/kubernetes.core.helm*.rst

ADDITIONAL INFORMATION
Only cosmetic changes in this PR, so the label skip-changelog is suggested

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
(cherry picked from commit 16e92a20e8)

Co-authored-by: Yuriy Novostavskiy <yuriy@novostavskiy.kyiv.ua>
2026-04-21 11:31:11 +02:00
patchback[bot]
66a820e03a Add sanity test ignores for ansible-core 2.22 (#1102) (#1106)
The `devel` and `milestone` branches for ansible-core have been bumped to
`2.22.0.dev0` as the `stable-2.21` branch was created. Testing against `devel`
and `milestone` now uses 2.22, which requires creation of the
`tests/sanity/ignore-2.22.txt` file in all maintained collection branches.

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch ignore-2.22
# Changes to be committed:
#	new file:   tests/sanity/ignore-2.22.txt
#

(cherry picked from commit 58f8f2e6e9)

Co-authored-by: Yuriy Novostavskiy <yuriy@novostavskiy.kiev.ua>
2026-04-20 18:34:35 -04:00
patchback[bot]
a3f2438e9d Ensure compatibility with Helm v4 for the collection (#1090) (#1096)
This is a backport of PR #1090 as merged into main (e6076e5).
SUMMARY

Ensure compatibility with Helm v4 for modules helm_plugin and helm_plugin_info
Partially addresses #1038

ISSUE TYPE


Feature Pull Request

COMPONENT NAME

helm_plugin
helm_plugin_info
helm_info
helm_pull
helm_registry_auth
helm
helm_template

Reviewed-by: Bikouo Aubin
Reviewed-by: Matthew Johnson
2026-03-17 15:03:02 +00:00
patchback[bot]
0709ea31c9 Support take_ownership parameter in helm installation (#1034) (#1092)
This is a backport of PR #1034 as merged into main (42acb4f).
SUMMARY
Adds support for the take_ownership for initial release installation operations.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME
plugins/modules/helm.py
ADDITIONAL INFORMATION
I recently had to migrate a namespace k8s from flat manifest installation into helm a release.
I was so glad to see the take_ownership feature but realized that it work only after first installation of the release.
Seeing no reason to denied this use case i suggest this very simple changes.
To reproduce it:

Create a new namespace in any cluster.
Create a secret
Install any helm chart that deploy the same secret using take_ownership: true.
2026-02-19 16:40:12 +00:00
patchback[bot]
44ab1fc478 Add check_mode support for k8s_drain module (#1086) (#1091)
This is a backport of PR #1086 as merged into main (d239adb).
SUMMARY

Closes #1037

added support for check_mode
Converted warnings into informational display when user has explicitly requested to delete daemontset-managed pods, unmanaged pods or pods with local storage


ISSUE TYPE


Feature Pull Request

COMPONENT NAME

k8s_drain

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2026-02-16 20:35:22 +00:00
Bianca Henderson
80c33c5573 Prep 6.3.0 release (#1084)
SUMMARY

Prep kubernetes.core 6.3.0 release

COMPONENT NAME

Multiple

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
Reviewed-by: Bikouo Aubin
Reviewed-by: Mike Graves <mgraves@redhat.com>
Reviewed-by: Alina Buzachis
Reviewed-by: Yuriy Novostavskiy <yuriy@novostavskiy.kyiv.ua>
Reviewed-by: Rahmanim Benny <brahmani@redhat.com>
2026-02-03 17:03:41 +00:00
patchback[bot]
73dc94be68 Add idempotency to helm_pull module (#1055) (#1080)
This is a backport of PR #1055 as merged into main (34beacf).
SUMMARY
This PR implements idempotency for the helm_pull module, addressing issue #889.

New force parameter with defaults to False.
implemented chart_exists() function
checks chart existence before downloading, returns changed=False when chart exists

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME
helm_pull
ADDITIONAL INFORMATION
Force parameter added for backward compatibility and edge cases.
Implemented with the partial support of GitHub Copilot with Claude Sonnet 4.5 model

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2026-01-29 18:22:52 +00:00
patchback[bot]
1bc65230bb Fix incorrect assertion in helm_pull integration test (#1077) (#1079)
This is a backport of PR #1077 as merged into main (23b6cec).
SUMMARY

The error message emitted for incorrect helm version has changed since the merge of #1039. This PR updates the related assertion in the helm_pull integration test

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2026-01-29 17:44:05 +00:00
patchback[bot]
91427a5b6a chore(CI): prevent patchback bot from labeling new PRs (#1062) (#1064)
This is a backport of PR #1062 as merged into main (987c029).
SUMMARY
Currently, the patchback bot creates PRs with cherry-picks of PRs that are labeled with stable-* label, and this PR (as any new PR) gets labeled as needs_triage. This is unnecessary as it intentional PR created by the CI job.
This pull request introduces a small update to ensure that the workflow only runs if the pull request is not created by the patchback[bot] user to avoid unnecessary labels.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME
.github/workflows/label-new-prs.yaml
ADDITIONAL INFORMATION
No changelog is required 

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2026-01-29 16:00:40 +00:00
patchback[bot]
1d1a23b1ab Replace passing `warnings to exit_json with AnsibleModule.warn` for the few modules (#1033) (#1073)
This is a backport of PR #1033 as merged into main (3e32c12).
SUMMARY
Using exit_json or fail_json for warnings is deprecated in ansible-core>=2.19.0 and will be removed in ansible-core>=2.23.0
Tested with ansible-core 2.19.3 as the latest released version at the time of the start of this PR and with 2.16.0 as the lowest version supported by kubernetes.core 6.x
Resolves: #1031
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME
k8s_drain
k8s_rollback
k8s_scale
ADDITIONAL INFORMATION
The initial version of this PR covers only the module k8s_drain, with the following commits extended to k8s_rollback
k8s_scale

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
Reviewed-by: Mike Graves <mgraves@redhat.com>
2026-01-26 21:14:44 +00:00
patchback[bot]
6edc84678d Limit compatibility to Helm =>v3.0.0,<4.0.0 (#1039) (#1071)
This is a backport of PR #1039 as merged into main (13791ec).
SUMMARY
Helm v4 is a major version with backward-incompatible changes, including to the flags and output of the Helm CLI and to the SDK. This version is currently not supported in the kubernetes.core. This PR is related to #1038 and is a short-term solution to mark compatibility explicitly
ISSUE TYPE

Bugfix Pull Request
Docs Pull Request

COMPONENT NAME

helm
helm_template
helm_info
helm_repository
helm_pull
helm_registry_auth
helm_plugin
helm_plugin_info

ADDITIONAL INFORMATION
Added `validate_helm_version()`` method to AnsibleHelmModule that enforces version constraint >=3.0.0,<4.0.0.
Fails fast with clear error message: "Helm version must be >=3.0.0,<4.0.0, current version is {version}"
Some modules (i.e. helm_registry_auth) technically is compatible with Helm v4, but validation was added to all helm modules.
Partially coauthored by GitHub Copilot with Claude Sonnet 4 model.
Addresses issue #1038

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
Reviewed-by: Mike Graves <mgraves@redhat.com>
2026-01-26 19:47:46 +00:00
patchback[bot]
66bd8620e4 Replace deprecated ansible.module_utils._text imports (#1053) (#1070)
This is a backport of PR #1053 as merged into main (452fb3d).
SUMMARY
Importing from ansible.module_utils._text is deprecated in ansible-core 2.20 and removed in 2.24. All imports of to_bytes, to_native, and to_text now use ansible.module_utils.common.text.converters.
Before:
from ansible.module_utils._text import to_bytes, to_native, to_text

After:
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME
plugins/module_utils/common.py
plugins/action/k8s_info.py
plugins/connection/kubectl.py
plugins/module_utils/{copy.py, k8s/runner.py}
plugins/modules/{k8s_cp.py, k8s_drain.py, k8s_exec.py, k8s_json_patch.py, k8s_scale.py, k8s_taint.py}
ADDITIONAL INFORMATION
It's not an actual Bugfix, more a lifecycle management to ensure compatibility with future Ansible versions.
Tested with ansible-core 2.20 to ensure no deprecation warnings are raised and with ansible-core 2.16 to ensure backward compatibility.
Patrially coauthored-by: GitHub Copilot with Claude Code 4.5 model.
Addresses issue #1052.

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2026-01-26 15:22:45 +00:00
patchback[bot]
94b43dc582 Fix K8S_AUTH_VERIFY_SSL environment value handling in kubectl connection plugin (#1049) (#1069)
This is a backport of PR #1049 as merged into main (12abc9b).
SUMMARY
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 instead of being properly converted to a boolean.
The option key name is validate_certs, which does NOT end with "verify_ssl", so the original condition key.endswith("verify_ssl") at line 327 failed. This caused the code to fall through to the else block which added the value as separate
arguments: ["--insecure-skip-tls-verify", "true"], making "true" appear as a kubectl command.
Fixes #1021
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME
kubernetes.core.kubectl
ADDITIONAL INFORMATION
Changes Made

Changed condition from key.endswith("verify_ssl") to key == "validate_certs"
Added import of boolean function from ansible.module_utils.parsing.convert_bool
Added proper boolean conversion using boolean(self.get_option(key), strict=False)

Partially used LLM (GitHub Copilot with Claude Sonnet 4).
Before Fix
K8S_AUTH_VERIFY_SSL=true
Command: ['/usr/bin/kubectl', '--insecure-skip-tls-verify', 'true', 'exec', ...]

                                                            ^^^^^ treated as kubectl command (BUG!)

After Fix
K8S_AUTH_VERIFY_SSL=true
Command: ['/usr/bin/kubectl', '--insecure-skip-tls-verify=false', 'exec', ...]
                                                           ^^^^^ properly converted (FIXED!)

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2026-01-23 20:24:44 +00:00
patchback[bot]
3c4f9cee60 chore(doc): update typos (#1059) (#1061)
This is a backport of PR #1059 as merged into main (6c00f7c).
SUMMARY
This trivial documentation-only pull request correcting a few errors in README.md.

Documentation corrections:

Fixed a broken Markdown link for the GitHub repository in the support request section.
Corrected the reference from LICENCE to LICENSE to match the actual file name.



ISSUE TYPE

Docs Pull Request

COMPONENT NAME
README.md
ADDITIONAL INFORMATION
Trivial documentation-only change, no changelog is required.

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2026-01-15 21:30:22 +00:00
patchback[bot]
a54b4a13b6 address sanity issues (#1056) (#1058)
This is a backport of PR #1056 as merged into main (bd1cacc).
SUMMARY


helm/helm_info - Deprecate some parameters and add new ones to resolve sanity issues.
k8s - the return block doc is not aligned with what the module returns


ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME

helm, helm_info, k8s
Fixes: #1046

Reviewed-by: Bikouo Aubin
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2026-01-14 17:08:35 +00:00
patchback[bot]
e16b3c46b0 Add new workflow to label prs with needs_triage (#1045) (#1048)
This is a backport of PR #1045 as merged into main (9cfa903).
SUMMARY
This pr adds a new workflow for labeling new and reopened prs that are not marked as draft. The needs_triage label will be removed if the pr is marked as draft during development and re-added once the pr is marked as ready for review.
After consulting with the team, we decided to label prs in a new workflow to allow for the prs and issues to have different labels in the future.
ACA-2362
ISSUE TYPE

Feature Pull Request

COMPONENT NAME
github workflow
Reported CI Issues
Sanity tests: #1046

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2025-12-18 14:29:05 +00:00
patchback[bot]
bc60523372 Add 2.21 ignore file for sanity tests (#1032) (#1036)
SUMMARY

Resolves #1027

Reviewed-by: Yuriy Novostavskiy <yuriy@novostavskiy.kyiv.ua>
Reviewed-by: GomathiselviS <gomathiselvi@gmail.com>
(cherry picked from commit 1c16a2d2b5)

Co-authored-by: Bianca Henderson <bianca@redhat.com>
2025-10-24 09:28:46 -04:00
patchback[bot]
64f3f07c5a Extend k8s action group (#992) (#1026)
This is a backport of PR #992 as merged into main (798f549).
SUMMARY


Add all k8s_* modules to the action group in order to esaily set kubeconfig parameter
ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME

meta
ADDITIONAL INFORMATION

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2025-10-14 20:47:03 +00:00
patchback[bot]
d6492b66d9 Selectively redact sensitive kubeconfig data from logs (#1014) (#1024)
This is a backport of PR #1014 as merged into main (4fa3648).
SUMMARY

Resolves #782

ISSUE TYPE


Bugfix Pull Request

ADDITIONAL INFORMATION


The proper redaction of kubeconfig data can be seen by running this example playbook with verbosity of -vvv against the code in this PR.
Prior to these changes, all info was redacted (as shown in the example below):
ok: [local] => {
    "changed": false,
    "invocation": {
        "module_args": {
            "api_key": null,
            "binary_path": null,
            "ca_cert": null,
            "context": null,
            "get_all_values": false,
            "host": null,
            "kubeconfig": {
                "apiVersion": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
                "clusters": [
                    {
                        "cluster": {
                            "insecure-skip-tls-verify": true,
                            "server": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"
                        },
                        "name": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"
                    },
                    {
                        "cluster": {
                            "certificate-authority-data": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
                            "server": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"
                        },
                        "name": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"
                    },
                    {
                        "cluster": {
                            "certificate-authority": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
                            "extensions": [
                                {
                                    "extension": {
                                        "last-update": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
                                        "provider": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
                                        "version": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"
                                    },
                                    "name": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"
                                }
                            ],
                            "server": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"
                        },
                        "name": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"
                    }
                ],
                "contexts": [
                    {
                        "context": {
                            "cluster": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
                            "user": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"
                        },
                        "name": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"
                    },
                    {
                        "context": {
                            "cluster": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
                            "user": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"
                        },
                        "name": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"
                    },
[output shortened]

With the changes in this PR, only sensitive data is redacted:
ok: [local] => {
    "changed": false,
    "invocation": {
        "module_args": {
            "api_key": null,
            "binary_path": null,
            "ca_cert": null,
            "context": null,
            "get_all_values": false,
            "host": null,
            "kubeconfig": {
                "apiVersion": "v1",
                "clusters": [
                    {
                        "cluster": {
                            "insecure-skip-tls-verify": true,
                            "server": "<server address>"
                        },
                        "name": "exercise"
                    },
                    {
                        "cluster": {
                            "certificate-authority-data": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
                            "server": "<server address>"
                        },
                        "name": "kind-drain-test"
                    },
                    {
                        "cluster": {
                            "certificate-authority": "<path to .crt>",
                            "extensions": [
                                {
                                    "extension": {
                                        "last-update": "Tue, 07 Oct 2025 11:25:54 EDT",
                                        "provider": "minikube.sigs.k8s.io",
                                        "version": "v1.35.0"
                                    },
                                    "name": "cluster_info"
                                }
                            ],
                            "server": "<server address>"
                        },
                        "name": "minikube"
                    }
                ],
                "contexts": [
                    {
                        "context": {
                            "cluster": "exercise-pod",
                            "user": "bianca"
                        },
                        "name": "exercise"
                    },
                    {
                        "context": {
                            "cluster": "kind-drain-test",
                            "user": "kind-drain-test"
                        },
                        "name": "kind-drain-test"
                    },
[output shortened]

Reviewed-by: GomathiselviS <gomathiselvi@gmail.com>
2025-10-14 19:16:05 +00:00
patchback[bot]
4d5388ddf8 775 document proxy configurations (#1018) (#1020)
This is a backport of PR #1018 as merged into main (ae624cf).
SUMMARY
Added documentation for no_proxy, proxy, and proxy_headers parameters that were missing from the k8s lookup plugin. These parameters are already implemented in the codebase but were not documented.
no_proxy: Comma separated list of hosts that shouldn't use proxy
proxy: HTTP proxy URL for connections
proxy_headers: Dictionary of proxy headers with suboptions for proxy_basic_auth, basic_auth, and user_agent
Fixes #775
ISSUE TYPE

Docs Pull Request

COMPONENT NAME
k8s lookup
Additional comment
This is a reissue of #993, which was lost during the latest release due to me PR incorrectly from my fork's main branch. Linter errors on the previous PR should already be resolved.
This had the backport-5, backport-6 and skip-changelog labels.

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2025-10-10 17:30:10 +00:00
Bianca Henderson
6dadd06252 Add missing changelog fragments from 5.4.0 and 5.4.1 releases (#1015)
Reviewed-by: Mandar Kulkarni <mandar242@gmail.com>
Reviewed-by: Yuriy Novostavskiy <yuriy@novostavskiy.kyiv.ua>
2025-10-07 20:38:26 +00:00
Bianca Henderson
69dc7d5c5d Prep 6.2.0 release (#1011)
SUMMARY

Prep kubernetes.core 6.2.0 release

COMPONENT NAME
Multiple

Reviewed-by: Bikouo Aubin
Reviewed-by: Yuriy Novostavskiy <yuriy@novostavskiy.kyiv.ua>
Reviewed-by: Alina Buzachis
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
Reviewed-by: Mandar Kulkarni <mandar242@gmail.com>
2025-10-07 18:18:54 +00:00
patchback[bot]
2fa1c2c6e5 Add support of local environment variables in kustomize lookup plugin (#786) (#1010)
This is a backport of PR #786 as merged into main (87344b9).
SUMMARY
kustomize doesn't support an environment that makes it impossible to use HTTP_PROXY or provide some templatized parameters.
This PR is the result of the issue #783
ISSUE TYPE

Feature Pull Request

COMPONENT NAME
kubernetes.core.kustomize lookup plugin

Reviewed-by: Bikouo Aubin
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2025-10-03 14:34:41 +00:00
patchback[bot]
f2623dd3cf update doc following #971 (#1006) (#1008)
This is a backport of PR #1006 as merged into main (200d64f).
SUMMARY
In the PR #971, support for copying files to initContainers, and this change includes a minor update for DOCUMENTATION for the k8s_cp module; however, docs/kubernetes.core.k8s_cp_module.rst wasn't updated, and it's a trivial change following the Updating documentation section of the CONTRIBUTING.md
ISSUE TYPE

Docs Pull Request

COMPONENT NAME
docs/kubernetes.core.k8s_cp_module.rst
ADDITIONAL INFORMATION
As it is a trivial change and related to #971, I didn't created a chnagelog fragment and suggest adding skip-changelog label.
To be backported to stable-5 and stable-6

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2025-10-02 20:11:20 +00:00
patchback[bot]
8772d8c997 Add the PR head as reference to the checkout action of the splitter job. (#981) (#1005)
This is a backport of PR #981 as merged into main (ec35c74).
SUMMARY
During the workflow checks of one of my previous pull requests, I ran into an error as result of a new integration test that was added in the main branch but which was not present in my pull request (https://github.com/ansible-collections/kubernetes.core/actions/runs/16787189478/job/47540604109). I'd find out that the reference for the repository checkout for the splitter job was not set and therefor it referenced to the main branch.
With this change, the head of the pull request is used as reference for the repository checkout action, in the splitter job. This way it will not fail when someone creates a PR that doesn't have newly added integration tests that were added to the main branch in the meantime. It also adds that newly added integration tests will be tested during the PR workflow checks already.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME
bugfix in the workflow
ADDITIONAL INFORMATION
n/a

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2025-10-02 19:12:05 +00:00
patchback[bot]
a32108f64f Added support for copying files to init Containers. (#971) (#1003)
This is a backport of PR #971 as merged into main (027700c).
SUMMARY
Was going trough the list with issues and found 958; which seemed a quick fix.
What I fixed with with this PR:

Added support for copying files to init containers.
Fixed the format message when an exec is failing for a pod (the order was wrong).
Added a check if the container that you try to run copy for is started.

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME
copy.py module
ADDITIONAL INFORMATION
Some testing.
Verify that the pod does not exist:
kubectl -n default get pod/yorick
Output:
Error from server (NotFound): pods "yorick" not found

Run the playbook to create the file, create the deployment, wait for the init container to be ready, copy the created file to the init container, cat the copied file (using kubernetes.core.k8s_exec) that is now in the init container and try to copy the created file to the (not started) container (which fails - to see the new error message for it):
cat << EOF | ansible-playbook /dev/stdin
- hosts: localhost
  gather_facts: False
  tasks:

  - ansible.builtin.copy:
      content: |
        Hi there
      dest: /tmp/yorick.txt

  - name: Deploy pod with initContainer with an unlimited while loop
    kubernetes.core.k8s:
      kubeconfig: "~/.kube/config"
      definition:
        apiVersion: v1
        kind: Pod
        metadata:
          name: "yorick"
          namespace: "default"
        spec:
          initContainers:
            - name: "yorick-init"
              image: busybox:latest
              command: ["/bin/sh"]
              args:
                - "-c"
                - |
                  echo "Init container started, waiting for file..."
                  # Wait for the file to be copied
                  while :;do
                    echo "Waiting for file"
                    sleep 5
                  done
                  echo "File received! Init container completing..."
          containers:
            - name: "yorick-container"
              image: busybox:latest
              command: ["/bin/sh"]
              args:
                - "-c"
                - |
                  # Keep container running for testing
                  sleep 300

  - kubernetes.core.k8s_info:
      kubeconfig: "~/.kube/config"
      api_version: v1
      kind: Pod
      name: "yorick"
      namespace: "default"
    register: pod_status
    until: >-
      pod_status.resources|length > 0
      and 'initContainerStatuses' in pod_status.resources.0.status
      and pod_status.resources.0.status.initContainerStatuses|length > 0
      and pod_status.resources.0.status.initContainerStatuses.0.started|bool

  - name: Copy /tmp/yorick.txt to the yorick-init init container
    kubernetes.core.k8s_cp:
      kubeconfig: "~/.kube/config"
      namespace: default
      pod: yorick
      remote_path: /tmp/yorick.txt
      local_path: /tmp/yorick.txt
      container: yorick-init

  - name: Execute a command
    kubernetes.core.k8s_exec:
      kubeconfig: "~/.kube/config"
      namespace: default
      pod: yorick
      container: yorick-init
      command: cat /tmp/yorick.txt
    register: exec_out

  - ansible.builtin.debug:
      var: exec_out.stdout

  - name: Try to copy /tmp/yorick.txt to the yorick-container container
    kubernetes.core.k8s_cp:
      kubeconfig: "~/.kube/config"
      namespace: default
      pod: yorick
      remote_path: /tmp/yorick.txt
      local_path: /tmp/yorick.txt
      container: yorick-container
EOF
Output:
PLAY [localhost] ********************************************************************************************************************************************************************

TASK [ansible.builtin.copy] *********************************************************************************************************************************************************
Thursday 31 July 2025  02:01:21 +0200 (0:00:00.016)       0:00:00.016 *********
ok: [localhost]

TASK [Deploy pod with initContainer with an unlimited while loop] *******************************************************************************************************************
Thursday 31 July 2025  02:01:21 +0200 (0:00:00.788)       0:00:00.804 *********
changed: [localhost]

TASK [kubernetes.core.k8s_info] *****************************************************************************************************************************************************
Thursday 31 July 2025  02:01:25 +0200 (0:00:03.963)       0:00:04.768 *********
FAILED - RETRYING: [localhost]: kubernetes.core.k8s_info (3 retries left).
ok: [localhost]

TASK [Copy /tmp/yorick.txt to the yorick-init init container] ***********************************************************************************************************************
Thursday 31 July 2025  02:01:32 +0200 (0:00:06.598)       0:00:11.366 *********
changed: [localhost]

TASK [Execute a command] ************************************************************************************************************************************************************
Thursday 31 July 2025  02:01:39 +0200 (0:00:07.017)       0:00:18.383 *********
changed: [localhost]

TASK [ansible.builtin.debug] ********************************************************************************************************************************************************
Thursday 31 July 2025  02:01:40 +0200 (0:00:00.644)       0:00:19.028 *********
ok: [localhost] => {
    "exec_out.stdout": "Hi there\n"
}

TASK [Try to copy /tmp/yorick.txt to the yorick-container container] ****************************************************************************************************************
Thursday 31 July 2025  02:01:40 +0200 (0:00:00.021)       0:00:19.050 *********
fatal: [localhost]: FAILED! => {
    "changed": false
}

MSG:

Pod container yorick-container is not started

PLAY RECAP **************************************************************************************************************************************************************************
localhost                  : ok=6    changed=3    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

Playbook run took 0 days, 0 hours, 0 minutes, 21 seconds

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2025-09-25 15:07:52 +00:00
patchback[bot]
365e5e9159 Add support for skip-schema-validation in helm module (#995) (#1001)
This is a backport of PR #995 as merged into main (da93cce).
SUMMARY
This pull request adds support for a new skip_schema_validation option to the helm module, allowing users to disable JSON schema validation for Helm charts and values (requires helm >= 3.16.0).
ISSUE TYPE

Feature Pull Request

COMPONENT NAME
helm
ADDITIONAL INFORMATION
Added the skip_schema_validation boolean parameter to the helm module, allowing users to disable JSON schema validation for charts and values. This option is only available with Helm versions >= 3.16.0, and an appropriate error is raised for older versions.
Added integration tests to verify the behavior of the skip_schema_validation option, including cases for both supported and unsupported Helm versions.
Closes #994

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2025-09-24 20:29:07 +00:00
patchback[bot]
448a68da3d Changelog fixes (#989) (#990)
This is a backport of PR #989 as merged into main (6158300).
SUMMARY

Changelog fixes

ISSUE TYPE


Docs Pull Request

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
Reviewed-by: Chyna Sanders
2025-09-22 20:14:29 +00:00
patchback[bot]
46acab9c4c [CI Fix] Remove ansible.module_utils.six imports (#998) (#1000)
This is a backport of PR #998 as merged into main (448d3fe).
SUMMARY
This PR is essentially attempting Option B from issue #996 (Option A is implemented here); this code update accounts for the recent merge of sanity: warn on ansible.module_utils.six imports #85651.

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
Reviewed-by: Mandar Kulkarni <mandar242@gmail.com>
2025-09-22 16:49:02 +00:00
Bianca Henderson
fdb77182c8 Update/correct stable-6 changelog (#987)
SUMMARY
A part of the changelog referring to reverted changes was left in; this PR updates the changelog files to accurately reflect the state of stable-6/6.1.0 release.

Reviewed-by: Yuriy Novostavskiy
Reviewed-by: Alina Buzachis
2025-08-13 08:34:52 +00:00
Alina Buzachis
fa3d94f793 Prep kubernetes.core 6.1.0 (#977)
SUMMARY


ISSUE TYPE


Bugfix Pull Request
Docs Pull Request
Feature Pull Request
New Module Pull Request

COMPONENT NAME

ADDITIONAL INFORMATION

Reviewed-by: Yuriy Novostavskiy
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
Reviewed-by: GomathiselviS <gomathiselvi@gmail.com>
2025-08-12 18:25:31 +00:00
patchback[bot]
9ec27cf37c CI fix for 976 (#982) (#985)
This is a backport of PR #982 as merged into main (a861079).
SUMMARY
Exclude plugins/connection/kubectl.py from ansible-lint, as this file contains only examples that is simplificated and may not be accordingally to linter rules.
resolves #976
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME
CI
ADDITIONAL INFORMATION

Reviewed-by: Alina Buzachis
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2025-08-12 15:59:34 +00:00
Bianca Henderson
10cb241256 Reapply "Remove kubeconfig value from module invocation log (#826)" (#899) (#966) (#979)
This reverts commit 1d962fb from stable-6 (i.e., reapplies the changes from #966); this is a temporary fix for #782 as it will re-introduce #870.

Reviewed-by: Alina Buzachis
Reviewed-by: GomathiselviS <gomathiselvi@gmail.com>
2025-08-11 16:48:04 +00:00
patchback[bot]
92e1f581fe fix(k8s,service): Hide fields first before creating diffs (#915) (#963)
This is a backport of PR #915 as merged into main (6a0635a).
SUMMARY

By hiding fields first before creating a diff hidden fields will not be shown in the resulting diffs and therefore will also not trigger the changed condition.
The issue can only be reproduced when a mutating webhook changes the object while the kubernetes.core.k8s module is working with it.

kubevirt/kubevirt.core#145
ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME

kubernetes.core.module_utils.k8s.service
ADDITIONAL INFORMATION


Run kubernetes.core.k8s and create object with hidden fields. After run kubernetes.core.k8s again and let a webhook mutate the object that the module is working with. The module should return with changed: no.

Reviewed-by: Alina Buzachis
2025-08-04 18:03:21 +00:00
patchback[bot]
7f69aff0d6 k8s_json_patch: support the hidden_fields param (#964) (#972)
This is a backport of PR #964 as merged into main (c48778d).
SUMMARY
Add support for hidden_fields on k8s_json_patch

ISSUE TYPE

Feature Pull Request

COMPONENT NAME
k8s_json_patch
ADDITIONAL INFORMATION
Works exactly the same as k8s
Haven't pushed the doc yet, because of many changes. Will do it on a separate commit if the tests pass.
1st commit here, sorry if I forget some things.
Thanks!

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2025-08-01 18:24:39 +00:00
patchback[bot]
8c65ac066d Add support for take-ownership Helm flag (#957) (#969)
This is a backport of PR #957 as merged into main (cf3c3a9).
SUMMARY
Add support for take-ownership Helm flag added in Helm 3.17.0
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

kubernetes.core.helm

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2025-07-28 15:48:39 +00:00
patchback[bot]
1d962fb932 Revert "Remove kubeconfig value from module invocation log (#826)" (#899) (#966)
This is a backport of PR #899 as merged into main (1705ced).
This reverts commit 6efabd3.
SUMMARY

Fixes #870
A better solution is necessary to address #782. The current code makes getting manifests practically unusable. We need to revert this commit until a better solution is found.

ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME

kubeconfig

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2025-07-22 21:29:21 +00:00
patchback[bot]
27ce23aa72 Fix integration test with ansibe-core 2.20 (#951) (#960)
This is a backport of PR #951 as merged into main (f568c9d).
SUMMARY
Now that ansible-core 2.19.0rc1 has been released, ansible-core’s devel branch has been bumped from 2.19.0.dev0 to 2.20.0.dev0. This potentially requires collection CIs to be updated which rely on devel using tests/sanity/ignore-2.19.txt, for example. Also it’s now time to add stable-2.19 to CI if you relied on devel to cover 2.19 so far. Note that milestone has also been updated to 2.20.0dev0.
During testing, I noticed that the failed test tasks/test_helm_not_installed.yml due to the new error message with ansible 2.20, please find here and following comments.
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME
test/CI (tasks/test_helm_not_installed.yml)
ADDITIONAL INFORMATION
to be cherry-picked to the stable-6 and stable-5

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2025-07-15 15:34:33 +00:00
patchback[bot]
993652b581 Add more functionality coverage to k8s_rollback integration test (#950) (#956)
This is a backport of PR #950 as merged into main (94e4235).
SUMMARY

Resolves #344

This revision adds the following test coverage:

Label Selectors: Tests rollback using label selectors to target specific deployments.
No Rollout History: Tests the warning scenario when attempting to rollback a deployment with only one revision.
Unsupported Resource Types: Tests error handling when trying to rollback unsupported resources like Services.
Non-existent Resources: Tests behavior when attempting to rollback resources that don't exist.
Multiple Resource Rollback: Tests bulk rollback operations using label selectors on multiple deployments.
Return Value Validation: Comprehensive validation of the rollback_info structure and content.
Field Selectors: Tests rollback using field selectors to target specific resources.
Check Mode Validation: Additional validation of check mode behavior and return values.

COMPONENT NAME

tests/integration/targets/k8s_rollback/tasks/main.yml

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2025-07-14 14:36:29 +00:00
patchback[bot]
9bd9d22db3 Fix the integration test for helm_registry_auth with helm >= 3.18.0 and clarify idempotency. (#946) (#953)
This is a backport of PR #946 as merged into main (642eb93).
SUMMARY
Fix the integration test for helm_registry_auth with helm >= 3.18.0 and clarify idempotency.
Fixes #944
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME
helm_registry_auth
ADDITIONAL INFORMATION
Caused by the changes in helm starting from 3.18.0

Reviewed-by: Bikouo Aubin
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
2025-07-08 15:56:48 +00:00
patchback[bot]
0593426918 Add plain_http parameter to helm, helm_pull and helm_template (#934) (#949)
This is a backport of PR #934 as merged into main (775959c).
SUMMARY

This change introduces the plain_http parameter to modules that can interact with OCI registries. This in needed in cases where the OCI registry does not use SSL encryption, forcing Helm to send HTTP requests instead of HTTPS

ISSUE TYPE


Feature Pull Request

COMPONENT NAME

helm, helm_pull and helm_template
ADDITIONAL INFORMATION


This is the output when trying to use an OCI registry that is not configured to use SSL certs.

fatal: [localhost]: FAILED! => {"changed": false, "command": "/usr/local/bin/helm show chart 'oci://<http-registry>/charts/foo'", "msg": "Failure when executing Helm command. Exited 1.\nstdout: \nstderr: Error: Get \"https://<http-registry>/v2/charts/foo/tags/list\": http: server gave HTTP response to HTTPS client\n", "stderr": "Error: Get \"https://<http-registry>/v2/charts/foo/tags/list\": http: server gave HTTP response to HTTPS client\n", "stderr_lines": ["Error: Get \"https://<http-registry>/v2/charts/foo/tags/list\": http: server gave HTTP response to HTTPS client"], "stdout": "", "stdout_lines": []}

Reviewed-by: Bikouo Aubin
2025-06-12 10:53:42 +00:00
169 changed files with 5036 additions and 1980 deletions

View File

@@ -3,6 +3,7 @@ profile: production
exclude_paths:
- .ansible/
- .github/
- tests/integration
- tests/unit
- tests/sanity

View File

@@ -3,3 +3,4 @@
plugins/connection/kubectl.py no-changed-when
# false positive result
plugins/connection/kubectl.py var-naming[no-reserved]
plugins/connection/kubectl.py jinja[invalid]

View File

@@ -26,6 +26,7 @@ jobs:
with:
path: ${{ env.source_dir }}
fetch-depth: "0"
ref: ${{ github.event.pull_request.head.sha }}
- name: list changes for pull request
id: splitter
@@ -54,13 +55,14 @@ jobs:
strategy:
fail-fast: false
matrix:
ansible-version:
- milestone
# 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
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:
@@ -106,6 +108,7 @@ 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
@@ -127,6 +130,7 @@ 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

28
.github/workflows/label-new-prs.yaml vendored Normal file
View File

@@ -0,0 +1,28 @@
---
name: label new prs
on:
pull_request_target:
types:
- opened
- reopened
- converted_to_draft
- ready_for_review
jobs:
add_label:
if: github.actor != 'patchback[bot]'
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Add 'needs_triage' label if the pr is not a draft
uses: actions-ecosystem/action-add-labels@v1
if: github.event.pull_request.draft == false
with:
labels: needs_triage
- name: Remove 'needs_triage' label if the pr is a draft
uses: actions-ecosystem/action-remove-labels@v1
if: github.event.pull_request.draft == true
with:
labels: needs_triage

View File

@@ -20,4 +20,6 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: run-ansible-lint
uses: ansible/ansible-lint@v25.1.2
uses: ansible/ansible-lint@main
with:
gh_action_ref: "v25.5.0"

4
.gitignore vendored
View File

@@ -17,7 +17,11 @@ tests/integration/cloud-config-*
# Helm charts
tests/integration/*-chart-*.tgz
tests/integration/targets/*/*.tgz
# ansible-test generated file
tests/integration/inventory
tests/integration/*-*.yml
# VS Code settings
.vscode/

View File

@@ -26,3 +26,4 @@ ignore: |
.tox
.ansible
tests/output
plugins/connection/kubectl.py

View File

@@ -4,13 +4,113 @@ Kubernetes Collection Release Notes
.. contents:: Topics
v6.0.0
v6.4.0
======
Release Summary
---------------
This major release removes the deprecated ``k8s`` inventory plugin and also removes ``ansible-core<2.16`` support.
This release adds Helm v4 compatibility across the Helm modules and improves ``k8s_drain`` with check mode. When you explicitly allow evicting unmanaged pods, pods with local storage, or pods managed by a ``DaemonSet``, those cases are reported as informational output instead of module warnings.
Minor Changes
-------------
- helm_info - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
- helm_plugin - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
- helm_plugin_info - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
- helm_pull - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
- helm_registry_auth - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
- helm_registry_auth - add new option plain_http to allow insecure http connection when running ``helm registry login`` (https://github.com/ansible-collections/kubernetes.core/pull/1090).
- helm_repository - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
- k8s_drain - Add support for ``check_mode`` (https://github.com/ansible-collections/kubernetes.core/pull/1086).
- k8s_drain - Convert module warnings into informational displays when users explicitly request the deletion of unmanaged pods, pods with local storage, or those managed by a `DaemonSet` (https://github.com/ansible-collections/kubernetes.core/issues/1037).
Bugfixes
--------
- Helm - Allow taking ownership of existing Kubernetes resources on the first installation of a Helm release. Previously, the ``take_ownership`` parameter was always disabled during the initial install, preventing resource adoption (https://github.com/ansible-collections/kubernetes.core/pull/1034).
v6.3.0
======
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.
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).
Deprecated Features
-------------------
- helm - the ``status.values`` return value has been deprecated and will be removed in a release after 2027-01-08. Use ``status.release_values`` instead (https://github.com/ansible-collections/kubernetes.core/pull/1056).
- helm_info - the ``status.values`` return value has been deprecated and will be removed in a release after 2027-01-08. Use ``status.release_values`` instead (https://github.com/ansible-collections/kubernetes.core/pull/1056).
Security Fixes
--------------
- Selectively redact sensitive info from kubeconfig instead of applying blanket ``no_log=True`` (https://github.com/ansible-collections/kubernetes.core/pull/1014).
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).
- 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
--------------------------------
@@ -18,6 +118,34 @@ 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
======
Release Summary
---------------
This release includes bugfixes for k8s service field handling, k8s_cp init containers support, and removes deprecated ansible.module_utils.six imports.
Bugfixes
--------
- Remove ``ansible.module_utils.six`` imports to avoid warnings (https://github.com/ansible-collections/kubernetes.core/pull/998).
- Update the `k8s_cp` module to also work for init containers (https://github.com/ansible-collections/kubernetes.core/pull/971).
- module_utils/k8s/service - hide fields first before creating diffs (https://github.com/ansible-collections/kubernetes.core/pull/915).
v5.4.0
======
Release Summary
---------------
This release updates the ``helm_registry_auth`` module to match the behavior of ``helm >= 3.18.0`` which reports a successful logout regardless of the current state (i.e., no idempotency).
Minor Changes
-------------
- Module ``helm_registry_auth`` does not support idempotency with ``helm >= 3.18.0`` (https://github.com/ansible-collections/kubernetes.core/pull/946).
v5.3.0
======
@@ -29,15 +157,15 @@ This release includes minor changes, bug fixes and also bumps ``ansible-lint`` v
Minor Changes
-------------
- kubernetes.core - Bump version of ``ansible-lint`` to ``25.1.2`` (https://github.com/ansible-collections/kubernetes.core/pull/919).
- Bump version of ``ansible-lint`` to 25.1.2 (https://github.com/ansible-collections/kubernetes.core/pull/919).
- action/k8s_info - update templating mechanism with changes from ``ansible-core 2.19`` (https://github.com/ansible-collections/kubernetes.core/pull/888).
- helm - add ``reset_then_reuse_values`` support to helm module (https://github.com/ansible-collections/kubernetes.core/issues/803).
- helm - add support for ``insecure_skip_tls_verify`` option to helm and ``helm_repository`` (https://github.com/ansible-collections/kubernetes.core/issues/694).
- helm - add support for ``insecure_skip_tls_verify`` option to helm and helm_repository(https://github.com/ansible-collections/kubernetes.core/issues/694).
Bugfixes
--------
- module_utils/k8s/service - Fix issue when trying to delete resource using ``delete_options`` and ``check_mode=true`` (https://github.com/ansible-collections/kubernetes.core/issues/892).
- module_utils/k8s/service - fix issue when trying to delete resource using ``delete_options`` and ``check_mode=true`` (https://github.com/ansible-collections/kubernetes.core/issues/892).
v5.2.0
======
@@ -65,7 +193,7 @@ This release came with new module ``helm_registry_auth``, improvements to the er
Minor Changes
-------------
- Bump version of ansible-lint to minimum 24.7.0 (https://github.com/ansible-collections/kubernetes.core/pull/765).
- Bump version of ``ansible-lint`` to minimum 24.7.0 (https://github.com/ansible-collections/kubernetes.core/pull/765).
- Parameter insecure_registry added to helm_template as equivalent of insecure-skip-tls-verify (https://github.com/ansible-collections/kubernetes.core/pull/805).
- k8s_drain - Improve error message for pod disruption budget when draining a node (https://github.com/ansible-collections/kubernetes.core/issues/797).

View File

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

View File

@@ -21,17 +21,19 @@ 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.16.0**.
This collection has been tested against the following Ansible versions: **>=2.16.0**.
For collections that support Ansible 2.9, please ensure you update your `network_os` to use the
fully qualified collection name (for example, `cisco.ios.ios`).
Plugins and modules within a collection may be tested with only specific Ansible versions.
A collection may contain metadata that identifies these versions.
PEP440 is the schema used to describe the versions of Ansible.
<!--end requires_ansible-->
### Helm Version Compatibility
This collection supports Helm v3.x and newer. Please note that specific modules or certain parameters may have additional version requirements.
### Python Support
* Collection supports 3.9+
@@ -47,17 +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
### 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
@@ -101,7 +103,7 @@ You can also include it in a `requirements.yml` file and install it via `ansible
---
collections:
- name: kubernetes.core
version: 6.0.0
version: 6.4.0
```
### Installing the Kubernetes Python Library
@@ -180,7 +182,6 @@ For documentation on how to use individual modules and other content included in
## Ansible Turbo Mode Tech Preview
The ``kubernetes.core`` collection supports Ansible Turbo mode as a tech preview via the ``cloud.common`` collection. By default, this feature is disabled. To enable Turbo mode for modules, set the environment variable `ENABLE_TURBO_MODE=1` on the managed node. For example:
```yaml
@@ -219,7 +220,7 @@ You can run the collection's test suites with the commands:
### Testing with `molecule`
There are also integration tests in the `molecule` directory which are meant to be run against a local Kubernetes cluster, e.g. using [KinD](https://kind.sigs.k8s.io) or [Minikube](https://minikube.sigs.k8s.io). To setup a local cluster using KinD and run Molecule:
There are also integration tests in the `molecule` directory which are meant to be run against a local Kubernetes cluster, e.g. using [KinD](https://kind.sigs.k8s.io) or [Minikube](https://minikube.sigs.k8s.io). To set up a local cluster using KinD and run Molecule:
kind create cluster
make test-molecule
@@ -258,7 +259,7 @@ For more information about communication, refer to the [Ansible Communication gu
For the latest supported versions, refer to the release notes below.
If you encounter issues or have questions, you can submit a support request through the following channels:
- GitHub Issues: Report bugs, request features, or ask questions by opening an issue in the [GitHub repository]((https://github.com/ansible-collections/kubernetes.core/).
- GitHub Issues: Report bugs, request features, or ask questions by opening an issue in the [GitHub repository](https://github.com/ansible-collections/kubernetes.core/).
## Release Notes
@@ -270,9 +271,8 @@ We follow the [Ansible Code of Conduct](https://docs.ansible.com/ansible/devel/c
If you encounter abusive behavior, please refer to the [policy violations](https://docs.ansible.com/ansible/devel/community/code_of_conduct.html#policy-violations) section of the Code for information on how to raise a complaint.
## License
GNU General Public License v3.0 or later
See LICENCE to see the full text.
See LICENSE to see the full text.

View File

@@ -977,7 +977,7 @@ releases:
- kustomize - kustomize plugin fails with deprecation warnings (https://github.com/ansible-collections/kubernetes.core/issues/639).
- waiter - Fix waiting for daemonset when desired number of pods is 0. (https://github.com/ansible-collections/kubernetes.core/pull/756).
minor_changes:
- Bump version of ansible-lint to minimum 24.7.0 (https://github.com/ansible-collections/kubernetes.core/pull/765).
- Bump version of ``ansible-lint`` to minimum 24.7.0 (https://github.com/ansible-collections/kubernetes.core/pull/765).
- Parameter insecure_registry added to helm_template as equivalent of insecure-skip-tls-verify
(https://github.com/ansible-collections/kubernetes.core/pull/805).
- k8s_drain - Improve error message for pod disruption budget when draining
@@ -1027,15 +1027,15 @@ releases:
changes:
bugfixes:
- module_utils/k8s/service - fix issue when trying to delete resource using
`delete_options` and `check_mode=true` (https://github.com/ansible-collections/kubernetes.core/issues/892).
``delete_options`` and ``check_mode=true`` (https://github.com/ansible-collections/kubernetes.core/issues/892).
minor_changes:
- 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 ``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
@@ -1044,6 +1044,35 @@ releases:
- 898-k8s-dont-delete-in-check-mode.yaml
- 919-update-ansible-lint-version.yaml
release_date: '2025-05-16'
5.4.0:
changes:
minor_changes:
- Module ``helm_registry_auth`` does not support idempotency with ``helm >=
3.18.0`` (https://github.com/ansible-collections/kubernetes.core/pull/946).
release_summary: This release updates the ``helm_registry_auth`` module to match
the behavior of ``helm >= 3.18.0`` which reports a successful logout regardless
of the current state (i.e., no idempotency).
fragments:
- 20250411-kubeconfig-no_log-revert.yaml
- 20250503-fix-unit-tests.yml
- 20250605-fix-helm_registry_auth-integration_test.yaml
- 5.4.0.yml
release_date: '2025-08-12'
5.4.1:
changes:
bugfixes:
- Remove ``ansible.module_utils.six`` imports to avoid warnings (https://github.com/ansible-collections/kubernetes.core/pull/998).
- Update the ``k8s_cp`` module to also work for init containers (https://github.com/ansible-collections/kubernetes.core/pull/971).
- module_utils/k8s/service - hide fields first before creating diffs (https://github.com/ansible-collections/kubernetes.core/pull/915).
release_summary: This release includes bugfixes for k8s service field handling,
k8s_cp init containers support, and removes deprecated ansible.module_utils.six
imports.
fragments:
- 20250428-k8s-service-hide-fields-first.yaml
- 20250731-fix-k8s_cp-initcontainers.yaml
- 20250922-remove-ansible-six-imports.yaml
- 5.4.1.yml
release_date: '2025-10-07'
6.0.0:
changes:
breaking_changes:
@@ -1052,3 +1081,125 @@ releases:
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`` does 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.
(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).
deprecated_features:
- helm - the ``status.values`` return value has been deprecated and will be
removed in a release after 2027-01-08. Use ``status.release_values`` instead
(https://github.com/ansible-collections/kubernetes.core/pull/1056).
- helm_info - the ``status.values`` return value has been deprecated and will
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:
- 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 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).
fragments:
- 1033-warnings-deprecations.yaml
- 20251002-fix-k8s-actiongroup.yaml
- 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
- 6-3-0.yaml
release_date: '2026-02-03'
6.4.0:
changes:
bugfixes:
- Helm - Allow taking ownership of existing Kubernetes resources on the first
installation of a Helm release. Previously, the ``take_ownership`` parameter
was always disabled during the initial install, preventing resource adoption
(https://github.com/ansible-collections/kubernetes.core/pull/1034).
minor_changes:
- helm_info - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
- helm_plugin - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
- helm_plugin_info - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
- helm_pull - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
- helm_registry_auth - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
- helm_registry_auth - add new option plain_http to allow insecure http connection
when running ``helm registry login`` (https://github.com/ansible-collections/kubernetes.core/pull/1090).
- helm_repository - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
- k8s_drain - Add support for ``check_mode`` (https://github.com/ansible-collections/kubernetes.core/pull/1086).
- k8s_drain - Convert module warnings into informational displays when users
explicitly request the deletion of unmanaged pods, pods with local storage,
or those managed by a ``DaemonSet`` (https://github.com/ansible-collections/kubernetes.core/issues/1037).
release_summary: This release adds Helm v4 compatibility across the Helm modules
and improves ``k8s_drain`` with check mode. When you explicitly allow evicting
unmanaged pods, pods with local storage, or pods managed by a ``DaemonSet``,
those cases are reported as informational output instead of module warnings.
fragments:
- 20251224-take-ownership-helm-initialization.yaml
- 20260203-k8s_drain-warning-fixes.yaml
- 20260213-support-helm-v4-for-helm-plugin-modules.yaml
- release-6-4-0.yml
release_date: '2026-04-22'

View File

@@ -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.

View File

@@ -25,7 +25,7 @@ Requirements
------------
The below requirements are needed on the host that executes this module.
- helm (https://github.com/helm/helm/releases)
- helm >= 3.0.0 (https://github.com/helm/helm/releases)
- yaml (https://pypi.org/project/PyYAML/)
@@ -268,7 +268,7 @@ Examples
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
Common return values are documented `here <https://docs.ansible.com/projects/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
.. raw:: html
@@ -410,6 +410,23 @@ Common return values are documented `here <https://docs.ansible.com/ansible/late
<br/>
</td>
</tr>
<tr>
<td class="elbow-placeholder">&nbsp;</td>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>release_values</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">dictionary</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.3.0</div>
</td>
<td>always</td>
<td>
<div>Dict of Values used to deploy.</div>
<br/>
</td>
</tr>
<tr>
<td class="elbow-placeholder">&nbsp;</td>
<td colspan="1">
@@ -465,12 +482,13 @@ Common return values are documented `here <https://docs.ansible.com/ansible/late
<b>values</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
<span style="color: purple">dictionary</span>
</div>
</td>
<td>always</td>
<td>
<div>Dict of Values used to deploy</div>
<div>This return value has been deprecated and will be removed in a release after 2027-01-08. Use RV(status.release_values) instead.</div>
<br/>
</td>
</tr>

View File

@@ -25,7 +25,7 @@ Requirements
------------
The below requirements are needed on the host that executes this module.
- helm (https://github.com/helm/helm/releases)
- helm >= 3.0.0 (https://github.com/helm/helm/releases)
- yaml (https://pypi.org/project/PyYAML/)
@@ -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>&nbsp;&larr;</div></li>
<li>yes</li>
</ul>
</td>
<td>
<div>Use HTTP instead of HTTPS when working with OCI registries</div>
<div>Requires Helm &gt;= 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>&nbsp;&larr;</div></li>
<li>yes</li>
</ul>
</td>
<td>
<div>Disables JSON schema validation for Chart and values.</div>
<div>This feature requires helm &gt;= 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>&nbsp;&larr;</div></li>
<li>yes</li>
</ul>
</td>
<td>
<div>Helm will ignore the check for helm annotations and take ownership of the existing resources</div>
<div>This feature requires helm &gt;= 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:
@@ -851,7 +920,7 @@ Examples
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
Common return values are documented `here <https://docs.ansible.com/projects/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
.. raw:: html
@@ -957,6 +1026,23 @@ Common return values are documented `here <https://docs.ansible.com/ansible/late
<br/>
</td>
</tr>
<tr>
<td class="elbow-placeholder">&nbsp;</td>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>release_values</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">dictionary</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.3.0</div>
</td>
<td>always</td>
<td>
<div>Dict of Values used to deploy.</div>
<br/>
</td>
</tr>
<tr>
<td class="elbow-placeholder">&nbsp;</td>
<td colspan="1">
@@ -1012,12 +1098,13 @@ Common return values are documented `here <https://docs.ansible.com/ansible/late
<b>values</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
<span style="color: purple">dictionary</span>
</div>
</td>
<td>always</td>
<td>
<div>Dict of Values used to deploy</div>
<div>Dict of Values used to deploy.</div>
<div>This return value has been deprecated and will be removed in a release after 2027-01-08. Use RV(status.release_values) instead.</div>
<br/>
</td>
</tr>

View File

@@ -25,7 +25,7 @@ Requirements
------------
The below requirements are needed on the host that executes this module.
- helm (https://github.com/helm/helm/releases)
- helm >= 3.0.0 (https://github.com/helm/helm/releases)
Parameters
@@ -196,7 +196,7 @@ Examples
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
Common return values are documented `here <https://docs.ansible.com/projects/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
.. raw:: html

View File

@@ -25,7 +25,7 @@ Requirements
------------
The below requirements are needed on the host that executes this module.
- helm (https://github.com/helm/helm/releases)
- helm >= 3.0.0 (https://github.com/helm/helm/releases)
Parameters
@@ -231,6 +231,28 @@ Parameters
<div style="font-size: small; color: darkgreen"><br/>aliases: verify_ssl</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>verify</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.4.0</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>no</li>
<li><div style="color: blue"><b>yes</b>&nbsp;&larr;</div></li>
</ul>
</td>
<td>
<div>Verify the plugin signature before installing.</div>
<div>This option requires helm version &gt;= 4.0.0</div>
<div>Used with <em>state=present</em>.</div>
</td>
</tr>
</table>
<br/>
@@ -272,7 +294,7 @@ Examples
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
Common return values are documented `here <https://docs.ansible.com/projects/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
.. raw:: html

View File

@@ -27,7 +27,7 @@ Requirements
------------
The below requirements are needed on the host that executes this module.
- helm >= 3.0 (https://github.com/helm/helm/releases)
- helm >= 3.0.0 (https://github.com/helm/helm/releases)
Parameters
@@ -174,6 +174,28 @@ Parameters
<div>location to write the chart.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>force</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.3.0</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>no</b>&nbsp;&larr;</div></li>
<li>yes</li>
</ul>
</td>
<td>
<div>Force download of the chart even if it already exists in the destination directory.</div>
<div>By default, the module will skip downloading if the chart with the same version already exists for idempotency.</div>
<div>When used with O(untar_chart=true), will remove any existing chart directory before extracting.</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
@@ -193,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>&nbsp;&larr;</div></li>
<li>yes</li>
</ul>
</td>
<td>
<div>Use HTTP instead of HTTPS when working with OCI registries</div>
<div>Requires Helm &gt;= 3.13.0</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
@@ -376,11 +419,28 @@ Examples
username: myuser
password: mypassword123
- name: Download Chart (force re-download even if exists)
kubernetes.core.helm_pull:
chart_ref: redis
repo_url: https://charts.bitnami.com/bitnami
chart_version: '17.0.0'
destination: /path/to/chart
force: yes
- name: Download and untar chart (force re-extraction even if directory exists)
kubernetes.core.helm_pull:
chart_ref: redis
repo_url: https://charts.bitnami.com/bitnami
chart_version: '17.0.0'
destination: /path/to/chart
untar_chart: yes
force: yes
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
Common return values are documented `here <https://docs.ansible.com/projects/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
.. raw:: html
@@ -407,6 +467,23 @@ Common return values are documented `here <https://docs.ansible.com/ansible/late
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">helm pull --repo test ...</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>
<b>msg</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small">
<span style="color: purple">string</span>
</div>
</td>
<td>when chart already exists</td>
<td>
<div>A message indicating the result of the operation.</div>
<br/>
<div style="font-size: smaller"><b>Sample:</b></div>
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">Chart redis version 17.0.0 already exists in destination directory</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="return-"></div>

View File

@@ -25,7 +25,7 @@ Requirements
------------
The below requirements are needed on the host that executes this module.
- helm (https://github.com/helm/helm/releases) => 3.8.0
- helm (https://github.com/helm/helm/releases) >= 3.8.0
Parameters
@@ -151,6 +151,27 @@ Parameters
<div style="font-size: small; color: darkgreen"><br/>aliases: repo_password</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.4.0</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>no</b>&nbsp;&larr;</div></li>
<li>yes</li>
</ul>
</td>
<td>
<div>Use insecure HTTP connections for <code>helm registry login</code>.</div>
<div>Requires Helm &gt;= 3.18.0</div>
</td>
</tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
@@ -170,6 +191,7 @@ Parameters
<div>Desired state of the registry.</div>
<div>If set to V(present) attempt to log in to the remote registry server using the URL specified in O(host).</div>
<div>If set to V(absent) attempt to log out from the remote registry server using the URL specified in O(host).</div>
<div>As helm &gt;= 3.18.0 reports successful logout even if the user is not logged in, this module will report a change regardless of the current state.</div>
</td>
</tr>
<tr>
@@ -214,7 +236,7 @@ Examples
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
Common return values are documented `here <https://docs.ansible.com/projects/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
.. raw:: html

View File

@@ -25,7 +25,7 @@ Requirements
------------
The below requirements are needed on the host that executes this module.
- helm (https://github.com/helm/helm/releases)
- helm >= 3.0.0 (https://github.com/helm/helm/releases)
- yaml (https://pypi.org/project/PyYAML/)
@@ -336,7 +336,7 @@ Examples
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
Common return values are documented `here <https://docs.ansible.com/projects/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
.. raw:: html

View File

@@ -20,6 +20,13 @@ Synopsis
Requirements
------------
The below requirements are needed on the host that executes this module.
- helm >= 3.0.0 (https://github.com/helm/helm/releases)
- yaml (https://pypi.org/project/PyYAML/)
Parameters
----------
@@ -194,6 +201,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>&nbsp;&larr;</div></li>
<li>yes</li>
</ul>
</td>
<td>
<div>Use HTTP instead of HTTPS when working with OCI registries</div>
<div>Requires Helm &gt;= 3.13.0</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
@@ -409,7 +437,7 @@ Examples
Return Values
-------------
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
Common return values are documented `here <https://docs.ansible.com/projects/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
.. raw:: html

View File

@@ -512,6 +512,7 @@ Notes
.. note::
- the tar binary is required on the container when copying from local filesystem to pod.
- the (init) container has to be started before you copy files or directories to it.
- To avoid SSL certificate validation errors when ``validate_certs`` is *True*, the full certificate chain for the API server must be provided via ``ca_cert`` or in the kubeconfig file.

View File

@@ -140,6 +140,25 @@ Parameters
<div>The name of a context found in the config file. Can also be specified via K8S_AUTH_CONTEXT environment variable.</div>
</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>

View File

@@ -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

View File

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

View File

@@ -8,13 +8,16 @@ action_groups:
- helm_repository
k8s:
- k8s
- k8s_exec
- k8s_info
- k8s_log
- k8s_scale
- k8s_service
- k8s_cluster_info
- k8s_cp
- k8s_drain
- k8s_exec
- k8s_info
- k8s_json_patch
- k8s_log
- k8s_rollback
- k8s_scale
- k8s_service
plugin_routing:
inventory:

View File

@@ -20,9 +20,8 @@ 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.module_utils.six import iteritems, string_types
from ansible.plugins.action import ActionBase
try:
@@ -100,7 +99,7 @@ class ActionModule(ActionBase):
"trim_blocks": True,
"lstrip_blocks": False,
}
if isinstance(template, string_types):
if isinstance(template, str):
# treat this as raw_params
template_param["path"] = template
elif isinstance(template, dict):
@@ -120,7 +119,7 @@ class ActionModule(ActionBase):
):
if s_type in template_args:
value = ensure_type(template_args[s_type], "string")
if value is not None and not isinstance(value, string_types):
if value is not None and not isinstance(value, str):
raise AnsibleActionFail(
"%s is expected to be a string, but got %s instead"
% (s_type, type(value))
@@ -196,7 +195,7 @@ class ActionModule(ActionBase):
)
template_params = []
if isinstance(template, string_types) or isinstance(template, dict):
if isinstance(template, str) or isinstance(template, dict):
template_params.append(self.get_template_args(template))
elif isinstance(template, list):
for element in template:
@@ -246,7 +245,7 @@ class ActionModule(ActionBase):
# add ansible 'template' vars
temp_vars = copy.deepcopy(task_vars)
overrides = {}
for key, value in iteritems(template_item):
for key, value in template_item.items():
if hasattr(self._templar.environment, key):
if value is not None:
overrides[key] = value
@@ -303,7 +302,7 @@ class ActionModule(ActionBase):
)
def get_kubeconfig(self, kubeconfig, remote_transport, new_module_args):
if isinstance(kubeconfig, string_types):
if isinstance(kubeconfig, str):
# find the kubeconfig in the expected search path
if not remote_transport:
# kubeconfig is local

View File

@@ -264,7 +264,8 @@ 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
from ansible.plugins.connection import BUFSIZE, ConnectionBase
@@ -324,9 +325,12 @@ class Connection(ConnectionBase):
# Build command options based on doc string
doc_yaml = AnsibleLoader(self.documentation).get_single_data()
for key in doc_yaml.get("options"):
if key.endswith("verify_ssl") and self.get_option(key) != "":
# Translate verify_ssl to skip_verify_ssl, and output as string
skip_verify_ssl = not self.get_option(key)
if key == "validate_certs" and self.get_option(key) != "":
# Translate validate_certs to --insecure-skip-tls-verify flag
# validate_certs=True means verify certs (don't skip verification)
# validate_certs=False means don't verify certs (skip verification)
validate_certs_value = boolean(self.get_option(key), strict=False)
skip_verify_ssl = not validate_certs_value
local_cmd.append(
"{0}={1}".format(
self.connection_options[key], str(skip_verify_ssl).lower()

View File

@@ -86,14 +86,48 @@ DOCUMENTATION = """
description:
- Provide a username for authenticating with the API. Can also be specified via K8S_AUTH_USERNAME environment
variable.
no_proxy:
description:
- The comma separated list of hosts/domains/IP/CIDR that shouldn't go through proxy.
Can also be specified via K8S_AUTH_NO_PROXY environment variable.
- Please note that this module does not pick up typical proxy settings from the environment (e.g. NO_PROXY).
- This feature requires kubernetes>=19.15.0.
When kubernetes library is less than 19.15.0, it fails even if no_proxy is set correctly.
type: str
password:
description:
- Provide a password for authenticating with the API. Can also be specified via K8S_AUTH_PASSWORD environment
variable.
proxy:
description:
- The URL of an HTTP proxy to use for the connection. Can also be specified via K8S_AUTH_PROXY environment variable.
- Please note that this module does not pick up typical proxy settings from the environment (e.g. HTTP_PROXY).
type: str
proxy_headers:
description:
- The Header used for the HTTP proxy.
- Documentation can be found here
U(https://urllib3.readthedocs.io/en/latest/reference/urllib3.util.html?highlight=proxy_headers#urllib3.util.make_headers).
type: dict
suboptions:
proxy_basic_auth:
type: str
description:
- Colon-separated username:password for proxy basic authentication header.
- Can also be specified via K8S_AUTH_PROXY_HEADERS_PROXY_BASIC_AUTH environment.
basic_auth:
type: str
description:
- Colon-separated username:password for basic authentication header.
- Can also be specified via K8S_AUTH_PROXY_HEADERS_BASIC_AUTH environment.
user_agent:
type: str
description:
- String representing the user-agent you want, such as foo/1.0.
- Can also be specified via K8S_AUTH_PROXY_HEADERS_USER_AGENT environment.
client_cert:
description:
- Path to a certificate used to authenticate with the API. Can also be specified via K8S_AUTH_CERT_FILE
environment
- 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:

View File

@@ -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(

View File

@@ -1,16 +1,64 @@
from __future__ import absolute_import, division, print_function
from ansible.module_utils.six import string_types
__metaclass__ = type
import warnings
def list_dict_str(value):
if isinstance(value, (list, dict, string_types)):
if isinstance(value, (list, dict, str)):
return value
raise TypeError
def extract_sensitive_values_from_kubeconfig(kubeconfig_data):
"""
Extract only sensitive string values from kubeconfig data for no_log_values.
:arg kubeconfig_data: Dictionary containing kubeconfig data
:returns: Set of sensitive string values to be added to no_log_values
"""
values = set()
sensitive_fields = {
"token",
"password",
"secret",
"client-key-data",
"client-certificate-data",
"certificate-authority-data",
"api_key",
"access-token",
"refresh-token",
}
# Check API version and warn if not v1
if isinstance(kubeconfig_data, dict):
api_version = kubeconfig_data.get("apiVersion", "v1")
if api_version != "v1":
warnings.warn(
f"Kubeconfig API version '{api_version}' is not 'v1'. "
f"Sensitive field redaction is only guaranteed for API version 'v1'. "
f"Some sensitive data may not be properly redacted from the logs.",
UserWarning,
)
def _extract_recursive(data, current_path=""):
if isinstance(data, dict):
for key, value in data.items():
path = f"{current_path}.{key}" if current_path else key
if key in sensitive_fields:
if isinstance(value, str):
values.add(value)
else:
_extract_recursive(value, path)
elif isinstance(data, list):
for i, item in enumerate(data):
_extract_recursive(item, f"{current_path}[{i}]")
_extract_recursive(kubeconfig_data)
return values
AUTH_PROXY_HEADERS_SPEC = dict(
proxy_basic_auth=dict(type="str", no_log=True),
basic_auth=dict(type="str", no_log=True),
@@ -18,7 +66,7 @@ AUTH_PROXY_HEADERS_SPEC = dict(
)
AUTH_ARG_SPEC = {
"kubeconfig": {"type": "raw", "no_log": True},
"kubeconfig": {"type": "raw"},
"context": {},
"host": {},
"api_key": {"no_log": True},

View File

@@ -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:

View File

@@ -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 (
@@ -96,7 +96,7 @@ class K8SCopy(metaclass=ABCMeta):
return error, stdout, stderr
except Exception as e:
self.module.fail_json(
msg="Error while running/parsing from pod {1}/{2} command='{0}' : {3}".format(
msg="Error while running/parsing from pod {0}/{1} command='{2}' : {3}".format(
self.namespace, self.name, cmd, to_native(e)
)
)
@@ -278,11 +278,15 @@ class K8SCopyFromPod(K8SCopy):
def run(self):
self.files_to_copy = self.list_remote_files()
if self.files_to_copy == []:
# Using warn method instead of passing warnings to exit_json as it is
# deprecated in ansible-core>=2.19.0
self._module.warn(
"No file found from directory '{0}' into remote Pod.".format(
self.remote_path
)
)
self.module.exit_json(
changed=False,
warning="No file found from directory '{0}' into remote Pod.".format(
self.remote_path
),
)
self.copy()
@@ -435,11 +439,21 @@ def check_pod(svc):
try:
result = svc.client.get(resource, name=name, namespace=namespace)
containers = [
c["name"] for c in result.to_dict()["status"]["containerStatuses"]
]
if container and container not in containers:
containers = dict(
{
c["name"]: c
for cl in ["initContainerStatuses", "containerStatuses"]
for c in result.to_dict()["status"].get(cl, [])
}
)
if container and container not in containers.keys():
module.fail_json(msg="Pod has no container {0}".format(container))
return containers
if (
container
and container in containers
and not bool(containers[container].get("started", False))
):
module.fail_json(msg="Pod container {0} is not started".format(container))
return containers.keys()
except Exception as exc:
_fail(exc)

View File

@@ -15,7 +15,9 @@ import tempfile
import traceback
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
from ansible.module_utils.six import string_types
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
extract_sensitive_values_from_kubeconfig,
)
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
LooseVersion,
)
@@ -38,16 +40,20 @@ def parse_helm_plugin_list(output=None):
if not output:
return ret
parsing_grammar = None
for line in output:
if line.startswith("NAME"):
parsing_grammar = [s.strip().lower() for s in line.split("\t")]
continue
name, version, description = line.split("\t", 3)
name = name.strip()
version = version.strip()
description = description.strip()
if name == "":
if parsing_grammar is None:
continue
ret.append((name, version, description))
plugin = {
parsing_grammar[i]: v.strip()
for i, v in enumerate(line.split("\t", len(parsing_grammar)))
}
if plugin["name"] == "":
continue
ret.append(plugin)
return ret
@@ -113,12 +119,19 @@ class AnsibleHelmModule(object):
kubeconfig_content = None
kubeconfig = self.params.get("kubeconfig")
if kubeconfig:
if isinstance(kubeconfig, string_types):
if isinstance(kubeconfig, str):
with open(os.path.expanduser(kubeconfig)) as fd:
kubeconfig_content = yaml.safe_load(fd)
elif isinstance(kubeconfig, dict):
kubeconfig_content = kubeconfig
# Redact sensitive fields from kubeconfig for logging purposes
if kubeconfig_content:
# Add original sensitive values to no_log_values to prevent them from appearing in logs
self._module.no_log_values.update(
extract_sensitive_values_from_kubeconfig(kubeconfig_content)
)
if self.params.get("ca_cert"):
ca_cert = self.params.get("ca_cert")
if LooseVersion(self.get_helm_version()) < LooseVersion("3.5.0"):
@@ -193,6 +206,38 @@ class AnsibleHelmModule(object):
return m.group(1)
return None
def is_helm_v4(self):
helm_version = self.get_helm_version()
if helm_version is None:
return False
return LooseVersion(helm_version) >= LooseVersion("4.0.0")
def is_helm_version_compatible_with_helm_diff(self, helm_diff_version):
"""
Return true if the helm version is compatible with the helm diff version
Helm v4 requires helm diff v3.14.0
"""
if not helm_diff_version:
return False
if self.is_helm_v4():
return LooseVersion(helm_diff_version) >= LooseVersion("3.14.0")
return True
def validate_helm_version(self, version="3.0.0"):
"""
Validate that Helm version is >= version (default version=3.0.0).
"""
helm_version = self.get_helm_version()
if helm_version is None:
self.fail_json(msg="Unable to determine Helm version")
if LooseVersion(helm_version) < LooseVersion(version):
self.fail_json(
msg="Helm version must be >= {0}, current version is {1}".format(
version, helm_version
)
)
def get_values(self, release_name, get_all=False):
"""
Get Values from deployed release

View File

@@ -16,7 +16,6 @@ HELM_AUTH_ARG_SPEC = dict(
type="raw",
aliases=["kubeconfig_path"],
fallback=(env_fallback, ["K8S_AUTH_KUBECONFIG"]),
no_log=True,
),
host=dict(type="str", fallback=(env_fallback, ["K8S_AUTH_HOST"])),
ca_cert=dict(

View File

@@ -5,7 +5,6 @@ import hashlib
import os
from typing import Any, Dict, List, Optional
from ansible.module_utils.six import iteritems, string_types
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
AUTH_ARG_MAP,
AUTH_ARG_SPEC,
@@ -115,7 +114,7 @@ def _load_config(auth: Dict) -> None:
"persist_config": auth.get("persist_config"),
}
if kubeconfig:
if isinstance(kubeconfig, string_types):
if isinstance(kubeconfig, str):
kubernetes.config.load_kube_config(config_file=kubeconfig, **optional_arg)
elif isinstance(kubeconfig, dict):
kubernetes.config.load_kube_config_from_dict(
@@ -163,7 +162,7 @@ def _create_configuration(auth: Dict):
except AttributeError:
configuration = kubernetes.client.Configuration()
for key, value in iteritems(auth):
for key, value in auth.items():
if key in AUTH_ARG_MAP.keys() and value is not None:
if key == "api_key":
setattr(

View File

@@ -3,6 +3,9 @@ from typing import Optional
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
from ansible.module_utils.common.text.converters import to_text
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
extract_sensitive_values_from_kubeconfig,
)
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
LooseVersion,
)
@@ -33,6 +36,15 @@ class AnsibleK8SModule:
self._module = self.settings["module_class"](**kwargs)
# Apply kubeconfig redaction for logging purposes
if hasattr(self._module, "params") and hasattr(self._module, "no_log_values"):
kubeconfig = self._module.params.get("kubeconfig")
if kubeconfig and isinstance(kubeconfig, dict):
# Add sensitive values to no_log_values to prevent them from appearing in logs
self._module.no_log_values.update(
extract_sensitive_values_from_kubeconfig(kubeconfig)
)
if self.settings["check_k8s"]:
self.requires("kubernetes")
self.has_at_least("kubernetes", "24.2.0", warn=True)

View File

@@ -4,7 +4,6 @@
import os
from typing import Dict, Iterable, List, Optional, Union, cast
from ansible.module_utils.six import string_types
from ansible.module_utils.urls import Request
try:
@@ -78,11 +77,11 @@ def create_definitions(params: Dict) -> List[ResourceDefinition]:
def from_yaml(definition: Union[str, List, Dict]) -> Iterable[Dict]:
"""Load resource definitions from a yaml definition."""
definitions: List[Dict] = []
if isinstance(definition, string_types):
if isinstance(definition, str):
definitions += yaml.safe_load_all(definition)
elif isinstance(definition, list):
for item in definition:
if isinstance(item, string_types):
if isinstance(item, str):
definitions += yaml.safe_load_all(item)
else:
definitions.append(item)

View File

@@ -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,
)

View File

@@ -498,8 +498,8 @@ def diff_objects(
if not diff:
return True, result
result["before"] = diff[0]
result["after"] = diff[1]
result["before"] = hide_fields(diff[0], hidden_fields)
result["after"] = hide_fields(diff[1], hidden_fields)
if list(result["after"].keys()) == ["metadata"] and list(
result["before"].keys()
@@ -512,9 +512,6 @@ def diff_objects(
).issubset(ignored_keys):
return True, result
result["before"] = hide_fields(result["before"], hidden_fields)
result["after"] = hide_fields(result["after"], hidden_fields)
return False, result

View File

@@ -21,7 +21,7 @@ author:
- Matthieu Diehr (@d-matt)
requirements:
- "helm (https://github.com/helm/helm/releases)"
- "helm >= 3.0.0 (https://github.com/helm/helm/releases)"
- "yaml (https://pypi.org/project/PyYAML/)"
description:
@@ -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:
- 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:
@@ -392,9 +419,18 @@ status:
returned: always
description: The Date of last update
values:
type: str
type: dict
returned: always
description: Dict of Values used to deploy
description:
- Dict of Values used to deploy.
- This return value has been deprecated and will be removed in a release after
2027-01-08. Use RV(status.release_values) instead.
release_values:
type: dict
returned: always
description:
- Dict of Values used to deploy.
version_added: 6.3.0
stdout:
type: str
description: Full `helm` command stdout, in case you want to display it or examine the event log
@@ -464,9 +500,13 @@ def get_release_status(module, release_name, all_status=False):
"--filter",
release_name,
]
if all_status:
if all_status and not module.is_helm_v4():
# --all has been removed from `helm list` command on helm v4
list_command.append("--all")
elif not all_status:
# The default behavior to display only deployed releases has been removed from
# Helm v4
list_command.append("--deployed")
rc, out, err = module.run_helm_command(list_command)
release = get_release(yaml.safe_load(out), release_name)
@@ -474,7 +514,8 @@ def get_release_status(module, release_name, all_status=False):
if release is None: # not install
return None
release["values"] = module.get_values(release_name)
release["release_values"] = module.get_values(release_name)
release["values"] = release["release_values"]
return release
@@ -495,7 +536,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
"""
@@ -504,6 +547,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)
@@ -533,6 +587,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
@@ -546,6 +603,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)
@@ -595,6 +654,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
@@ -618,6 +680,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
@@ -670,8 +743,8 @@ def get_plugin_version(plugin):
return None
for line in out:
if line[0] == plugin:
return line[1]
if line["name"] == plugin:
return line["version"]
return None
@@ -690,6 +763,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.
@@ -745,6 +820,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())
@@ -808,6 +905,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
@@ -832,6 +932,9 @@ def main():
if not IMP_YAML:
module.fail_json(msg=missing_required_lib("yaml"), exception=IMP_YAML_ERR)
# Validate Helm version >=3.0.0
module.validate_helm_version()
changed = False
chart_ref = module.params.get("chart_ref")
@@ -862,6 +965,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)
@@ -871,6 +977,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'
@@ -881,8 +1014,7 @@ def main():
if wait:
helm_version = module.get_helm_version()
if LooseVersion(helm_version) < LooseVersion("3.7.0"):
opt_result["warnings"] = []
opt_result["warnings"].append(
module.warn(
"helm uninstall support option --wait for helm release >= 3.7.0"
)
wait = False
@@ -900,7 +1032,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:
@@ -962,19 +1094,29 @@ 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
else:
helm_diff_version = get_plugin_version("diff")
if helm_diff_version and (
not chart_repo_url
or (
chart_repo_url
and LooseVersion(helm_diff_version) >= LooseVersion("3.4.1")
helm_version_compatible = module.is_helm_version_compatible_with_helm_diff(
helm_diff_version
)
if (
helm_diff_version
and helm_version_compatible
and (
not chart_repo_url
or (
chart_repo_url
and LooseVersion(helm_diff_version) >= LooseVersion("3.4.1")
)
)
):
(would_change, prepared) = helmdiff_check(
would_change, prepared = helmdiff_check(
module,
release_name,
chart_ref,
@@ -989,14 +1131,24 @@ 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}
else:
module.warn(
"The default idempotency check can fail to report changes in certain cases. "
"Install helm diff >= 3.4.1 for better results."
)
if helm_diff_version and not helm_version_compatible:
module.warn(
"Idempotency checks are currently disabled due to a version mismatch."
f" Helm version {module.get_helm_version()} requires helm-diff >= 3.14.0,"
f" but the environment is currently running {helm_diff_version}."
" Please align the plugin versions to restore standard behavior."
)
else:
module.warn(
"The default idempotency check can fail to report changes in certain cases. "
"Install helm diff >= 3.4.1 for better results."
)
would_change = default_check(
release_status, chart_info, release_values, values_files
)
@@ -1026,14 +1178,22 @@ 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
if module.check_mode:
check_status = {"values": {"current": {}, "declared": {}}}
check_status = {
"values": {"current": {}, "declared": {}},
"release_values": {"current": {}, "declared": {}},
}
if release_status:
check_status["values"]["current"] = release_status["values"]
check_status["values"]["current"] = release_status["release_values"]
check_status["values"]["declared"] = release_status
check_status["release_values"]["current"] = release_status["release_values"]
check_status["release_values"]["declared"] = release_status
module.exit_json(
changed=changed,

View File

@@ -20,7 +20,7 @@ author:
- Lucas Boisserie (@LucasBoisserie)
requirements:
- "helm (https://github.com/helm/helm/releases)"
- "helm >= 3.0.0 (https://github.com/helm/helm/releases)"
- "yaml (https://pypi.org/project/PyYAML/)"
description:
@@ -115,9 +115,18 @@ status:
returned: always
description: The Date of last update
values:
type: str
type: dict
returned: always
description: Dict of Values used to deploy
description:
- Dict of Values used to deploy
- This return value has been deprecated and will be removed in a release after
2027-01-08. Use RV(status.release_values) instead.
release_values:
type: dict
returned: always
description:
- Dict of Values used to deploy.
version_added: 6.3.0
hooks:
type: list
elements: dict
@@ -202,7 +211,8 @@ def get_release_status(module, release_name, release_state, get_all_values=False
if release is None: # not install
return None
release["values"] = module.get_values(release_name, get_all_values)
release["release_values"] = module.get_values(release_name, get_all_values)
release["values"] = release["release_values"]
release["manifest"] = module.get_manifest(release_name)
release["notes"] = module.get_notes(release_name)
release["hooks"] = module.get_hooks(release_name)
@@ -235,6 +245,9 @@ def main():
if not IMP_YAML:
module.fail_json(msg=missing_required_lib("yaml"), exception=IMP_YAML_ERR)
# Validate Helm version >=3.0.0
module.validate_helm_version()
release_name = module.params.get("release_name")
release_state = module.params.get("release_state")
get_all_values = module.params.get("get_all_values")

View File

@@ -16,7 +16,7 @@ version_added: 1.0.0
author:
- Abhijeet Kasurde (@Akasurde)
requirements:
- "helm (https://github.com/helm/helm/releases)"
- "helm >= 3.0.0 (https://github.com/helm/helm/releases)"
description:
- Manages Helm plugins.
options:
@@ -48,6 +48,14 @@ options:
required: false
type: str
version_added: 2.3.0
verify:
description:
- Verify the plugin signature before installing.
- This option requires helm version >= 4.0.0
- Used with I(state=present).
type: bool
default: true
version_added: 6.4.0
extends_documentation_fragment:
- kubernetes.core.helm_common_options
"""
@@ -118,6 +126,9 @@ from ansible_collections.kubernetes.core.plugins.module_utils.helm_args_common i
HELM_AUTH_ARG_SPEC,
HELM_AUTH_MUTUALLY_EXCLUSIVE,
)
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
LooseVersion,
)
def argument_spec():
@@ -138,6 +149,10 @@ def argument_spec():
default="present",
choices=["present", "absent", "latest"],
),
verify=dict(
type="bool",
default=True,
),
)
)
return arg_spec
@@ -161,6 +176,9 @@ def main():
mutually_exclusive=mutually_exclusive(),
)
# Validate helm version >= 3.0.0
module.validate_helm_version()
state = module.params.get("state")
helm_cmd_common = module.get_helm_binary() + " plugin"
@@ -168,8 +186,19 @@ def main():
if state == "present":
helm_cmd_common += " install %s" % module.params.get("plugin_path")
plugin_version = module.params.get("plugin_version")
verify = module.params.get("verify")
if plugin_version is not None:
helm_cmd_common += " --version=%s" % plugin_version
if not verify:
helm_version = module.get_helm_version()
if LooseVersion(helm_version) < LooseVersion("4.0.0"):
module.warn(
"verify parameter requires helm >= 4.0.0, current version is {0}".format(
helm_version
)
)
else:
helm_cmd_common += " --verify=false"
if not module.check_mode:
rc, out, err = module.run_helm_command(
helm_cmd_common, fails_on_error=False
@@ -208,9 +237,9 @@ def main():
elif state == "absent":
plugin_name = module.params.get("plugin_name")
rc, output, err, command = module.get_helm_plugin_list()
out = parse_helm_plugin_list(output=output.splitlines())
plugins = parse_helm_plugin_list(output=output.splitlines())
if not out:
if not plugins:
module.exit_json(
failed=False,
changed=False,
@@ -221,12 +250,7 @@ def main():
rc=rc,
)
found = False
for line in out:
if line[0] == plugin_name:
found = True
break
if not found:
if all(plugin["name"] != plugin_name for plugin in plugins):
module.exit_json(
failed=False,
changed=False,
@@ -264,9 +288,9 @@ def main():
elif state == "latest":
plugin_name = module.params.get("plugin_name")
rc, output, err, command = module.get_helm_plugin_list()
out = parse_helm_plugin_list(output=output.splitlines())
plugins = parse_helm_plugin_list(output=output.splitlines())
if not out:
if not plugins:
module.exit_json(
failed=False,
changed=False,
@@ -277,12 +301,7 @@ def main():
rc=rc,
)
found = False
for line in out:
if line[0] == plugin_name:
found = True
break
if not found:
if all(plugin["name"] != plugin_name for plugin in plugins):
module.exit_json(
failed=False,
changed=False,

View File

@@ -16,7 +16,7 @@ version_added: 1.0.0
author:
- Abhijeet Kasurde (@Akasurde)
requirements:
- "helm (https://github.com/helm/helm/releases)"
- "helm >= 3.0.0 (https://github.com/helm/helm/releases)"
description:
- Gather information about Helm plugins installed in namespace.
options:
@@ -98,26 +98,16 @@ def main():
supports_check_mode=True,
)
plugin_name = module.params.get("plugin_name")
# Validate helm version >= 3.0.0
module.validate_helm_version()
plugin_list = []
plugin_name = module.params.get("plugin_name")
rc, output, err, command = module.get_helm_plugin_list()
out = parse_helm_plugin_list(output=output.splitlines())
for line in out:
if plugin_name is None:
plugin_list.append(
{"name": line[0], "version": line[1], "description": line[2]}
)
continue
if plugin_name == line[0]:
plugin_list.append(
{"name": line[0], "version": line[1], "description": line[2]}
)
break
plugins = parse_helm_plugin_list(output=output.splitlines())
if plugin_name is not None:
plugins = [plugin for plugin in plugins if plugin.get("name") == plugin_name]
module.exit_json(
changed=True,
@@ -125,7 +115,7 @@ def main():
stdout=output,
stderr=err,
rc=rc,
plugin_list=plugin_list,
plugin_list=plugins,
)

View File

@@ -21,7 +21,7 @@ description:
- There are options for unpacking the chart after download.
requirements:
- "helm >= 3.0 (https://github.com/helm/helm/releases)"
- "helm >= 3.0.0 (https://github.com/helm/helm/releases)"
options:
chart_ref:
@@ -89,6 +89,14 @@ options:
- if set to true, will untar the chart after downloading it.
type: bool
default: False
force:
description:
- Force download of the chart even if it already exists in the destination directory.
- By default, the module will skip downloading if the chart with the same version already exists for idempotency.
- When used with O(untar_chart=true), will remove any existing chart directory before extracting.
type: bool
default: False
version_added: 6.3.0
destination:
description:
- location to write the chart.
@@ -114,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"""
@@ -145,6 +160,23 @@ EXAMPLES = r"""
destination: /path/to/chart
username: myuser
password: mypassword123
- name: Download Chart (force re-download even if exists)
kubernetes.core.helm_pull:
chart_ref: redis
repo_url: https://charts.bitnami.com/bitnami
chart_version: '17.0.0'
destination: /path/to/chart
force: yes
- name: Download and untar chart (force re-extraction even if directory exists)
kubernetes.core.helm_pull:
chart_ref: redis
repo_url: https://charts.bitnami.com/bitnami
chart_version: '17.0.0'
destination: /path/to/chart
untar_chart: yes
force: yes
"""
RETURN = r"""
@@ -163,6 +195,11 @@ command:
description: Full `helm pull` command built by this module, in case you want to re-run the command outside the module or debug a problem.
returned: always
sample: helm pull --repo test ...
msg:
type: str
description: A message indicating the result of the operation.
returned: when chart already exists
sample: Chart redis version 17.0.0 already exists in destination directory
rc:
type: int
description: Helm pull command return code
@@ -170,6 +207,18 @@ rc:
sample: 1
"""
import os
import shutil
import tarfile
import uuid
try:
import yaml
HAS_YAML = True
except ImportError:
HAS_YAML = False
from ansible_collections.kubernetes.core.plugins.module_utils.helm import (
AnsibleHelmModule,
)
@@ -178,6 +227,115 @@ from ansible_collections.kubernetes.core.plugins.module_utils.version import (
)
def extract_chart_name(chart_ref):
"""
Extract chart name from chart reference.
Args:
chart_ref (str): Chart reference (name, URL, or OCI reference)
Returns:
str: Extracted chart name
"""
chart_name = chart_ref.split("/")[-1]
# Remove any query parameters or fragments from URL-based refs
if "?" in chart_name:
chart_name = chart_name.split("?")[0]
if "#" in chart_name:
chart_name = chart_name.split("#")[0]
# Remove .tgz extension if present
if chart_name.endswith(".tgz"):
chart_name = chart_name[:-4]
return chart_name
def chart_exists(destination, chart_ref, chart_version, untar_chart):
"""
Check if the chart already exists in the destination directory.
For untarred charts: check if directory exists with Chart.yaml matching version
For tarred charts: check if .tgz file exists and contains matching version
Args:
destination (str): Destination directory path
chart_ref (str): Chart reference (name or URL)
chart_version (str): Chart version to check for
untar_chart (bool): Whether to check for untarred or tarred chart
Returns:
bool: True if chart with matching version exists, False otherwise
"""
# YAML is required for version checking
if not HAS_YAML:
return False
# Without version, we can't reliably check
if not chart_version:
return False
# Extract chart name from chart_ref using shared helper
chart_name = extract_chart_name(chart_ref)
if untar_chart:
# Check for extracted directory
chart_dir = os.path.join(destination, chart_name)
chart_yaml_path = os.path.join(chart_dir, "Chart.yaml")
if os.path.isdir(chart_dir) and os.path.isfile(chart_yaml_path):
try:
with open(chart_yaml_path, "r", encoding="utf-8") as chart_file:
chart_metadata = yaml.safe_load(chart_file)
# Ensure chart_metadata is a dict and has a version that matches
if (
chart_metadata
and isinstance(chart_metadata, dict)
and chart_metadata.get("version") == chart_version
and chart_metadata.get("name") == chart_name
):
return True
except (yaml.YAMLError, IOError, OSError, TypeError):
# If we can't read or parse the file, treat as non-existent
pass
else:
# Check for .tgz file
chart_file = os.path.join(destination, f"{chart_name}-{chart_version}.tgz")
if os.path.isfile(chart_file):
try:
# Verify it's a valid tarball with matching version
with tarfile.open(chart_file, "r:gz") as tar:
# Try to extract Chart.yaml to verify version
# Look for Chart.yaml at the expected path: <chart-name>/Chart.yaml
expected_chart_yaml = f"{chart_name}/Chart.yaml"
try:
member = tar.getmember(expected_chart_yaml)
chart_yaml_file = tar.extractfile(member)
if chart_yaml_file:
try:
chart_metadata = yaml.safe_load(chart_yaml_file)
# Ensure chart_metadata is a dict and has a version that matches
if (
chart_metadata
and isinstance(chart_metadata, dict)
and chart_metadata.get("version") == chart_version
and chart_metadata.get("name") == chart_name
):
return True
except (yaml.YAMLError, TypeError):
# If we can't parse the YAML, treat as non-existent
pass
finally:
chart_yaml_file.close()
except KeyError:
# Chart.yaml not found at expected path
pass
except (tarfile.TarError, yaml.YAMLError, IOError, OSError, TypeError):
# If we can't read or parse the tarball, treat as non-existent
pass
return False
def main():
argspec = dict(
chart_ref=dict(type="str", required=True),
@@ -196,11 +354,13 @@ def main():
),
chart_devel=dict(type="bool"),
untar_chart=dict(type="bool", default=False),
force=dict(type="bool", default=False),
destination=dict(type="path", required=True),
chart_ca_cert=dict(type="path"),
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,
@@ -212,19 +372,17 @@ def main():
mutually_exclusive=[("chart_version", "chart_devel")],
)
# Validate Helm version >=3.0.0
module.validate_helm_version()
helm_version = module.get_helm_version()
if LooseVersion(helm_version) < LooseVersion("3.0.0"):
module.fail_json(
msg="This module requires helm >= 3.0.0, current version is {0}".format(
helm_version
)
)
helm_pull_opt_versionning = dict(
skip_tls_certs_check="3.3.0",
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):
@@ -264,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():
@@ -276,8 +435,72 @@ def main():
module.params.get("chart_ref"),
" ".join(helm_pull_opts),
)
# Check if chart already exists (idempotency)
if module.params.get("chart_version") and not module.params.get("force"):
chart_exists_locally = chart_exists(
module.params.get("destination"),
module.params.get("chart_ref"),
module.params.get("chart_version"),
module.params.get("untar_chart"),
)
if chart_exists_locally:
module.exit_json(
failed=False,
changed=False,
msg="Chart {0} version {1} already exists in destination directory".format(
module.params.get("chart_ref"), module.params.get("chart_version")
),
command="",
stdout="",
stderr="",
rc=0,
)
# When both untar_chart and force are enabled, we need to remove the existing chart directory
# BEFORE running helm pull to prevent helm's "directory already exists" error.
# We do this by:
# 1. Renaming the existing directory to a temporary name (if it exists)
# 2. Running helm pull
# 3. On success: remove the temporary directory
# 4. On failure: restore the temporary directory and report the error
chart_dir_renamed = False
chart_dir = None
chart_dir_backup = None
if module.params.get("untar_chart") and module.params.get("force"):
chart_name = extract_chart_name(module.params.get("chart_ref"))
chart_dir = os.path.join(module.params.get("destination"), chart_name)
# Check if directory exists and contains a Chart.yaml (to be safe)
if os.path.isdir(chart_dir):
chart_yaml_path = os.path.join(chart_dir, "Chart.yaml")
# Only rename if it looks like a Helm chart directory (have Chart.yaml)
if os.path.isfile(chart_yaml_path):
if not module.check_mode:
# Rename to temporary backup name using uuid for uniqueness
backup_suffix = uuid.uuid4().hex[:8]
chart_dir_backup = os.path.join(
module.params.get("destination"),
f".{chart_name}_backup_{backup_suffix}",
)
os.rename(chart_dir, chart_dir_backup)
chart_dir_renamed = True
if not module.check_mode:
rc, out, err = module.run_helm_command(helm_cmd_common, fails_on_error=False)
# Handle cleanup/restore based on helm command result
if chart_dir_renamed:
if rc == 0:
# Success: remove the backup directory
if os.path.isdir(chart_dir_backup):
shutil.rmtree(chart_dir_backup)
else:
# Failure: restore the backup directory
if os.path.isdir(chart_dir_backup) and not os.path.exists(chart_dir):
os.rename(chart_dir_backup, chart_dir)
else:
rc, out, err = (0, "", "")

View File

@@ -20,7 +20,7 @@ author:
- Yuriy Novostavskiy (@yurnov)
requirements:
- "helm (https://github.com/helm/helm/releases) => 3.8.0"
- "helm (https://github.com/helm/helm/releases) >= 3.8.0"
description:
- Helm registry authentication module allows you to login C(helm registry login) and logout C(helm registry logout) from a Helm registry.
@@ -31,6 +31,7 @@ options:
- Desired state of the registry.
- If set to V(present) attempt to log in to the remote registry server using the URL specified in O(host).
- If set to V(absent) attempt to log out from the remote registry server using the URL specified in O(host).
- As helm >= 3.18.0 reports successful logout even if the user is not logged in, this module will report a change regardless of the current state.
required: false
default: present
choices: ['present', 'absent']
@@ -74,6 +75,14 @@ options:
- Path to the CA certificate SSL file for verify registry server certificate.
required: false
type: path
plain_http:
description:
- Use insecure HTTP connections for C(helm registry login).
- Requires Helm >= 3.18.0
required: false
type: bool
default: False
version_added: 6.4.0
binary_path:
description:
- The path of a helm binary to use.
@@ -129,6 +138,9 @@ failed:
from ansible_collections.kubernetes.core.plugins.module_utils.helm import (
AnsibleHelmModule,
)
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
LooseVersion,
)
def arg_spec():
@@ -144,6 +156,7 @@ def arg_spec():
key_file=dict(type="path", required=False),
cert_file=dict(type="path", required=False),
ca_file=dict(type="path", required=False),
plain_http=dict(type="bool", default=False),
)
@@ -156,6 +169,7 @@ def login(
key_file,
cert_file,
ca_file,
plain_http,
):
login_command = command + " registry login " + host
@@ -173,6 +187,8 @@ def login(
if ca_file is not None:
login_command += " --ca-file=" + ca_file
if plain_http:
login_command += " --plain-http"
return login_command
@@ -190,6 +206,9 @@ def main():
supports_check_mode=True,
)
# Validate Helm version >=3.8.0
module.validate_helm_version(version="3.8.0")
changed = False
host = module.params.get("host")
@@ -200,6 +219,19 @@ def main():
key_file = module.params.get("key_file")
cert_file = module.params.get("cert_file")
ca_file = module.params.get("ca_file")
plain_http = module.params.get("plain_http")
helm_version = module.get_helm_version()
if plain_http:
if LooseVersion(helm_version) < LooseVersion("3.18.0"):
module.warn(
"plain_http option requires helm >= 3.18.0, current version is {0}".format(
helm_version
)
)
# reset option
plain_http = False
helm_cmd = module.get_helm_binary()
@@ -208,7 +240,15 @@ def main():
changed = True
elif state == "present":
helm_cmd = login(
helm_cmd, host, insecure, username, password, key_file, cert_file, ca_file
helm_cmd,
host,
insecure,
username,
password,
key_file,
cert_file,
ca_file,
plain_http,
)
changed = True
@@ -231,6 +271,12 @@ def main():
command=helm_cmd,
)
if LooseVersion(helm_version) >= LooseVersion("3.18.0") and state == "absent":
# https://github.com/ansible-collections/kubernetes.core/issues/944
module.warn(
"The helm_registry_auth is not idempotent with helm >= 3.18.0, always report a change."
)
module.exit_json(changed=changed, stdout=out, stderr=err, command=helm_cmd)

View File

@@ -20,7 +20,7 @@ author:
- Lucas Boisserie (@LucasBoisserie)
requirements:
- "helm (https://github.com/helm/helm/releases)"
- "helm >= 3.0.0 (https://github.com/helm/helm/releases)"
- "yaml (https://pypi.org/project/PyYAML/)"
description:
@@ -295,6 +295,9 @@ def main():
if not IMP_YAML:
module.fail_json(msg=missing_required_lib("yaml"), exception=IMP_YAML_ERR)
# Validate Helm version >= 3.0.0
module.validate_helm_version()
changed = False
repo_name = module.params.get("repo_name")

View File

@@ -21,6 +21,10 @@ author:
description:
- Render chart templates to an output directory or as text of concatenated yaml documents.
requirements:
- "helm >= 3.0.0 (https://github.com/helm/helm/releases)"
- "yaml (https://pypi.org/project/PyYAML/)"
options:
binary_path:
description:
@@ -147,6 +151,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 +229,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 +250,7 @@ def template(
values_files=None,
include_crds=False,
set_values=None,
plain_http=False,
):
cmd += " template "
@@ -262,6 +277,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 +325,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,12 +346,25 @@ 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)
# Validate Helm version >=3.0.0
module.validate_helm_version()
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)
@@ -357,6 +389,7 @@ def main():
values_files=values_files,
include_crds=include_crds,
set_values=set_values_args,
plain_http=plain_http,
)
if not check_mode:

View File

@@ -383,28 +383,24 @@ result:
contains:
api_version:
description: The versioned schema of this representation of an object.
returned: success
returned: when O(resource_definition) or O(src) contains a single object.
type: str
kind:
description: Represents the REST resource this object represents.
returned: success
returned: when O(resource_definition) or O(src) contains a single object.
type: str
metadata:
description: Standard object metadata. Includes name, namespace, annotations, labels, etc.
returned: success
returned: when O(resource_definition) or O(src) contains a single object.
type: complex
spec:
description: Specific attributes of the object. Will vary based on the I(api_version) and I(kind).
returned: success
returned: when O(resource_definition) or O(src) contains a single object.
type: complex
status:
description: Current status details for the object.
returned: success
returned: when O(resource_definition) or O(src) contains a single object.
type: complex
items:
description: Returned only when multiple yaml documents are passed to src or resource_definition
returned: when resource_definition or src contains list of objects
type: list
duration:
description: elapsed time of task in seconds
returned: when C(wait) is true
@@ -414,6 +410,46 @@ result:
description: error while trying to create/delete the object.
returned: error
type: complex
results:
description: An array of created, patched, or otherwise present objects.
returned: when O(resource_definition) or O(src) contains a list of objects.
type: complex
contains:
api_version:
description: The versioned schema of this representation of an object.
returned: when O(resource_definition) or O(src) contains a single object.
type: str
kind:
description: Represents the REST resource this object represents.
returned: when O(resource_definition) or O(src) contains a single object.
type: str
metadata:
description: Standard object metadata. Includes name, namespace, annotations, labels, etc.
returned: when O(resource_definition) or O(src) contains a single object.
type: complex
spec:
description: Specific attributes of the object. Will vary based on the I(api_version) and I(kind).
returned: when O(resource_definition) or O(src) contains a single object.
type: complex
status:
description: Current status details for the object.
returned: when O(resource_definition) or O(src) contains a single object.
type: complex
duration:
description: elapsed time of task in seconds
returned: when C(wait) is true
type: int
sample: 48
error:
description: error while trying to create/delete the object.
returned: error
type: complex
method:
description:
- The method used to deploy the resource.
returned: success
type: str
sample: create
"""
import copy

View File

@@ -79,6 +79,7 @@ options:
notes:
- the tar binary is required on the container when copying from local filesystem to pod.
- the (init) container has to be started before you copy files or directories to it.
"""
EXAMPLES = r"""
@@ -139,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,
)

View File

@@ -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,
)
@@ -230,7 +230,7 @@ def filter_pods(pods, force, ignore_daemonset, delete_emptydir_data):
else:
to_delete.append((pod.metadata.namespace, pod.metadata.name))
warnings, errors = [], []
warnings, errors, info = [], [], []
if unmanaged:
pod_names = ",".join([pod[0] + "/" + pod[1] for pod in unmanaged])
if not force:
@@ -242,7 +242,7 @@ def filter_pods(pods, force, ignore_daemonset, delete_emptydir_data):
)
else:
# Pod not managed will be deleted as 'force' is true
warnings.append(
info.append(
"Deleting Pods not managed by ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet: {0}.".format(
pod_names
)
@@ -264,7 +264,7 @@ def filter_pods(pods, force, ignore_daemonset, delete_emptydir_data):
"cannot delete Pods with local storage: {0}.".format(pod_names)
)
else:
warnings.append("Deleting Pods with local storage: {0}.".format(pod_names))
info.append("Deleting Pods with local storage: {0}.".format(pod_names))
for pod in localStorage:
to_delete.append((pod[0], pod[1]))
@@ -278,8 +278,8 @@ def filter_pods(pods, force, ignore_daemonset, delete_emptydir_data):
)
)
else:
warnings.append("Ignoring DaemonSet-managed Pods: {0}.".format(pod_names))
return to_delete, warnings, errors
info.append("Ignoring DaemonSet-managed Pods: {0}.".format(pod_names))
return to_delete, warnings, errors, info
class K8sDrainAnsible(object):
@@ -334,18 +334,19 @@ class K8sDrainAnsible(object):
def evict_pods(self, pods):
for namespace, name in pods:
try:
if self._drain_options.get("disable_eviction"):
self._api_instance.delete_namespaced_pod(
name=name, namespace=namespace, body=self._delete_options
)
else:
body = v1_eviction(
delete_options=self._delete_options,
metadata=V1ObjectMeta(name=name, namespace=namespace),
)
self._api_instance.create_namespaced_pod_eviction(
name=name, namespace=namespace, body=body
)
if not self._module.check_mode:
if self._drain_options.get("disable_eviction"):
self._api_instance.delete_namespaced_pod(
name=name, namespace=namespace, body=self._delete_options
)
else:
body = v1_eviction(
delete_options=self._delete_options,
metadata=V1ObjectMeta(name=name, namespace=namespace),
)
self._api_instance.create_namespaced_pod_eviction(
name=name, namespace=namespace, body=body
)
self._changed = True
except ApiException as exc:
if exc.reason != "Not Found":
@@ -362,11 +363,7 @@ class K8sDrainAnsible(object):
)
def list_pods(self):
params = {
"field_selector": "spec.nodeName={name}".format(
name=self._module.params.get("name")
)
}
params = {"field_selector": "spec.nodeName=" + self._module.params.get("name")}
pod_selectors = self._module.params.get("pod_selectors")
if pod_selectors:
params["label_selector"] = ",".join(pod_selectors)
@@ -376,7 +373,8 @@ class K8sDrainAnsible(object):
# Mark node as unschedulable
result = []
if not node_unschedulable:
self.patch_node(unschedulable=True)
if not self._module.check_mode:
self.patch_node(unschedulable=True)
result.append(
"node {0} marked unschedulable.".format(self._module.params.get("name"))
)
@@ -391,7 +389,8 @@ class K8sDrainAnsible(object):
def _revert_node_patch():
if self._changed:
self._changed = False
self.patch_node(unschedulable=False)
if not self._module.check_mode:
self.patch_node(unschedulable=False)
try:
pod_list = self.list_pods()
@@ -401,7 +400,7 @@ class K8sDrainAnsible(object):
delete_emptydir_data = self._drain_options.get(
"delete_emptydir_data", False
)
pods, warnings, errors = filter_pods(
pods, warnings, errors, info = filter_pods(
pod_list.items, force, ignore_daemonset, delete_emptydir_data
)
if errors:
@@ -431,17 +430,25 @@ class K8sDrainAnsible(object):
if pods:
self.evict_pods(pods)
number_pod = len(pods)
if self._drain_options.get("wait_timeout") is not None:
warn = self.wait_for_pod_deletion(
pods,
self._drain_options.get("wait_timeout"),
self._drain_options.get("wait_sleep"),
if self._module.check_mode:
result.append(
"Would have deleted {0} Pod(s) from node if not in check mode.".format(
number_pod
)
)
if warn:
warnings.append(warn)
result.append("{0} Pod(s) deleted from node.".format(number_pod))
else:
wait_timeout = self._drain_options.get("wait_timeout")
wait_sleep = self._drain_options.get("wait_sleep")
if wait_timeout is not None:
warn = self.wait_for_pod_deletion(pods, wait_timeout, wait_sleep)
if warn:
warnings.append(warn)
result.append("{0} Pod(s) deleted from node.".format(number_pod))
if warnings:
return dict(result=" ".join(result), warnings=warnings)
for warning in warnings:
self._module.warn(warning)
for line in info:
self._module.debug(line)
return dict(result=" ".join(result))
def patch_node(self, unschedulable):
@@ -482,7 +489,8 @@ class K8sDrainAnsible(object):
self._module.exit_json(
result="node {0} already marked unschedulable.".format(name)
)
self.patch_node(unschedulable=True)
if not self._module.check_mode:
self.patch_node(unschedulable=True)
result["result"] = "node {0} marked unschedulable.".format(name)
self._changed = True
@@ -491,7 +499,8 @@ class K8sDrainAnsible(object):
self._module.exit_json(
result="node {0} already marked schedulable.".format(name)
)
self.patch_node(unschedulable=False)
if not self._module.check_mode:
self.patch_node(unschedulable=False)
result["result"] = "node {0} marked schedulable.".format(name)
self._changed = True
@@ -534,7 +543,9 @@ def argspec():
def main():
module = AnsibleK8SModule(module_class=AnsibleModule, argument_spec=argspec())
module = AnsibleK8SModule(
module_class=AnsibleModule, argument_spec=argspec(), supports_check_mode=True
)
if not HAS_EVICTION_API:
module.fail_json(

View File

@@ -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,
)

View File

@@ -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

View File

@@ -168,7 +168,9 @@ def perform_action(svc, resource):
module.params["kind"],
resource["metadata"]["name"],
)
result = {"changed": False, "warnings": [warn]}
if warn:
module.warn(warn)
result = {"changed": False}
return result
if module.params["kind"] == "Deployment":

View File

@@ -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,
)
@@ -243,10 +243,12 @@ def execute_module(client, module):
module.fail_json(msg=error, **return_attributes)
def _continue_or_exit(warn):
if warn:
module.warn(warn)
if multiple_scale:
return_attributes["results"].append({"warning": warn, "changed": False})
return_attributes["results"].append({"changed": False})
else:
module.exit_json(warning=warn, **return_attributes)
module.exit_json(**return_attributes)
for existing in existing_items:
if kind.lower() == "job":

View File

@@ -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,
)

View File

@@ -1,4 +1 @@
time=100
helm_info
helm_repository
helm_template
disabled # used by test targets helm_vX_XX_XX

View File

@@ -9,23 +9,25 @@ chart_test_version: 4.2.4
chart_test_version_local_path: 1.32.0
chart_test_version_upgrade: 4.2.5
chart_test_version_upgrade_local_path: 1.33.0
chart_test_repo: "https://kubernetes.github.io/ingress-nginx"
chart_test_repo: "https://stenic.github.io/k8status/"
chart_test_git_repo: "http://github.com/helm/charts.git"
chart_test_values:
revisionHistoryLimit: 0
myValue: "changed"
test_namespace:
- "helm-test-crds"
- "helm-uninstall"
- "helm-read-envvars"
- "helm-dep-update"
- "helm-local-path-001"
- "helm-local-path-002"
- "helm-local-path-003"
- "helm-from-repository"
- "helm-from-url"
- "helm-reuse-values"
- "helm-chart-with-space-into-name"
- "helm-reset-then-reuse-values"
- "helm-insecure"
- "helm-test-crds-{{ helm_version | replace('.', '-') }}"
- "helm-uninstall-{{ helm_version | replace('.', '-') }}"
- "helm-read-envvars-{{ helm_version | replace('.', '-') }}"
- "helm-dep-update-{{ helm_version | replace('.', '-') }}"
- "helm-local-path-001-{{ helm_version | replace('.', '-') }}"
- "helm-local-path-002-{{ helm_version | replace('.', '-') }}"
- "helm-local-path-003-{{ helm_version | replace('.', '-') }}"
- "helm-from-repository-{{ helm_version | replace('.', '-') }}"
- "helm-from-url-{{ helm_version | replace('.', '-') }}"
- "helm-reuse-values-{{ helm_version | replace('.', '-') }}"
- "helm-chart-with-space-into-name-{{ helm_version | replace('.', '-') }}"
- "helm-reset-then-reuse-values-{{ helm_version | replace('.', '-') }}"
- "helm-insecure-{{ helm_version | replace('.', '-') }}"
- "helm-test-take-ownership-{{ helm_version | replace('.', '-') }}"
- "helm-skip-schema-validation-{{ helm_version | replace('.', '-') }}"

View File

@@ -52,7 +52,9 @@ import json
import subprocess
import time
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.kubernetes.core.plugins.module_utils.helm import (
AnsibleHelmModule,
)
class HelmReleaseNotFoundError(Exception):
@@ -60,7 +62,9 @@ class HelmReleaseNotFoundError(Exception):
super().__init__(message)
def create_pending_install_release(helm_binary, chart_ref, chart_release, namespace):
def create_pending_install_release(
module, helm_binary, chart_ref, chart_release, namespace
):
# create pending-install release
command = [
helm_binary,
@@ -78,13 +82,14 @@ def create_pending_install_release(helm_binary, chart_ref, chart_release, namesp
command = [
helm_binary,
"list",
"--all",
"--output=json",
"--namespace",
namespace,
"--filter",
chart_release,
]
if not module.is_helm_v4():
command.append("--all")
cmd = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = cmd.communicate()
@@ -92,11 +97,11 @@ def create_pending_install_release(helm_binary, chart_ref, chart_release, namesp
if not data:
error = "Release %s not found." % chart_release
raise HelmReleaseNotFoundError(message=error)
return data[0]["status"] == "pending-install", data[0]["status"]
return data[0]["status"] in ("pending-install", "failed"), data[0]["status"]
def main():
module = AnsibleModule(
module = AnsibleHelmModule(
argument_spec=dict(
binary_path=dict(type="path", required=True),
chart_ref=dict(type="str", required=True),
@@ -106,6 +111,7 @@ def main():
)
params = dict(
module=module,
helm_binary=module.params.get("binary_path"),
chart_release=module.params.get("chart_release"),
chart_ref=module.params.get("chart_ref"),
@@ -116,7 +122,7 @@ def main():
result, status = create_pending_install_release(**params)
if not result:
module.fail_json(
msg="unable to create pending-install release, current status is %s"
msg="unable to create pending-install/failed release, current status is %s"
% status
)
module.exit_json(changed=True, msg="Release created with status '%s'" % status)

View File

@@ -1,5 +1,3 @@
---
collections:
- kubernetes.core
dependencies:
- remove_namespace

View File

@@ -1,7 +0,0 @@
---
- connection: local
gather_facts: true
hosts: localhost
roles:
- helm

View File

@@ -1,15 +0,0 @@
---
- name: Init Helm folders
file:
path: /tmp/helm/
state: directory
- name: Unarchive Helm binary
unarchive:
src: 'https://get.helm.sh/{{ helm_archive_name | default(helm_default_archive_name) }}'
dest: /tmp/helm/
remote_src: yes
retries: 10
delay: 5
register: result
until: result is not failed

View File

@@ -1,8 +1,22 @@
---
- name: Ensure helm is not installed
file:
path: "{{ item }}"
state: absent
with_items:
- "/tmp/helm"
- name: Check failed if helm is not installed
include_tasks: test_helm_not_installed.yml
- name: Install Helm v4
ansible.builtin.include_role:
name: install_helm
vars:
helm_version: v3.6.0
- name: Test helm uninstall
ansible.builtin.include_tasks: test_helm_uninstall.yml
- name: Run tests
include_tasks: run_test.yml
loop_control:
loop_var: helm_version
with_items:
- "v3.15.4"
- "v3.16.0"

View File

@@ -1,55 +1,63 @@
---
- name: Ensure helm is not installed
file:
path: "{{ item }}"
state: absent
with_items:
- "/tmp/helm"
- name: Check failed if helm is not installed
include_tasks: test_helm_not_installed.yml
- name: "Install {{ helm_version }}"
include_role:
name: install_helm
- name: "Ensure we honor the environment variables"
include_tasks: test_read_envvars.yml
- name: Main helm tests
block:
- name: Install helm-diff plugin
helm_plugin:
binary_path: "{{ helm_binary }}"
plugin_path: https://github.com/databus23/helm-diff
plugin_version: "{{ helm_version is version('v4.0.0', '>=') | ternary('v3.14.0', 'v3.10.0') }}"
verify: false
- name: Deploy charts
include_tasks: "tests_chart/{{ test_chart_type }}.yml"
loop_control:
loop_var: test_chart_type
with_items:
- from_local_path
- from_repository
- from_url
- name: "Ensure we honor the environment variables"
include_tasks: test_read_envvars.yml
- name: test helm upgrade with reuse_values
include_tasks: test_helm_reuse_values.yml
- name: Deploy charts
include_tasks: "tests_chart/{{ test_chart_type }}.yml"
loop_control:
loop_var: test_chart_type
with_items:
- from_local_path
- from_repository
- from_url
- name: test helm upgrade with reset_then_reuse_values
include_tasks: test_helm_reset_then_reuse_values.yml
- name: test helm upgrade with reuse_values
include_tasks: test_helm_reuse_values.yml
- name: test helm dependency update
include_tasks: test_up_dep.yml
- name: test helm upgrade with reset_then_reuse_values
include_tasks: test_helm_reset_then_reuse_values.yml
- name: Test helm uninstall
include_tasks: test_helm_uninstall.yml
- name: test helm dependency update
include_tasks: test_up_dep.yml
- name: Test helm install with chart name containing space
include_tasks: test_helm_with_space_into_chart_name.yml
- name: Test helm install with chart name containing space
include_tasks: test_helm_with_space_into_chart_name.yml
# https://github.com/ansible-collections/community.kubernetes/issues/296
- name: Test Skip CRDS feature in helm chart install
include_tasks: test_crds.yml
# https://github.com/ansible-collections/community.kubernetes/issues/296
- name: Test Skip CRDS feature in helm chart install
include_tasks: test_crds.yml
- name: Test insecure registry flag feature
include_tasks: test_helm_insecure.yml
- name: Test insecure registry flag feature
include_tasks: test_helm_insecure.yml
- name: Clean helm install
file:
path: "{{ item }}"
state: absent
with_items:
- "/tmp/helm/"
- 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
always:
- name: Remove helm-diff plugin
helm_plugin:
binary_path: "{{ helm_binary }}"
plugin_name: diff
state: absent
ignore_errors: true
- name: Clean helm install
ansible.builtin.file:
path: "/tmp/helm/"
state: absent

View File

@@ -5,7 +5,7 @@
name: test
chart_ref: "{{ chart_test }}"
namespace: "helm-test"
ignore_errors: yes
ignore_errors: true
register: helm_missing_binary
- name: Assert that helm is not installed
@@ -13,3 +13,11 @@
that:
- helm_missing_binary is failed
- "'No such file or directory' in helm_missing_binary.msg"
when: ansible_version.full is version('2.20', '<')
- name: Assert that helm is not installed (ansible 2.20+)
assert:
that:
- helm_missing_binary is failed
- "'Error executing command' in helm_missing_binary.msg"
when: ansible_version.full is version('2.20', '>=')

View File

@@ -36,7 +36,29 @@
that:
- install is changed
- '"--reset-then-reuse-values" not in install.command'
- release_value["status"]["values"] == chart_release_values
- release_value["status"]["release_values"] == chart_release_values
# We need to provide the actual redis password otherwise the update command
# will fail with the following:
# Error: execution error at (redis/templates/replicas/application.yaml:55:35):
# PASSWORDS ERROR: You must provide your current passwords when upgrading the release.
# Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims.
# Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases
# 'global.redis.password' must not be empty, please add '--set global.redis.password=$REDIS_PASSWORD' to the command. To get the current value:
- name: Retrieve release password
kubernetes.core.k8s_info:
namespace: "{{ helm_namespace }}"
kind: Secret
name: test-redis
register: redis_secret
- ansible.builtin.set_fact:
chart_reset_then_reuse_values: "{{ chart_reset_then_reuse_values | combine(redis_global_password) }}"
vars:
redis_global_password:
global:
redis:
password: "{{ redis_secret.resources.0.data['redis-password'] | b64decode }}"
- name: Upgrade chart using reset_then_reuse_values=true
helm:
@@ -64,7 +86,7 @@
- '"--reset-then-reuse-values" in upgrade.command'
- '"--reuse-values " not in upgrade.command'
- '"--reset-values" not in upgrade.command'
- release_value["status"]["values"] == chart_release_values | combine(chart_reset_then_reuse_values, recursive=true)
- release_value["status"]["release_values"] == chart_release_values | combine(chart_reset_then_reuse_values, recursive=true)
always:
- name: Remove helm namespace
@@ -73,3 +95,4 @@
kind: Namespace
name: "{{ helm_namespace }}"
state: absent
wait: false

View File

@@ -36,7 +36,22 @@
that:
- install is changed
- '"--reuse-values=True" not in install.command'
- release_value["status"]["values"] == chart_release_values
- release_value["status"]["release_values"] == chart_release_values
- name: Retrieve release password
kubernetes.core.k8s_info:
namespace: "{{ helm_namespace }}"
kind: Secret
name: test-redis
register: redis_secret
- ansible.builtin.set_fact:
chart_reuse_values: "{{ chart_reuse_values | combine(redis_global_password) }}"
vars:
redis_global_password:
global:
redis:
password: "{{ redis_secret.resources.0.data['redis-password'] | b64decode }}"
- name: Upgrade chart using reuse_values=true
helm:
@@ -62,7 +77,7 @@
- upgrade is changed
- '"--reuse-values=True" in upgrade.command'
- '"--reset-values" not in upgrade.command'
- release_value["status"]["values"] == chart_release_values | combine(chart_reuse_values, recursive=true)
- release_value["status"]["release_values"] == chart_release_values | combine(chart_reuse_values, recursive=true)
always:
- name: Remove helm namespace

View File

@@ -0,0 +1,101 @@
---
- 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'
# We need to provide the actual redis password otherwise the update command
# will fail with the following:
# Error: execution error at (redis/templates/replicas/application.yaml:55:35):
# PASSWORDS ERROR: You must provide your current passwords when upgrading the release.
# Note that even after reinstallation, old credentials may be needed as they may be kept in persistent volume claims.
# Further information can be obtained at https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues/#credential-errors-while-upgrading-chart-releases
# 'global.redis.password' must not be empty, please add '--set global.redis.password=$REDIS_PASSWORD' to the command. To get the current value:
- name: Retrieve release password
kubernetes.core.k8s_info:
namespace: "{{ helm_namespace }}"
kind: Secret
name: test-take-ownership-redis
register: redis_secret
- 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"
global:
redis:
password: "{{ redis_secret.resources.0.data['redis-password'] | b64decode }}"
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"
global:
redis:
password: "{{ redis_secret.resources.0.data['redis-password'] | b64decode }}"
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

View File

@@ -31,26 +31,18 @@
- name: assert warning has been raised
assert:
that:
- uninstall.warnings
- uninstall.warnings is defined
- '"helm uninstall support option --wait for helm release >= 3.7.0" in uninstall.warnings'
- name: Create temp directory
tempfile:
state: directory
suffix: .test
register: _result
- set_fact:
helm_tmp_dir: "{{ _result.path }}"
- name: Unarchive Helm binary
unarchive:
src: 'https://get.helm.sh/helm-v3.7.0-linux-amd64.tar.gz'
dest: "{{ helm_tmp_dir }}"
remote_src: yes
- name: Install Helm v4
ansible.builtin.include_role:
name: install_helm
vars:
helm_version: v4.0.0
- name: Install chart
helm:
binary_path: "{{ helm_tmp_dir }}/linux-amd64/helm"
binary_path: "{{ helm_binary }}"
name: "{{ chart_name }}"
chart_ref: "{{ chart_source }}"
namespace: "{{ helm_namespace }}"
@@ -59,7 +51,7 @@
- name: uninstall chart again using recent version
helm:
state: absent
binary_path: "{{ helm_tmp_dir }}/linux-amd64/helm"
binary_path: "{{ helm_binary }}"
name: "{{ chart_name }}"
namespace: "{{ helm_namespace }}"
wait: yes
@@ -96,12 +88,6 @@
- _info.status is undefined
always:
- name: Delete temp directory
file:
path: "{{ helm_tmp_dir }}"
state: absent
ignore_errors: true
- name: Remove namespace
k8s:
kind: Namespace

View File

@@ -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

View File

@@ -30,9 +30,9 @@
binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}"
chart_version: "{{ chart_test_version }}"
namespace: "{{ helm_namespace }}"
ignore_errors: yes
ignore_errors: true
register: install_fail
- name: "Assert that Install fail {{ chart_test }} from {{ source }}"
@@ -46,7 +46,7 @@
binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}"
chart_version: "{{ chart_test_version }}"
namespace: "{{ helm_namespace }}"
create_namespace: true
register: install_check_mode
@@ -57,24 +57,25 @@
that:
- install_check_mode is changed
- install_check_mode.status is defined
- install_check_mode.status.values is defined
- install_check_mode.status.release_values is defined
- name: "Install {{ chart_test }} from {{ source }}"
helm:
binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}"
chart_version: "{{ chart_test_version }}"
namespace: "{{ helm_namespace }}"
create_namespace: true
register: install
- name: "Assert that {{ chart_test }} chart is installed from {{ source }}"
- name: "Assert that {{ chart_test }} chart version {{ chart_test_version }} is installed from {{ source }}"
assert:
that:
- install is changed
- install.status.chart == chart_test+"-"+chart_test_version
- install.status.status | lower == 'deployed'
- install.status.release_values == {}
- name: Check helm_info content
helm_info:
@@ -92,7 +93,7 @@
- deployed
register: release_state_content_info
- name: "Assert that {{ chart_test }} is installed from {{ source }} with helm_info"
- name: "Assert that {{ chart_test }} chart version {{ chart_test_version }} is installed from {{ source }} with helm_info"
assert:
that:
- content_info.status.chart == chart_test+"-"+chart_test_version
@@ -104,9 +105,10 @@
binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}"
chart_version: "{{ chart_test_version }}"
namespace: "{{ helm_namespace }}"
register: install
diff: true
- name: Assert idempotency
assert:
@@ -120,7 +122,7 @@
binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}"
chart_version: "{{ chart_test_version }}"
namespace: "{{ helm_namespace }}"
values: "{{ chart_test_values }}"
register: install
@@ -131,17 +133,18 @@
- install is changed
- install.status.status | lower == 'deployed'
- install.status.chart == chart_test+"-"+chart_test_version
- "install.status['values'].revisionHistoryLimit == 0"
- install.status['release_values'] == chart_test_values
- name: Check idempotency after adding vars
helm:
binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}"
chart_version: "{{ chart_test_version }}"
namespace: "{{ helm_namespace }}"
values: "{{ chart_test_values }}"
register: install
diff: true
- name: Assert idempotency after add vars
assert:
@@ -149,14 +152,14 @@
- install is not changed
- install.status.status | lower == 'deployed'
- install.status.chart == chart_test+"-"+chart_test_version
- "install.status['values'].revisionHistoryLimit == 0"
- install.status['release_values'] == chart_test_values
- name: "Remove Vars to {{ chart_test }} from {{ source }}"
helm:
binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}"
chart_version: "{{ chart_test_version }}"
namespace: "{{ helm_namespace }}"
register: install
@@ -166,16 +169,17 @@
- install is changed
- install.status.status | lower == 'deployed'
- install.status.chart == chart_test+"-"+chart_test_version
- install.status['values'] == {}
- install.status['release_values'] == {}
- name: Check idempotency after removing vars
helm:
binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}"
chart_version: "{{ chart_test_version }}"
namespace: "{{ helm_namespace }}"
register: install
diff: true
- name: Assert idempotency after removing vars
assert:
@@ -183,14 +187,14 @@
- install is not changed
- install.status.status | lower == 'deployed'
- install.status.chart == chart_test+"-"+chart_test_version
- install.status['values'] == {}
- install.status['release_values'] == {}
- name: "Upgrade {{ chart_test }} from {{ source }}"
helm:
binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source_upgrade | default(chart_source) }}"
chart_version: "{{ chart_source_version_upgrade | default(omit) }}"
chart_version: "{{ chart_test_version_upgrade }}"
namespace: "{{ helm_namespace }}"
register: install
@@ -206,9 +210,10 @@
binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source_upgrade | default(chart_source) }}"
chart_version: "{{ chart_source_version_upgrade | default(omit) }}"
chart_version: "{{ chart_test_version_upgrade }}"
namespace: "{{ helm_namespace }}"
register: install
diff: true
- name: Assert idempotency after upgrade
assert:
@@ -237,6 +242,7 @@
name: "{{ chart_release_name }}"
namespace: "{{ helm_namespace }}"
register: install
diff: true
- name: Assert idempotency
assert:
@@ -249,7 +255,7 @@
binary_path: "{{ helm_binary }}"
name: "{{ chart_release_replaced_name }}"
chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}"
chart_version: "{{ chart_test_version }}"
namespace: "{{ helm_namespace }}"
register: install
@@ -277,7 +283,7 @@
binary_path: "{{ helm_binary }}"
name: "{{ chart_release_replaced_name }}"
chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}"
chart_version: "{{ chart_test_version }}"
namespace: "{{ helm_namespace }}"
replace: True
register: install
@@ -305,7 +311,7 @@
binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}"
chart_version: "{{ chart_test_version }}"
namespace: "{{ helm_namespace }}"
values_files:
- "{{ role_path }}/files/values.yaml"
@@ -317,14 +323,14 @@
- install is changed
- install.status.status | lower == 'deployed'
- install.status.chart == chart_test+"-"+chart_test_version
- "install.status['values'].revisionHistoryLimit == 0"
- "install.status['release_values'].revisionHistoryLimit == 0"
- name: "Install {{ chart_test }} from {{ source }} with values_files (again)"
helm:
binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}"
chart_version: "{{ chart_test_version }}"
namespace: "{{ helm_namespace }}"
values_files:
- "{{ role_path }}/files/values.yaml"
@@ -346,7 +352,7 @@
helm_template:
binary_path: "{{ helm_binary }}"
chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}"
chart_version: "{{ chart_test_version }}"
output_dir: "{{ temp_dir }}"
values_files:
- "{{ role_path }}/files/values.yaml"
@@ -372,7 +378,7 @@
helm_template:
binary_path: "{{ helm_binary }}"
chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}"
chart_version: "{{ chart_test_version }}"
disable_hook: True
release_name: "myrelease"
release_namespace: "myreleasenamespace"
@@ -398,11 +404,11 @@
binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}"
chart_version: "{{ chart_test_version }}"
namespace: "{{ helm_namespace }}"
create_namespace: true
context: does-not-exist
ignore_errors: yes
ignore_errors: true
register: result
- name: Assert that release fails with non-existent context
@@ -417,6 +423,7 @@
state: absent
path: "{{ temp_dir }}"
ignore_errors: true
when: temp_dir is defined
- name: Remove helm namespace
k8s:

View File

@@ -5,18 +5,38 @@
name: test_helm
repo_url: "{{ chart_test_repo }}"
- name: Install Chart from repository
include_tasks: "../tests_chart.yml"
vars:
source: repository
chart_source: "test_helm/{{ chart_test }}"
chart_source_version: "{{ chart_test_version }}"
chart_source_version_upgrade: "{{ chart_test_version_upgrade }}"
helm_namespace: "{{ test_namespace[7] }}"
- name: Create temporary file to save values in
ansible.builtin.tempfile:
suffix: .helm_values
register: value_file
- name: Remove chart repo
helm_repository:
binary_path: "{{ helm_binary }}"
name: test_helm
repo_url: "{{ chart_test_repo }}"
state: absent
- vars:
source: repository
chart_test: k8status
chart_source: "test_helm/k8status"
chart_test_version: "0.16.1"
chart_test_version_upgrade: "0.16.2"
helm_namespace: "{{ test_namespace[7] }}"
chart_test_values:
replicaCount: 3
block:
- name: Save values into file
ansible.builtin.copy:
content: "{{ chart_test_values }}"
dest: "{{ value_file.path }}"
- name: Install Chart from repository
ansible.builtin.include_tasks: "../tests_chart.yml"
always:
- name: Remove temporary file
ansible.builtin.file:
state: absent
path: "{{ value_file.path }}"
- name: Remove chart repo
helm_repository:
binary_path: "{{ helm_binary }}"
name: test_helm
repo_url: "{{ chart_test_repo }}"
state: absent

View File

@@ -3,6 +3,11 @@
include_tasks: "../tests_chart.yml"
vars:
source: url
chart_source: "https://github.com/kubernetes/ingress-nginx/releases/download/helm-chart-{{ chart_test_version }}/{{ chart_test }}-{{ chart_test_version }}.tgz"
chart_source_upgrade: "https://github.com/kubernetes/ingress-nginx/releases/download/helm-chart-{{ chart_test_version_upgrade }}/{{ chart_test }}-{{ chart_test_version_upgrade }}.tgz"
chart_test: "k8status"
chart_test_values:
replicaCount: 3
chart_test_version: "0.16.1"
chart_test_version_upgrade: "0.16.2"
chart_source: https://github.com/stenic/k8status/releases/download/k8status-0.16.1/k8status-0.16.1.tgz
chart_source_upgrade: https://github.com/stenic/k8status/releases/download/k8status-0.16.2/k8status-0.16.2.tgz
helm_namespace: "{{ test_namespace[8] }}"

View File

@@ -239,6 +239,7 @@
vars:
chart_local_path: '{{ _tmpd.path }}/test-chart-deployment-time'
chart_repo_path: 'testing'
helm_binary_path: "{{ helm_binary }}"
always:
- name: Delete temporary directory
ansible.builtin.file:

View File

@@ -92,25 +92,11 @@
path: /tmp/helm/
state: absent
- name: Init Helm folders
file:
path: /tmp/helm
state: directory
- name: Set Helm old version
set_fact:
helm_archive_name: "helm-v3.8.0-linux-amd64.tar.gz"
helm_diff_old_version: "3.8.0"
- name: Unarchive Helm binary
unarchive:
src: "https://get.helm.sh/{{ helm_archive_name | default(helm_default_archive_name) }}"
dest: /tmp/helm/
remote_src: yes
retries: 10
delay: 5
register: result
until: result is not failed
- name: Install old version of helm
ansible.builtin.include_role:
name: install_helm
vars:
helm_version: "v3.8.0"
- name: Upgrade helm release (with reset_then_reuse_values=true)
kubernetes.core.helm:
@@ -140,7 +126,7 @@
binary_path: "{{ helm_binary }}"
state: present
plugin_path: https://github.com/databus23/helm-diff
plugin_version: "{{ helm_diff_old_version }}"
plugin_version: "3.8.0"
- name: Upgrade helm release (with reset_then_reuse_values=true)
kubernetes.core.helm:
@@ -166,6 +152,11 @@
- '"reset_then_reuse_values requires helm diff >= 3.9.12, current version is" in helm_upgrade.msg'
always:
- name: Delete Helm folders
file:
path: /tmp/helm/
state: absent
- name: Remove temporary directory
file:
path: "{{ helm_dir.path }}"

View File

@@ -1,7 +1,10 @@
---
helm_binary: "/tmp/helm/{{ ansible_system | lower }}-amd64/helm"
default_kubeconfig_path: "~/.kube/config"
test_namespace:
- "helm-in-memory-kubeconfig"
- "helm-kubeconfig-with-ca-cert"
- "helm-kubeconfig-with-insecure-skip-tls-verify"
helm_versions:
- v3.10.3
- v3.16.4
- v4.0.0

View File

@@ -1,4 +0,0 @@
---
dependencies:
- remove_namespace
- install_helm

View File

@@ -57,7 +57,7 @@
assert:
that:
- _install is failed
- '"Error: Kubernetes cluster unreachable" in _install.msg'
- '"error: kubernetes cluster unreachable" in _install.msg | lower()'
- name: Test helm modules using in-memory kubeconfig
include_tasks: "tests_helm_auth.yml"

View File

@@ -48,7 +48,7 @@
assert:
that:
- _install is failed
- '"Error: Kubernetes cluster unreachable" in _install.msg'
- '"error: kubernetes cluster unreachable" in _install.msg | lower()'
- name: Test helm modules using in-memory kubeconfig
include_tasks: "tests_helm_auth.yml"

View File

@@ -1,21 +1,5 @@
---
- name: Test helm with in-memory kubeconfig
include_tasks: "from_in_memory_kubeconfig.yml"
- ansible.builtin.include_tasks: run_tests.yml
loop: "{{ helm_versions }}"
loop_control:
loop_var: test_helm_version
with_items:
- "v3.10.3"
- name: Test helm with custom kubeconfig and validate_certs=false
include_tasks: "from_kubeconfig_with_validate_certs.yml"
loop_control:
loop_var: test_helm_version
with_items:
- "v3.10.3"
- name: Test helm with custom kubeconfig and ca_cert
include_tasks: "from_kubeconfig_with_cacert.yml"
loop_control:
loop_var: test_helm_version
with_items:
- "v3.10.3"
loop_var: helm_version

View File

@@ -0,0 +1,15 @@
---
- name: Run tests with helm version "{{ helm_version }}"
block:
- name: "Install Helm"
ansible.builtin.include_role:
name: install_helm
- name: Test helm with in-memory kubeconfig
ansible.builtin.include_tasks: "from_in_memory_kubeconfig.yml"
- name: Test helm with custom kubeconfig and validate_certs=false
include_tasks: "from_kubeconfig_with_validate_certs.yml"
- name: Test helm with custom kubeconfig and ca_cert
include_tasks: "from_kubeconfig_with_cacert.yml"

View File

@@ -5,16 +5,6 @@
suffix: .helm
register: _dir
- name: Install helm binary
block:
- name: "Install {{ test_helm_version }}"
include_role:
name: install_helm
vars:
helm_version: "{{ test_helm_version }}"
when: test_helm_version is defined
- set_fact:
saved_kubeconfig_path: "{{ _dir.path }}/config"
@@ -44,6 +34,7 @@
ca_cert: "{{ test_ca_cert | default(omit) }}"
state: present
plugin_path: https://github.com/hydeenoble/helm-subenv
verify: false
register: plugin
- assert:

View File

@@ -0,0 +1 @@
redis*

View File

@@ -0,0 +1,3 @@
helm_template
helm_pull
helm

View File

@@ -0,0 +1,4 @@
[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
helm-4.0.0 helm_version=v4.0.0 test_namespace=helm-plain-http-v4-0-0 tests_should_failed=false

View File

@@ -0,0 +1,15 @@
- name: Run test for helm plain http option
hosts: all
gather_facts: true
strategy: free
vars:
ansible_connection: local
ansible_python_interpreter: "{{ ansible_playbook_python }}"
chart_test_oci: "oci://registry-1.docker.io/bitnamicharts/redis"
roles:
- role: setup_namespace
tasks:
- ansible.builtin.include_tasks: tasks/test.yaml

View File

@@ -0,0 +1,95 @@
---
- 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 }}"
# 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

View File

@@ -0,0 +1,4 @@
#!/usr/bin/env bash
set -eux
export ANSIBLE_ROLES_PATH=../
ansible-playbook playbooks/play.yaml -i inventory.ini "$@"

View File

@@ -1,3 +0,0 @@
---
dependencies:
- install_helm

View File

@@ -1,165 +1,8 @@
---
- name: Install env plugin in check mode
helm_plugin:
binary_path: "{{ helm_binary }}"
state: present
plugin_path: https://github.com/adamreese/helm-env
register: check_install_env
check_mode: true
- assert:
that:
- check_install_env.changed
- name: Install env plugin
helm_plugin:
binary_path: "{{ helm_binary }}"
state: present
plugin_path: https://github.com/adamreese/helm-env
register: install_env
- assert:
that:
- install_env.changed
- name: Gather info about all plugin
helm_plugin_info:
binary_path: "{{ helm_binary }}"
register: plugin_info
- assert:
that:
- plugin_info.plugin_list is defined
- name: Install env plugin again
helm_plugin:
binary_path: "{{ helm_binary }}"
state: present
plugin_path: https://github.com/adamreese/helm-env
register: install_env
- assert:
that:
- not install_env.changed
- name: Uninstall env plugin in check mode
helm_plugin:
binary_path: "{{ helm_binary }}"
state: absent
plugin_name: env
register: check_uninstall_env
check_mode: true
- assert:
that:
- check_uninstall_env.changed
- name: Uninstall env plugin
helm_plugin:
binary_path: "{{ helm_binary }}"
state: absent
plugin_name: env
register: uninstall_env
- assert:
that:
- uninstall_env.changed
- name: Uninstall env plugin again
helm_plugin:
binary_path: "{{ helm_binary }}"
state: absent
plugin_name: env
register: uninstall_env
- assert:
that:
- not uninstall_env.changed
# https://github.com/ansible-collections/community.kubernetes/issues/399
- block:
- name: Copy required plugin files
copy:
src: "files/sample_plugin"
dest: "/tmp/helm_plugin_test/"
- name: Install sample_plugin from the directory
helm_plugin:
binary_path: "{{ helm_binary }}"
state: present
plugin_path: "/tmp/helm_plugin_test/sample_plugin"
register: sample_plugin_output
- name: Assert that sample_plugin is installed or not
assert:
that:
- sample_plugin_output.changed
- name: Gather Helm plugin info
helm_plugin_info:
binary_path: "{{ helm_binary }}"
register: r
- name: Set sample_plugin version
set_fact:
plugin_version: "{{ ( r.plugin_list | selectattr('name', 'equalto', plugin_name) | list )[0].version }}"
vars:
plugin_name: "sample_plugin"
- name: Assert if sample_plugin with multiline comment is installed
assert:
that:
- plugin_version == "0.0.1"
always:
- name: Uninstall sample_plugin
helm_plugin:
binary_path: "{{ helm_binary }}"
state: absent
plugin_name: sample_plugin
ignore_errors: yes
- block:
- name: uninstall helm plugin secrets
helm_plugin:
binary_path: "{{ helm_binary }}"
plugin_name: secrets
state: absent
- name: install helm-secrets on a specific version
helm_plugin:
binary_path: "{{ helm_binary }}"
plugin_path: https://github.com/jkroepke/helm-secrets
plugin_version: 3.4.1
state: present
- name: list helm plugin
helm_plugin_info:
plugin_name: secrets
binary_path: "{{ helm_binary }}"
register: plugin_list
- name: assert that secrets has been installed with specified version
assert:
that:
- plugin_list.plugin_list[0].version == "3.4.1"
- name: Update helm plugin version to latest
helm_plugin:
binary_path: "{{ helm_binary }}"
plugin_name: secrets
state: latest
register: _update
- name: assert update was performed
assert:
that:
- _update.changed
- '"Updated plugin: secrets" in _update.stdout'
always:
- name: Uninstall sample_plugin
helm_plugin:
binary_path: "{{ helm_binary }}"
state: absent
plugin_name: secrets
ignore_errors: yes
- name: Run tests
include_tasks: run_tests.yml
loop_control:
loop_var: helm_version
with_items:
- "v3.17.0"
- "v4.0.0"

View File

@@ -0,0 +1,195 @@
---
- name: "Install {{ helm_version }}"
include_role:
name: install_helm
- block:
- name: Install env plugin in check mode
helm_plugin:
binary_path: "{{ helm_binary }}"
state: present
plugin_path: https://github.com/adamreese/helm-env
verify: false
register: check_install_env
check_mode: true
- assert:
that:
- check_install_env.changed
- name: Install env plugin
helm_plugin:
binary_path: "{{ helm_binary }}"
state: present
plugin_path: https://github.com/adamreese/helm-env
verify: false
register: install_env
- assert:
that:
- install_env.changed
- name: Gather info about all plugin
helm_plugin_info:
binary_path: "{{ helm_binary }}"
register: plugin_info
- assert:
that:
- plugin_info.plugin_list is defined
- name: Install env plugin again
helm_plugin:
binary_path: "{{ helm_binary }}"
state: present
plugin_path: https://github.com/adamreese/helm-env
verify: false
register: install_env
- assert:
that:
- not install_env.changed
- name: Uninstall env plugin in check mode
helm_plugin:
binary_path: "{{ helm_binary }}"
state: absent
plugin_name: env
verify: false
register: check_uninstall_env
check_mode: true
- assert:
that:
- check_uninstall_env.changed
- name: Uninstall env plugin
helm_plugin:
binary_path: "{{ helm_binary }}"
state: absent
plugin_name: env
register: uninstall_env
- assert:
that:
- uninstall_env.changed
- name: Uninstall env plugin again
helm_plugin:
binary_path: "{{ helm_binary }}"
state: absent
plugin_name: env
register: uninstall_env
- assert:
that:
- not uninstall_env.changed
always:
- name: Uninstall env plugin
helm_plugin:
binary_path: "{{ helm_binary }}"
state: absent
plugin_name: env
# https://github.com/ansible-collections/community.kubernetes/issues/399
- block:
- name: Copy required plugin files
copy:
src: "files/sample_plugin"
dest: "/tmp/helm_plugin_test/"
- name: Install sample_plugin from the directory
helm_plugin:
binary_path: "{{ helm_binary }}"
state: present
plugin_path: "/tmp/helm_plugin_test/sample_plugin"
register: sample_plugin_output
- name: Assert that sample_plugin is installed or not
assert:
that:
- sample_plugin_output.changed
- name: Gather Helm plugin info
helm_plugin_info:
binary_path: "{{ helm_binary }}"
register: r
- name: Set sample_plugin version
set_fact:
plugin_version: "{{ ( r.plugin_list | selectattr('name', 'equalto', plugin_name) | list )[0].version }}"
vars:
plugin_name: "sample_plugin"
- name: Assert if sample_plugin with multiline comment is installed
assert:
that:
- plugin_version == "0.0.1"
always:
- name: Uninstall sample_plugin
helm_plugin:
binary_path: "{{ helm_binary }}"
state: absent
plugin_name: sample_plugin
ignore_errors: true
- block:
- name: uninstall helm plugin unittest
helm_plugin:
binary_path: "{{ helm_binary }}"
plugin_name: unittest
state: absent
- name: install helm-unittest on a specific version
helm_plugin:
binary_path: "{{ helm_binary }}"
plugin_path: https://github.com/helm-unittest/helm-unittest
plugin_version: v1.0.1
verify: false
state: present
- name: list helm plugin
helm_plugin_info:
plugin_name: unittest
binary_path: "{{ helm_binary }}"
register: plugin_list
- name: assert that unittest has been installed with specified version
assert:
that:
- plugin_list.plugin_list[0].version == "1.0.1"
- name: Update helm plugin version to latest (check mode)
helm_plugin:
binary_path: "{{ helm_binary }}"
plugin_name: unittest
state: latest
register: _update_checkmode
check_mode: true
- name: Assert that module reported change while running in check mode
assert:
that:
- _update_checkmode.changed
- '"Updated plugin: unittest" not in _update_checkmode.stdout'
- name: Update helm plugin version to latest
helm_plugin:
binary_path: "{{ helm_binary }}"
plugin_name: unittest
state: latest
register: _update
- name: assert update was performed
assert:
that:
- _update.changed
- '"Updated plugin: unittest" in _update.stdout'
always:
- name: Uninstall sample_plugin
helm_plugin:
binary_path: "{{ helm_binary }}"
state: absent
plugin_name: unittest

View File

@@ -5,7 +5,7 @@
- 3.8.0
- 3.1.0
- 3.0.0
- 2.3.0
- 4.0.0
- block:
- name: Create temp directory for helm tests
@@ -20,37 +20,13 @@
- set_fact:
destination: "{{ temp_dir }}"
- name: Create Helm directories
file:
state: directory
path: "{{ temp_dir }}/{{ item }}"
with_items: "{{ helm_versions }}"
- name: Unarchive Helm binary
unarchive:
src: "https://get.helm.sh/helm-v{{ item }}-linux-amd64.tar.gz"
dest: "{{ temp_dir }}/{{ item }}"
remote_src: yes
with_items: "{{ helm_versions }}"
# Testing helm pull with helm version == 2.3.0
- block:
- name: Assert that helm pull failed with helm <= 3.0.0
helm_pull:
binary_path: "{{ helm_path }}"
chart_ref: https://github.com/grafana/helm-charts/releases/download/grafana-5.6.0/grafana-5.6.0.tgz
destination: "{{ destination }}"
ignore_errors: true
register: _result
- name: assert that module failed with proper message
assert:
that:
- _result is failed
- _result.msg == "This module requires helm >= 3.0.0, current version is 2.3.0"
- name: Install Helm versions
ansible.builtin.include_role:
name: install_helm
loop: "{{ helm_versions }}"
vars:
helm_path: "{{ temp_dir }}/2.3.0/linux-amd64/helm"
helm_version: "v{{ item }}"
helm_install_path: "{{ temp_dir }}/{{ item }}"
# Testing helm pull with helm version == 3.0.0
- block:
@@ -103,7 +79,7 @@
- _result.msg == "Parameter chart_ca_cert requires helm >= 3.1.0, current version is 3.0.0"
vars:
helm_path: "{{ temp_dir }}/3.0.0/linux-amd64/helm"
helm_path: "{{ temp_dir }}/3.0.0/helm"
# Testing helm pull with helm version == 3.1.0
- block:
@@ -143,7 +119,7 @@
- _result.msg == "Parameter skip_tls_certs_check requires helm >= 3.3.0, current version is 3.1.0"
vars:
helm_path: "{{ temp_dir }}/3.1.0/linux-amd64/helm"
helm_path: "{{ temp_dir }}/3.1.0/helm"
# Testing helm pull with helm version == 3.8.0
- block:
@@ -221,8 +197,103 @@
- _chart.stat.exists
- _chart.stat.isdir
# Test idempotency with tarred chart
- name: Download chart with version (first time)
helm_pull:
binary_path: "{{ helm_path }}"
chart_ref: "oci://registry-1.docker.io/bitnamicharts/redis"
destination: "{{ destination }}"
chart_version: "24.1.0"
register: _result_first
- name: Download chart with version (second time - should be idempotent)
helm_pull:
binary_path: "{{ helm_path }}"
chart_ref: "oci://registry-1.docker.io/bitnamicharts/redis"
destination: "{{ destination }}"
chart_version: "24.1.0"
register: _result_second
- name: Validate idempotency for tarred chart
assert:
that:
- _result_first is changed
- _result_second is not changed
# Test force parameter with tarred chart
- name: Download chart with force=true (should always download)
helm_pull:
binary_path: "{{ helm_path }}"
chart_ref: "oci://registry-1.docker.io/bitnamicharts/redis"
destination: "{{ destination }}"
chart_version: "24.1.0"
force: true
register: _result_force
- name: Validate force parameter causes download
assert:
that:
- _result_force is changed
# Test idempotency with untarred chart in the separate folder
- name: Create separate directory for untar test under {{ temp_dir }}
ansible.builtin.file:
path: "{{ destination }}/untar_test"
state: directory
mode: '0755'
- name: Download and untar chart (first time)
helm_pull:
binary_path: "{{ helm_path }}"
chart_ref: "oci://registry-1.docker.io/bitnamicharts/redis"
destination: "{{ destination }}/untar_test"
chart_version: "24.0.0"
untar_chart: true
register: _result_untar_first
- name: Download and untar chart (second time - should be idempotent)
helm_pull:
binary_path: "{{ helm_path }}"
chart_ref: "oci://registry-1.docker.io/bitnamicharts/redis"
destination: "{{ destination }}/untar_test"
chart_version: "24.0.0"
untar_chart: true
register: _result_untar_second
- name: Validate idempotency for untarred chart
assert:
that:
- _result_untar_first is changed
- _result_untar_second is not changed
- name: Download and untar chart with force=true (should remove existing directory and re-extract)
helm_pull:
binary_path: "{{ helm_path }}"
chart_ref: "oci://registry-1.docker.io/bitnamicharts/redis"
destination: "{{ destination }}/untar_test"
chart_version: "24.0.0"
untar_chart: true
force: true
register: _result_untar_force
- name: Validate first force extraction works
assert:
that:
- _result_untar_force is changed
- name: Verify chart directory still exists after force re-extraction
stat:
path: "{{ destination }}/untar_test/redis"
register: _chart_after_force
- name: Validate chart directory exists
assert:
that:
- _chart_after_force.stat.exists
- _chart_after_force.stat.isdir
vars:
helm_path: "{{ temp_dir }}/3.8.0/linux-amd64/helm"
helm_path: "{{ temp_dir }}/3.8.0/helm"
always:

View File

@@ -5,5 +5,9 @@ username: testuser
password: testpassword
wrong_password: 'WrongPassword'
registry_name: oci_registry
registry_port: 5000
registry_port: 5002
test_chart: https://github.com/grafana/helm-charts/releases/download/k8s-monitoring-1.6.8/k8s-monitoring-1.6.8.tgz
helm_versions:
- v3.17.0
- v3.20.0
- v4.0.0

View File

@@ -1,3 +0,0 @@
---
dependencies:
- install_helm

View File

@@ -1,178 +0,0 @@
---
- name: Run module test
# using a shell and command module to run the test as test can be non-idempotent
# and it allow to not install any additional dependencies
block:
- name: Ensure that helm is installed
ansible.builtin.shell: helm version --client --short | grep v3
register: _helm_version
failed_when: _helm_version.rc != 0
- name: Ensure that Docker demon is running
ansible.builtin.command: "docker info"
register: _docker_info
failed_when: _docker_info.rc != 0
- name: Create a tmpfile htpasswd directory
ansible.builtin.tempfile:
state: directory
suffix: .httppasswd
register: _tmpfile
- name: Copy htpasswd to the tmpfile directory
ansible.builtin.copy:
src: registry.password
dest: "{{ _tmpfile.path }}/registry.password"
- name: Setup the registry
ansible.builtin.command: >-
docker run -d --rm
-p {{ registry_port }}:5000
--name "{{ registry_name }}"
-v "{{ _tmpfile.path }}:/auth"
-e "REGISTRY_AUTH=htpasswd"
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm"
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/registry.password
registry:2
register: _setup_registry
failed_when: _setup_registry.rc != 0
- name: Ensure that the registry is running and rechable
ansible.builtin.wait_for:
host: localhost
port: "{{ registry_port }}"
- name: Test the registry with correct credentials to ensure that the registry is running
ansible.builtin.shell: >-
echo {{ password | quote }} | helm registry login localhost:{{ registry_port }}
-u {{ username }} --password-stdin
register: _login_correct
failed_when: _login_correct.rc != 0
- name: Clean up credentials to run test on clean environment
ansible.builtin.shell: >-
helm registry logout localhost:{{ registry_port }}
register: _logout
failed_when: _logout.rc != 0
- name: Create directory for helm chart
ansible.builtin.tempfile:
state: directory
suffix: ".helm"
register: _destination
- name: Pull test helm chart
ansible.builtin.uri:
url: "{{ test_chart }}"
dest: "{{ _destination.path }}/k8s-monitoring-1.6.8.tgz"
return_content: no
status_code: 200
- name: Test module helm_registry_auth with correct credentials
helm_registry_auth:
username: "{{ username }}"
password: "{{ password }}"
host: localhost:{{ registry_port }}
state: present
register: _helm_registry_auth_correct
- name: Assert that the registry is logged in
# Helm binary prints the message to stderr, refence: https://github.com/helm/helm/issues/13464
assert:
that:
- "'Login Succeeded' in _helm_registry_auth_correct.stderr"
- "'{{ password }}' not in _helm_registry_auth_correct.command"
- "'{{ password }}' not in _helm_registry_auth_correct.stdout"
- "'{{ password }}' not in _helm_registry_auth_correct.stderr"
- name: Ensure that push to the registry is working
ansible.builtin.shell: >-
helm push "{{ _destination.path }}/k8s-monitoring-1.6.8.tgz" oci://localhost:{{ registry_port }}/test/
register: _save_chart
failed_when: _save_chart.rc != 0
- name: Assert that the chart is saved
# Helm binary prints the message to stderr, refence: https://github.com/helm/helm/issues/13464
assert:
that: "'Pushed: localhost:{{ registry_port }}/test/k8s-monitoring' in _save_chart.stderr"
- name: Test logout
helm_registry_auth:
host: localhost:{{ registry_port }}
state: absent
register: _helm_registry_auth_logout
- name: Assert logout
# Helm binary prints the message to stderr
assert:
that: "'Removing login credentials' in _helm_registry_auth_logout.stderr"
- name: Test logout idempotency
helm_registry_auth:
host: localhost:{{ registry_port }}
state: absent
register: _helm_registry_auth_logout_idempotency
- name: Assert logout operation did not report change
ansible.builtin.assert:
that: _helm_registry_auth_logout_idempotency is not changed
- name: Ensure that not able to push to the registry
ansible.builtin.shell: >-
helm push "{{ _destination.path }}/k8s-monitoring-1.6.8.tgz" oci://localhost:{{ registry_port }}/test/
register: _save_chart
failed_when: _save_chart.rc == 0
- name: Read content of ~/.config/helm/registry/config.json
ansible.builtin.slurp:
src: ~/.config/helm/registry/config.json
register: _config_json
- name: Assert that auth data is remove and the chart is not saved
# Helm binary prints the message to stderr
ansible.builtin.assert:
that:
- "'push access denied' in _save_chart.stderr"
- "'authorization failed' in _save_chart.stderr"
- "_save_chart.rc != 0"
- "'localhost:{{ registry_port }}' not in _config_json.content | b64decode"
- name: Test module helm_registry_auth with wrong credentials
helm_registry_auth:
username: "{{ username }}"
password: "{{ wrong_password }}"
host: localhost:{{ registry_port }}
state: present
register: _helm_registry_auth_wrong
ignore_errors: true
- name: Read content of ~/.config/helm/registry/config.json
ansible.builtin.slurp:
src: ~/.config/helm/registry/config.json
register: _config_json
- name: Assert that the registry is not logged in and auth data is not saved
ansible.builtin.assert:
that:
- "'401 Unauthorized' in _helm_registry_auth_wrong.stderr"
- "'{{ wrong_password }}' not in _helm_registry_auth_correct.command"
- "'{{ wrong_password }}' not in _helm_registry_auth_correct.stdout"
- "'{{ wrong_password }}' not in _helm_registry_auth_correct.stderr"
- "'localhost:{{ registry_port }}' not in _config_json.content | b64decode"
# Clean up
always:
- name: Stop and remove the registry
ansible.builtin.command: docker stop {{ registry_name }}
ignore_errors: true
- name: Remove the tmpfile
ansible.builtin.file:
state: absent
path: "{{ item }}"
force: true
loop:
- "{{ _tmpfile.path }}"
- "{{ _destination.path }}"
ignore_errors: true

View File

@@ -0,0 +1,60 @@
---
- name: Run tests for helm_registry_auth with different helm versions
block:
- name: Create temporary directory to install helm binaries
ansible.builtin.tempfile:
state: directory
suffix: .helm
register: _tmpdir
- name: Ensure that Docker demon is running
ansible.builtin.command: "docker info"
register: _docker_info
failed_when: _docker_info.rc != 0
- name: Copy htpasswd to the tmpfile directory
ansible.builtin.copy:
src: registry.password
dest: "{{ _tmpdir.path }}/registry.password"
- name: Pull test helm chart
ansible.builtin.uri:
url: "{{ test_chart }}"
dest: "{{ _tmpdir.path }}/k8s-monitoring-1.6.8.tgz"
return_content: no
status_code: 200
- name: Setup the registry
ansible.builtin.command: >-
docker run -d --rm
-p {{ registry_port }}:5000
--name "{{ registry_name }}"
-v "{{ _tmpdir.path }}:/auth"
-e "REGISTRY_AUTH=htpasswd"
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm"
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/registry.password
registry:2
register: _setup_registry
failed_when: _setup_registry.rc != 0
- name: Ensure that the registry is running and rechable
ansible.builtin.wait_for:
host: localhost
port: "{{ registry_port }}"
- name: Run tests
ansible.builtin.include_tasks: run_tests.yml
loop: "{{ helm_versions }}"
loop_control:
loop_var: helm_version
always:
- name: Stop and remove the registry
ansible.builtin.command: docker stop {{ registry_name }}
ignore_errors: true
- name: Delete temporary directory
ansible.builtin.file:
state: absent
path: "{{ _tmpdir.path }}"
ignore_errors: true

View File

@@ -0,0 +1,108 @@
---
- block:
- name: Install helm versions
ansible.builtin.include_role:
name: install_helm
# - name: Test the registry with correct credentials to ensure that the registry is running
# ansible.builtin.shell: >-
# echo {{ password | quote }} | {{ helm_binary }} registry login localhost:{{ registry_port }}
# -u {{ username }} --password-stdin --plain-http
# register: _login_correct
# failed_when: _login_correct.rc != 0
# - name: Clean up credentials to run test on clean environment
# ansible.builtin.shell: >-
# {{ helm_binary }} registry logout localhost:{{ registry_port }}
# register: _logout
# failed_when: _logout.rc != 0
- name: Test module helm_registry_auth with correct credentials
helm_registry_auth:
binary_path: "{{ helm_binary }}"
username: "{{ username }}"
password: "{{ password }}"
host: localhost:{{ registry_port }}
plain_http: true
state: present
register: _helm_registry_auth_correct
- name: Assert that the registry is logged in
# Helm binary prints the message to stderr, refence: https://github.com/helm/helm/issues/13464
assert:
that:
- "'Login Succeeded' in _helm_registry_auth_correct.stdout_lines + _helm_registry_auth_correct.stderr_lines"
- password not in _helm_registry_auth_correct.command
- password not in _helm_registry_auth_correct.stdout
- password not in _helm_registry_auth_correct.stderr
- name: Ensure that push to the registry is working
ansible.builtin.shell: >-
{{ helm_binary }} push --plain-http "{{ _tmpdir.path }}/k8s-monitoring-1.6.8.tgz" oci://localhost:{{ registry_port }}/test/
register: _save_chart
failed_when: _save_chart.rc != 0
- name: Assert that the chart is saved
# Helm binary prints the message to stderr, refence: https://github.com/helm/helm/issues/13464
assert:
that: "'Pushed: localhost:' + registry_port | string + '/test/k8s-monitoring' in _save_chart.stderr"
- name: Test logout
helm_registry_auth:
binary_path: "{{ helm_binary }}"
host: localhost:{{ registry_port }}
state: absent
register: _helm_registry_auth_logout
- name: Assert logout
# Helm binary prints the message to stderr
assert:
that: "'Removing login credentials' in _helm_registry_auth_logout.stderr"
- name: Ensure that not able to push to the registry
ansible.builtin.shell: >-
{{ helm_binary }} push --plain-http "{{ _tmpdir.path }}/k8s-monitoring-1.6.8.tgz" oci://localhost:{{ registry_port }}/test/
register: _save_chart
failed_when: _save_chart.rc == 0
- name: Assert that auth data is remove and the chart is not saved
# Helm binary prints the message to stderr
ansible.builtin.assert:
that:
- "'push access denied' in _save_chart.stderr or 'basic credential not found' in _save_chart.stderr"
- "_save_chart.rc != 0"
- name: Test idempotency of logout with helm < 3.18.0
when: helm_version is ansible.builtin.version('v3.18.0', '<')
block:
- name: Test logout idempotency
helm_registry_auth:
binary_path: "{{ helm_binary }}"
host: localhost:{{ registry_port }}
state: absent
register: _helm_registry_auth_logout_idempotency
- name: Assert logout operation did not report change
ansible.builtin.assert:
that: _helm_registry_auth_logout_idempotency is not changed
- name: Test module helm_registry_auth with wrong credentials
helm_registry_auth:
binary_path: "{{ helm_binary }}"
username: "{{ username }}"
password: "{{ wrong_password }}"
host: localhost:{{ registry_port }}
state: present
plain_http: true
register: _helm_registry_auth_wrong
ignore_errors: true
- name: Assert that the registry is not logged in and auth data is not saved
ansible.builtin.assert:
that:
- "'401' in _helm_registry_auth_wrong.stderr"
- "'unauthorized' in _helm_registry_auth_wrong.stderr | lower"
- "'{{ wrong_password }}' not in _helm_registry_auth_correct.command"
- "'{{ wrong_password }}' not in _helm_registry_auth_correct.stdout"
- "'{{ wrong_password }}' not in _helm_registry_auth_correct.stderr"

View File

@@ -1,5 +1,2 @@
time=20
helm_repository
helm_info
helm
helm_template
time=1
helm_repository

View File

@@ -1,3 +1,5 @@
---
chart_test_repo: "https://kubernetes.github.io/ingress-nginx"
helm_binary: "/tmp/helm/{{ ansible_system | lower }}-amd64/helm"
helm_versions:
- v3.20.0
- v4.0.0

View File

@@ -1,5 +0,0 @@
---
collections:
- kubernetes.core
dependencies:
- install_helm

View File

@@ -1,101 +1,6 @@
---
- name: "Ensure test_helm_repo doesn't exist"
helm_repository:
binary_path: "{{ helm_binary }}"
name: test_helm_repo
state: absent
- name: Add test_helm_repo chart repository
helm_repository:
binary_path: "{{ helm_binary }}"
name: test_helm_repo
repo_url: "{{ chart_test_repo }}"
register: repository
- name: Assert that test_helm_repo repository is added
assert:
that:
- repository is changed
- '"--insecure-skip-tls-verify" not in repository.command'
- name: Check idempotency
helm_repository:
binary_path: "{{ helm_binary }}"
name: test_helm_repo
repo_url: "{{ chart_test_repo }}"
register: repository
- name: Assert idempotency
assert:
that:
- repository is not changed
- name: Failed to add repository with the same name
helm_repository:
binary_path: "{{ helm_binary }}"
name: test_helm_repo
repo_url: "https://other-charts.url"
register: repository_errors
ignore_errors: yes
- name: Assert that adding repository with the same name failed
assert:
that:
- repository_errors is failed
- name: Succesfully add repository with the same name when forcing
helm_repository:
binary_path: "{{ helm_binary }}"
name: test_helm_repo
repo_url: "{{ chart_test_repo }}"
force: true
register: repository
- name: Assert that test_helm_repo repository is changed
assert:
that:
- repository is changed
- name: Remove test_helm_repo chart repository
helm_repository:
binary_path: "{{ helm_binary }}"
name: test_helm_repo
state: absent
register: repository
- name: Assert that test_helm_repo repository is removed
assert:
that:
- repository is changed
- name: Check idempotency after remove
helm_repository:
binary_path: "{{ helm_binary }}"
name: test_helm_repo
state: absent
register: repository
- name: Assert idempotency
assert:
that:
- repository is not changed
- name: Add test_helm_repo chart repository as insecure
helm_repository:
binary_path: "{{ helm_binary }}"
name: test_helm_repo
repo_url: "{{ chart_test_repo }}"
insecure_skip_tls_verify: true
register: repository
- name: Assert that repository added and flag set
assert:
that:
- repository is changed
- '"--insecure-skip-tls-verify" in repository.command'
- name: Clean test_helm_repo chart repository
helm_repository:
binary_path: "{{ helm_binary }}"
name: test_helm_repo
state: absent
- name: Run test for helm_repository module
ansible.builtin.include_tasks: run_tests.yml
loop: "{{ helm_versions }}"
loop_control:
loop_var: helm_version

Some files were not shown because too many files have changed in this diff Show More