Compare commits

37 Commits
main ... 6.3.0

Author SHA1 Message Date
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
Bianca Henderson
8fa5b201a4 Prep release 6.0.0 (#933)
SUMMARY

Prep kubernetes.core 6.0.0
Prerequisite: Release of community.okd/redhat.openshift 4.0.2 needs to happen first

ISSUE TYPE


Feature Pull Request

COMPONENT NAME
Multiple

Reviewed-by: Bikouo Aubin
2025-06-03 16:56:33 +00:00
120 changed files with 1402 additions and 3201 deletions

View File

@@ -55,14 +55,13 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
# Ref must match a branch/tag on github.com/ansible/ansible (e.g. stable-2.18, not 2.18). ansible-version:
ansible-version: ["stable-2.18", "milestone"] - milestone
enable-turbo-mode: [true, false]
exclude:
- ansible-version: "milestone"
enable-turbo-mode: true
python-version: python-version:
- "3.12" - "3.12"
enable-turbo-mode:
- true
- false
workflow-id: ${{ fromJson(needs.splitter.outputs.test_jobs) }} workflow-id: ${{ fromJson(needs.splitter.outputs.test_jobs) }}
name: "integration-py${{ matrix.python-version }}-${{ matrix.ansible-version }}-${{ matrix.workflow-id }}-enable_turbo=${{ matrix.enable-turbo-mode }}" name: "integration-py${{ matrix.python-version }}-${{ matrix.ansible-version }}-${{ matrix.workflow-id }}-enable_turbo=${{ matrix.enable-turbo-mode }}"
steps: steps:
@@ -108,7 +107,6 @@ jobs:
source_path: ${{ env.source }} source_path: ${{ env.source }}
- name: checkout ansible-collections/cloud.common - name: checkout ansible-collections/cloud.common
if: ${{ matrix.enable-turbo-mode == true }}
uses: ansible-network/github_actions/.github/actions/checkout_dependency@main uses: ansible-network/github_actions/.github/actions/checkout_dependency@main
with: with:
repository: ansible-collections/cloud.common repository: ansible-collections/cloud.common
@@ -130,7 +128,6 @@ jobs:
ref: main ref: main
- name: install cloud.common collection - name: install cloud.common collection
if: ${{ matrix.enable-turbo-mode == true }}
uses: ansible-network/github_actions/.github/actions/build_install_collection@main uses: ansible-network/github_actions/.github/actions/build_install_collection@main
with: with:
install_python_dependencies: true install_python_dependencies: true

View File

@@ -1,18 +0,0 @@
---
name: label new issues
on:
issues:
types:
- opened
- reopened
jobs:
add_label:
runs-on: ubuntu-latest
permissions:
contents: write
issues: write
steps:
- uses: actions-ecosystem/action-add-labels@v1
with:
labels: needs_triage

View File

@@ -1,70 +0,0 @@
---
# SonarCloud analysis for kubernetes.core
#
# Uses the same-repo + default-branch push model: GitHub does not expose org secrets to workflows
# from fork PRs (see https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions).
# This job is gated so the Sonar token is never available in untrusted fork contexts. A follow-up
# workflow triggered by workflow_run + artifacts is an alternative if the org later requires Sonar
# with coverage on fork PRs (see https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run).
name: SonarCloud
on:
push:
branches:
- main
- stable-*
pull_request:
branches:
- main
- stable-*
workflow_dispatch:
permissions:
contents: read
pull-requests: read
jobs:
sonarqube:
name: SonarCloud Scan
runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
env:
# Pin ansible-test behavior; bump when raising supported ansible-core (see meta/runtime.yml).
ANSIBLE_CORE_VERSION: "2.19.5"
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install Ansible (ansible-test)
run: |
pip install --upgrade pip
pip install "ansible-core==${ANSIBLE_CORE_VERSION}"
- name: Unit tests with coverage
run: ansible-test units --venv --coverage --python 3.12 --requirements
- name: Coverage combine and XML for Sonar
run: |
ansible-test coverage combine --venv --python 3.12 --requirements
ansible-test coverage xml --venv --python 3.12 --requirements
- name: Copy coverage report to repo root
run: |
set -euo pipefail
ls -la tests/output/reports/
xml=$(find tests/output/reports -maxdepth 1 -name '*.xml' ! -name '*powershell*' | head -1)
test -n "$xml"
cp "$xml" coverage.xml
- name: SonarCloud Scan
# Same pinned version as ansible-collections/amazon.aws sonarcloud.yml
uses: SonarSource/sonarqube-scan-action@a31c9398be7ace6bbfaf30c0bd5d415f843d45e9
env:
SONAR_TOKEN: ${{ secrets.ANSIBLE_COLLECTIONS_ORG_SONAR_TOKEN_CICD_BOT }}

4
.gitignore vendored
View File

@@ -17,7 +17,6 @@ tests/integration/cloud-config-*
# Helm charts # Helm charts
tests/integration/*-chart-*.tgz tests/integration/*-chart-*.tgz
tests/integration/targets/*/*.tgz
# ansible-test generated file # ansible-test generated file
tests/integration/inventory tests/integration/inventory
@@ -25,6 +24,3 @@ tests/integration/*-*.yml
# VS Code settings # VS Code settings
.vscode/ .vscode/
# Root coverage report for SonarCloud (generated locally or in CI)
/coverage.xml

View File

@@ -4,32 +4,6 @@ Kubernetes Collection Release Notes
.. contents:: Topics .. contents:: Topics
v6.4.0
======
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.
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 v6.3.0
====== ======
@@ -112,52 +86,12 @@ Bugfixes
v6.0.0 v6.0.0
====== ======
Release Summary
---------------
This major release removes the deprecated ``k8s`` inventory plugin and also removes ``ansible-core<2.16`` support.
Breaking Changes / Porting Guide Breaking Changes / Porting Guide
-------------------------------- --------------------------------
- Remove deprecated ``k8s`` invetory plugin (https://github.com/ansible-collections/kubernetes.core/pull/867). - Remove deprecated ``k8s`` invetory plugin (https://github.com/ansible-collections/kubernetes.core/pull/867).
- Remove support for ``ansible-core<2.16`` (https://github.com/ansible-collections/kubernetes.core/pull/867). - Remove support for ``ansible-core<2.16`` (https://github.com/ansible-collections/kubernetes.core/pull/867).
v5.4.2
======
Release Summary
---------------
This release includes bugfixes such as replacing the passing of ``warnings`` to ``exit_json`` with ``AnsibleModule.warn`` as well as a security update for selectively redacting sensitive information from kubeconfig.
Minor Changes
-------------
- 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).
v5.4.1 v5.4.1
====== ======
@@ -184,7 +118,7 @@ This release updates the ``helm_registry_auth`` module to match the behavior of
Minor 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). - Module ``helm_registry_auth`` does not support idempotency with ``helm >= 3.18.0`` (https://github.com/ansible-collections/kubernetes.core/pull/946)
v5.3.0 v5.3.0
====== ======

32
CI.md
View File

@@ -1,32 +0,0 @@
# Continuous Integration (CI)
## Kubernetes Upstream Testing
GitHub Actions are used to run the CI for the kubernetes.core collection. The workflows used for the CI can be found in the [.github/workflows](.github/workflows) directory.
### PR Testing Workflows
The following tests run on every pull request:
| Job | Description | Python Versions | ansible-core Versions |
| --- | ----------- | --------------- | --------------------- |
| [Changelog](.github/workflows/changelog.yaml) | Checks for the presence of changelog fragments | 3.12 | devel |
| [Linters](.github/workflows/linters.yaml) | Runs `black`, `flake8`, `isort`, `yamllint`, and `ansible-lint` on plugins and tests | 3.10 | devel |
| [Sanity](.github/workflows/sanity-tests.yaml) | Runs ansible sanity checks | See compatibility table below | devel, stable-2.18, stable-2.19, stable-2.20 |
| [Unit tests](.github/workflows/unit-tests.yaml) | Executes unit test cases | See compatibility table below | devel, stable-2.16, stable-2.17, stable-2.18, stable-2.19, stable-2.20 |
| [Integration](.github/workflows/integration-tests.yaml) | Executes integration test suites using KinD cluster (split across 8 jobs, tests with Turbo mode enabled/disabled) | 3.12 | milestone |
**Note:** Integration tests require a KinD (Kubernetes in Docker) cluster and test both with Turbo mode enabled and disabled.
### Python Version Compatibility by ansible-core Version
These are outlined in the collection's [tox.ini](tox.ini) file (`envlist`) and GitHub Actions workflow exclusions.
| ansible-core Version | Sanity Tests | Unit Tests |
| -------------------- | ------------ | ---------- |
| devel | 3.12, 3.13, 3.14 | 3.12, 3.13 |
| stable-2.20 | 3.12, 3.13, 3.14 | 3.12, 3.13, 3.14 |
| stable-2.19 | 3.11, 3.12, 3.13 | 3.11, 3.12, 3.13 |
| stable-2.18 | 3.11, 3.12, 3.13 | 3.11, 3.12, 3.13 |
| stable-2.17 | 3.10, 3.11, 3.12 | 3.10, 3.11, 3.12 |
| stable-2.16 | 3.10, 3.11 | 3.10, 3.11 |

View File

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

View File

@@ -6,24 +6,6 @@ This repository hosts the `kubernetes.core` (formerly known as `community.kubern
The collection includes a variety of Ansible content to help automate the management of applications in Kubernetes and OpenShift clusters, as well as the provisioning and maintenance of clusters themselves. The collection includes a variety of Ansible content to help automate the management of applications in Kubernetes and OpenShift clusters, as well as the provisioning and maintenance of clusters themselves.
## SonarCloud (code quality)
Static analysis runs on [SonarCloud](https://sonarcloud.io) using `sonar-project.properties` and
`.github/workflows/sonarcloud.yml`. Coverage shown in Sonar comes from unit-test coverage exported as
`coverage.xml` at the repository root during CI.
The SonarCloud project key must match `sonar.projectKey` (`ansible-collections_kubernetes.core`). Adding
or renaming the project is coordinated via Ansible Collections maintainers.
GitHub does not expose organization secrets to workflows for pull requests opened from forks. The
Sonar job therefore only runs on pushes to this repository's branches and on pull requests where the
head branch is on `ansible-collections/kubernetes.core` (not from forks). That matches GitHub's
documented behavior for [secrets in Actions](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions).
If the project later needs Sonar with coverage on **fork** PRs, maintainers typically add a separate
trusted job after a workflow that uploads coverage artifacts, using GitHub's `workflow_run` event.
See [workflow_run (GitHub Docs)](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run).
## Communication ## Communication
* Join the Ansible forum: * Join the Ansible forum:
@@ -50,7 +32,7 @@ PEP440 is the schema used to describe the versions of Ansible.
### Helm Version Compatibility ### Helm Version Compatibility
This collection supports Helm v3.x and newer. Please note that specific modules or certain parameters may have additional version requirements. Helm modules in this collection are compatible with Helm v3.x and are not yet compatible with Helm v4. Individual modules and their parameters may support a more specific range of Helm versions.
### Python Support ### Python Support
@@ -121,7 +103,7 @@ You can also include it in a `requirements.yml` file and install it via `ansible
--- ---
collections: collections:
- name: kubernetes.core - name: kubernetes.core
version: 6.4.0 version: 6.3.0
``` ```
### Installing the Kubernetes Python Library ### Installing the Kubernetes Python Library

View File

@@ -1027,15 +1027,15 @@ releases:
changes: changes:
bugfixes: bugfixes:
- module_utils/k8s/service - fix issue when trying to delete resource using - 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: 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 - action/k8s_info - update templating mechanism with changes from ``ansible-core
2.19`` (https://github.com/ansible-collections/kubernetes.core/pull/888). 2.19`` (https://github.com/ansible-collections/kubernetes.core/pull/888).
- helm - add ``reset_then_reuse_values`` support to helm module (https://github.com/ansible-collections/kubernetes.core/issues/803). - helm - add reset_then_reuse_values support to helm module (https://github.com/ansible-collections/kubernetes.core/issues/803).
- helm - add support for ``insecure_skip_tls_verify`` option to helm and helm_repository(https://github.com/ansible-collections/kubernetes.core/issues/694). - helm - add support for ``insecure_skip_tls_verify`` option to helm and helm_repository(https://github.com/ansible-collections/kubernetes.core/issues/694).
release_summary: This release includes minor changes, bug fixes and also bumps 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: fragments:
- 20250324-k8s_info-templating.yaml - 20250324-k8s_info-templating.yaml
- 5.3.0.yml - 5.3.0.yml
@@ -1062,7 +1062,7 @@ releases:
changes: changes:
bugfixes: bugfixes:
- Remove ``ansible.module_utils.six`` imports to avoid warnings (https://github.com/ansible-collections/kubernetes.core/pull/998). - 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). - 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). - 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, release_summary: This release includes bugfixes for k8s service field handling,
k8s_cp init containers support, and removes deprecated ansible.module_utils.six k8s_cp init containers support, and removes deprecated ansible.module_utils.six
@@ -1073,49 +1073,6 @@ releases:
- 20250922-remove-ansible-six-imports.yaml - 20250922-remove-ansible-six-imports.yaml
- 5.4.1.yml - 5.4.1.yml
release_date: '2025-10-07' release_date: '2025-10-07'
5.4.2:
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:
- helm - added ``release_values`` key to ``status`` return value that can be
accessed using Jinja2 dot notation (https://github.com/ansible-collections/kubernetes.core/pull/1056).
- helm_info - added ``release_values`` key to ``status`` return value that can
be accessed using Jinja2 dot notation (https://github.com/ansible-collections/kubernetes.core/pull/1056).
release_summary: This release includes various bugfixes such as replacing the
passing of ``warnings`` to ``exit_json`` with ``AnsibleModule.warn`` as well
as security updates for selectively redacting sensitive information from kubeconfig.
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
- 20260107-add-idempodency-for-helm-pull.yaml
- 20260108-fix-sanity-failures.yml
- 5-4-2.yaml
release_date: '2026-02-03'
6.0.0: 6.0.0:
changes: changes:
breaking_changes: breaking_changes:
@@ -1129,9 +1086,9 @@ releases:
bugfixes: bugfixes:
- module_utils/k8s/service - hide fields first before creating diffs (https://github.com/ansible-collections/kubernetes.core/pull/915). - module_utils/k8s/service - hide fields first before creating diffs (https://github.com/ansible-collections/kubernetes.core/pull/915).
minor_changes: minor_changes:
- Module ``helm_registry_auth`` does not support idempotency with `helm >= 3.18.0` - Module helm_registry_auth do not support idempotency with `helm >= 3.18.0`
(https://github.com/ansible-collections/kubernetes.core/pull/946). (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). - 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 - helm - Parameter plain_http added for working with insecure OCI registries
(https://github.com/ansible-collections/kubernetes.core/pull/934). (https://github.com/ansible-collections/kubernetes.core/pull/934).
- helm - Parameter take_ownership added (https://github.com/ansible-collections/kubernetes.core/pull/957). - helm - Parameter take_ownership added (https://github.com/ansible-collections/kubernetes.core/pull/957).
@@ -1216,33 +1173,3 @@ releases:
- 20260108-fix-sanity-failures.yml - 20260108-fix-sanity-failures.yml
- 6-3-0.yaml - 6-3-0.yaml
release_date: '2026-02-03' 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

@@ -25,7 +25,7 @@ Requirements
------------ ------------
The below requirements are needed on the host that executes this module. The below requirements are needed on the host that executes this module.
- helm >= 3.0.0 (https://github.com/helm/helm/releases) - helm (https://github.com/helm/helm/releases)
- yaml (https://pypi.org/project/PyYAML/) - yaml (https://pypi.org/project/PyYAML/)
@@ -268,7 +268,7 @@ Examples
Return Values Return Values
------------- -------------
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: 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:
.. raw:: html .. raw:: html
@@ -410,23 +410,6 @@ Common return values are documented `here <https://docs.ansible.com/projects/ans
<br/> <br/>
</td> </td>
</tr> </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> <tr>
<td class="elbow-placeholder">&nbsp;</td> <td class="elbow-placeholder">&nbsp;</td>
<td colspan="1"> <td colspan="1">
@@ -482,13 +465,12 @@ Common return values are documented `here <https://docs.ansible.com/projects/ans
<b>values</b> <b>values</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a> <a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small"> <div style="font-size: small">
<span style="color: purple">dictionary</span> <span style="color: purple">string</span>
</div> </div>
</td> </td>
<td>always</td> <td>always</td>
<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/> <br/>
</td> </td>
</tr> </tr>

View File

@@ -25,7 +25,7 @@ Requirements
------------ ------------
The below requirements are needed on the host that executes this module. The below requirements are needed on the host that executes this module.
- helm >= 3.0.0 (https://github.com/helm/helm/releases) - helm (https://github.com/helm/helm/releases)
- yaml (https://pypi.org/project/PyYAML/) - yaml (https://pypi.org/project/PyYAML/)
@@ -660,7 +660,7 @@ Parameters
</ul> </ul>
</td> </td>
<td> <td>
<div>Helm will ignore the check for helm annotations and take ownership of the existing resources</div> <div>When upgrading, 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> <div>This feature requires helm &gt;= 3.17.0</div>
</td> </td>
</tr> </tr>
@@ -920,7 +920,7 @@ Examples
Return Values Return Values
------------- -------------
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: 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:
.. raw:: html .. raw:: html
@@ -1026,23 +1026,6 @@ Common return values are documented `here <https://docs.ansible.com/projects/ans
<br/> <br/>
</td> </td>
</tr> </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> <tr>
<td class="elbow-placeholder">&nbsp;</td> <td class="elbow-placeholder">&nbsp;</td>
<td colspan="1"> <td colspan="1">
@@ -1098,13 +1081,12 @@ Common return values are documented `here <https://docs.ansible.com/projects/ans
<b>values</b> <b>values</b>
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a> <a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
<div style="font-size: small"> <div style="font-size: small">
<span style="color: purple">dictionary</span> <span style="color: purple">string</span>
</div> </div>
</td> </td>
<td>always</td> <td>always</td>
<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/> <br/>
</td> </td>
</tr> </tr>

View File

@@ -25,7 +25,7 @@ Requirements
------------ ------------
The below requirements are needed on the host that executes this module. The below requirements are needed on the host that executes this module.
- helm >= 3.0.0 (https://github.com/helm/helm/releases) - helm (https://github.com/helm/helm/releases)
Parameters Parameters
@@ -196,7 +196,7 @@ Examples
Return Values Return Values
------------- -------------
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: 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:
.. raw:: html .. raw:: html

View File

@@ -25,7 +25,7 @@ Requirements
------------ ------------
The below requirements are needed on the host that executes this module. The below requirements are needed on the host that executes this module.
- helm >= 3.0.0 (https://github.com/helm/helm/releases) - helm (https://github.com/helm/helm/releases)
Parameters Parameters
@@ -231,28 +231,6 @@ Parameters
<div style="font-size: small; color: darkgreen"><br/>aliases: verify_ssl</div> <div style="font-size: small; color: darkgreen"><br/>aliases: verify_ssl</div>
</td> </td>
</tr> </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> </table>
<br/> <br/>
@@ -294,7 +272,7 @@ Examples
Return Values Return Values
------------- -------------
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: 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:
.. raw:: html .. raw:: html

View File

@@ -27,7 +27,7 @@ Requirements
------------ ------------
The below requirements are needed on the host that executes this module. The below requirements are needed on the host that executes this module.
- helm >= 3.0.0 (https://github.com/helm/helm/releases) - helm >= 3.0, <4.0.0 (https://github.com/helm/helm/releases)
Parameters Parameters

View File

@@ -25,7 +25,7 @@ Requirements
------------ ------------
The below requirements are needed on the host that executes this module. 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, <4.0.0
Parameters Parameters
@@ -151,27 +151,6 @@ Parameters
<div style="font-size: small; color: darkgreen"><br/>aliases: repo_password</div> <div style="font-size: small; color: darkgreen"><br/>aliases: repo_password</div>
</td> </td>
</tr> </tr>
<tr>
<td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>plain_http</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.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> <tr>
<td colspan="1"> <td colspan="1">
<div class="ansibleOptionAnchor" id="parameter-"></div> <div class="ansibleOptionAnchor" id="parameter-"></div>

View File

@@ -25,7 +25,7 @@ Requirements
------------ ------------
The below requirements are needed on the host that executes this module. The below requirements are needed on the host that executes this module.
- helm >= 3.0.0 (https://github.com/helm/helm/releases) - helm (https://github.com/helm/helm/releases)
- yaml (https://pypi.org/project/PyYAML/) - yaml (https://pypi.org/project/PyYAML/)
@@ -336,7 +336,7 @@ Examples
Return Values Return Values
------------- -------------
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: 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:
.. raw:: html .. raw:: html

View File

@@ -20,13 +20,6 @@ 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 Parameters
---------- ----------
@@ -437,7 +430,7 @@ Examples
Return Values Return Values
------------- -------------
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: 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:
.. raw:: html .. raw:: html

View File

@@ -701,21 +701,6 @@ Examples
wait_sleep: 10 wait_sleep: 10
wait_timeout: 360 wait_timeout: 360
- name: Wait for OpenShift bootstrap to complete
kubernetes.core.k8s_info:
api_version: v1
kind: ConfigMap
name: bootstrap
namespace: kube-system
register: ocp_bootstrap_status
until: >
ocp_bootstrap_status.resources is defined and
(ocp_bootstrap_status.resources | length > 0) and
(ocp_bootstrap_status.resources[0].data.status is defined) and
(ocp_bootstrap_status.resources[0].data.status == 'complete')
retries: 60
delay: 15
Return Values Return Values

View File

@@ -25,7 +25,7 @@ tags:
- openshift - openshift
- okd - okd
- cluster - cluster
version: 7.0.0-dev0 version: 6.3.0
build_ignore: build_ignore:
- .DS_Store - .DS_Store
- "*.tar.gz" - "*.tar.gz"

View File

@@ -40,20 +40,16 @@ def parse_helm_plugin_list(output=None):
if not output: if not output:
return ret return ret
parsing_grammar = None
for line in output: for line in output:
if line.startswith("NAME"): if line.startswith("NAME"):
parsing_grammar = [s.strip().lower() for s in line.split("\t")]
continue continue
if parsing_grammar is None: name, version, description = line.split("\t", 3)
name = name.strip()
version = version.strip()
description = description.strip()
if name == "":
continue continue
plugin = { ret.append((name, version, description))
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 return ret
@@ -206,35 +202,21 @@ class AnsibleHelmModule(object):
return m.group(1) return m.group(1)
return None return None
def is_helm_v4(self): def validate_helm_version(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 Validate that Helm version is >=3.0.0 and <4.0.0.
Helm v4 requires helm diff v3.14.0 Helm 4 is not yet supported.
"""
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() helm_version = self.get_helm_version()
if helm_version is None: if helm_version is None:
self.fail_json(msg="Unable to determine Helm version") self.fail_json(msg="Unable to determine Helm version")
if LooseVersion(helm_version) < LooseVersion(version): if (LooseVersion(helm_version) < LooseVersion("3.0.0")) or (
LooseVersion(helm_version) >= LooseVersion("4.0.0")
):
self.fail_json( self.fail_json(
msg="Helm version must be >= {0}, current version is {1}".format( msg="Helm version must be >=3.0.0,<4.0.0, current version is {0}".format(
version, helm_version helm_version
) )
) )

View File

@@ -1,91 +0,0 @@
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import hashlib
import os
import traceback
try:
import yaml
IMP_YAML = True
IMP_YAML_ERR = None
except ImportError:
IMP_YAML = False
IMP_YAML_ERR = traceback.format_exc()
def load_yaml_file(path):
if not path or not os.path.exists(path):
return {}
with open(path, "r") as f:
return yaml.safe_load(f) or {}
def deep_merge(base, updates):
result = base.copy()
for key, value in updates.items():
if key in result and isinstance(result[key], dict) and isinstance(value, dict):
result[key] = deep_merge(result[key], value)
else:
result[key] = value
return result
def merge_by_name(existing, new):
merged = {}
for item in existing:
if isinstance(item, dict) and "name" in item:
merged[item["name"]] = item
for item in new:
if not isinstance(item, dict) or "name" not in item:
continue
name = item["name"]
behavior = item.get("behavior", "merge")
item_copy = {k: v for k, v in item.items() if k != "behavior"}
if name in merged:
if behavior == "keep":
continue
elif behavior == "replace":
merged[name] = item_copy
else:
result = {"name": name}
for key in ["cluster", "user", "context"]:
if key in merged[name] or key in item_copy:
existing_config = merged[name].get(key, {})
new_config = item_copy.get(key, {})
result[key] = deep_merge(existing_config, new_config)
for key in merged[name]:
if key not in ["name", "cluster", "user", "context"]:
result[key] = merged[name][key]
for key in item_copy:
if (
key not in ["name", "cluster", "user", "context"]
and key not in result
):
result[key] = item_copy[key]
merged[name] = result
else:
merged[name] = item_copy
return list(merged.values())
def hash_data(data):
"""Generate SHA-256 hash for idempotency checking."""
return hashlib.sha256(yaml.safe_dump(data, sort_keys=True).encode()).hexdigest()
def write_file(dest, data):
if not dest:
return False
with open(dest, "w") as f:
yaml.safe_dump(data, f, sort_keys=False)
return True

View File

@@ -21,7 +21,7 @@ author:
- Matthieu Diehr (@d-matt) - Matthieu Diehr (@d-matt)
requirements: requirements:
- "helm >= 3.0.0 (https://github.com/helm/helm/releases)" - "helm (https://github.com/helm/helm/releases)"
- "yaml (https://pypi.org/project/PyYAML/)" - "yaml (https://pypi.org/project/PyYAML/)"
description: description:
@@ -246,7 +246,7 @@ options:
version_added: 6.1.0 version_added: 6.1.0
take_ownership: take_ownership:
description: description:
- Helm will ignore the check for helm annotations and take ownership of the existing resources - When upgrading, Helm will ignore the check for helm annotations and take ownership of the existing resources
- This feature requires helm >= 3.17.0 - This feature requires helm >= 3.17.0
type: bool type: bool
default: False default: False
@@ -500,13 +500,9 @@ def get_release_status(module, release_name, all_status=False):
"--filter", "--filter",
release_name, release_name,
] ]
if all_status and not module.is_helm_v4(): if all_status:
# --all has been removed from `helm list` command on helm v4
list_command.append("--all") 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) rc, out, err = module.run_helm_command(list_command)
release = get_release(yaml.safe_load(out), release_name) release = get_release(yaml.safe_load(out), release_name)
@@ -743,8 +739,8 @@ def get_plugin_version(plugin):
return None return None
for line in out: for line in out:
if line["name"] == plugin: if line[0] == plugin:
return line["version"] return line[1]
return None return None
@@ -932,7 +928,7 @@ def main():
if not IMP_YAML: if not IMP_YAML:
module.fail_json(msg=missing_required_lib("yaml"), exception=IMP_YAML_ERR) module.fail_json(msg=missing_required_lib("yaml"), exception=IMP_YAML_ERR)
# Validate Helm version >=3.0.0 # Validate Helm version >=3.0.0,<4.0.0
module.validate_helm_version() module.validate_helm_version()
changed = False changed = False
@@ -1014,7 +1010,8 @@ def main():
if wait: if wait:
helm_version = module.get_helm_version() helm_version = module.get_helm_version()
if LooseVersion(helm_version) < LooseVersion("3.7.0"): if LooseVersion(helm_version) < LooseVersion("3.7.0"):
module.warn( opt_result["warnings"] = []
opt_result["warnings"].append(
"helm uninstall support option --wait for helm release >= 3.7.0" "helm uninstall support option --wait for helm release >= 3.7.0"
) )
wait = False wait = False
@@ -1095,28 +1092,20 @@ def main():
reset_then_reuse_values=reset_then_reuse_values, reset_then_reuse_values=reset_then_reuse_values,
insecure_skip_tls_verify=insecure_skip_tls_verify, insecure_skip_tls_verify=insecure_skip_tls_verify,
plain_http=plain_http, plain_http=plain_http,
take_ownership=take_ownership,
skip_schema_validation=skip_schema_validation, skip_schema_validation=skip_schema_validation,
) )
changed = True changed = True
else: else:
helm_diff_version = get_plugin_version("diff") helm_diff_version = get_plugin_version("diff")
helm_version_compatible = module.is_helm_version_compatible_with_helm_diff( if helm_diff_version and (
helm_diff_version not chart_repo_url
) or (
if ( chart_repo_url
helm_diff_version and LooseVersion(helm_diff_version) >= LooseVersion("3.4.1")
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, module,
release_name, release_name,
chart_ref, chart_ref,
@@ -1137,18 +1126,10 @@ def main():
if would_change and module._diff: if would_change and module._diff:
opt_result["diff"] = {"prepared": prepared} opt_result["diff"] = {"prepared": prepared}
else: else:
if helm_diff_version and not helm_version_compatible: module.warn(
module.warn( "The default idempotency check can fail to report changes in certain cases. "
"Idempotency checks are currently disabled due to a version mismatch." "Install helm diff >= 3.4.1 for better results."
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( would_change = default_check(
release_status, chart_info, release_values, values_files release_status, chart_info, release_values, values_files
) )

View File

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

View File

@@ -16,7 +16,7 @@ version_added: 1.0.0
author: author:
- Abhijeet Kasurde (@Akasurde) - Abhijeet Kasurde (@Akasurde)
requirements: requirements:
- "helm >= 3.0.0 (https://github.com/helm/helm/releases)" - "helm (https://github.com/helm/helm/releases)"
description: description:
- Manages Helm plugins. - Manages Helm plugins.
options: options:
@@ -48,14 +48,6 @@ options:
required: false required: false
type: str type: str
version_added: 2.3.0 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: extends_documentation_fragment:
- kubernetes.core.helm_common_options - kubernetes.core.helm_common_options
""" """
@@ -126,9 +118,6 @@ from ansible_collections.kubernetes.core.plugins.module_utils.helm_args_common i
HELM_AUTH_ARG_SPEC, HELM_AUTH_ARG_SPEC,
HELM_AUTH_MUTUALLY_EXCLUSIVE, HELM_AUTH_MUTUALLY_EXCLUSIVE,
) )
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
LooseVersion,
)
def argument_spec(): def argument_spec():
@@ -149,10 +138,6 @@ def argument_spec():
default="present", default="present",
choices=["present", "absent", "latest"], choices=["present", "absent", "latest"],
), ),
verify=dict(
type="bool",
default=True,
),
) )
) )
return arg_spec return arg_spec
@@ -176,7 +161,7 @@ def main():
mutually_exclusive=mutually_exclusive(), mutually_exclusive=mutually_exclusive(),
) )
# Validate helm version >= 3.0.0 # Validate Helm version >=3.0.0,<4.0.0
module.validate_helm_version() module.validate_helm_version()
state = module.params.get("state") state = module.params.get("state")
@@ -186,19 +171,8 @@ def main():
if state == "present": if state == "present":
helm_cmd_common += " install %s" % module.params.get("plugin_path") helm_cmd_common += " install %s" % module.params.get("plugin_path")
plugin_version = module.params.get("plugin_version") plugin_version = module.params.get("plugin_version")
verify = module.params.get("verify")
if plugin_version is not None: if plugin_version is not None:
helm_cmd_common += " --version=%s" % plugin_version 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: if not module.check_mode:
rc, out, err = module.run_helm_command( rc, out, err = module.run_helm_command(
helm_cmd_common, fails_on_error=False helm_cmd_common, fails_on_error=False
@@ -237,9 +211,9 @@ def main():
elif state == "absent": elif state == "absent":
plugin_name = module.params.get("plugin_name") plugin_name = module.params.get("plugin_name")
rc, output, err, command = module.get_helm_plugin_list() rc, output, err, command = module.get_helm_plugin_list()
plugins = parse_helm_plugin_list(output=output.splitlines()) out = parse_helm_plugin_list(output=output.splitlines())
if not plugins: if not out:
module.exit_json( module.exit_json(
failed=False, failed=False,
changed=False, changed=False,
@@ -250,7 +224,12 @@ def main():
rc=rc, rc=rc,
) )
if all(plugin["name"] != plugin_name for plugin in plugins): found = False
for line in out:
if line[0] == plugin_name:
found = True
break
if not found:
module.exit_json( module.exit_json(
failed=False, failed=False,
changed=False, changed=False,
@@ -288,9 +267,9 @@ def main():
elif state == "latest": elif state == "latest":
plugin_name = module.params.get("plugin_name") plugin_name = module.params.get("plugin_name")
rc, output, err, command = module.get_helm_plugin_list() rc, output, err, command = module.get_helm_plugin_list()
plugins = parse_helm_plugin_list(output=output.splitlines()) out = parse_helm_plugin_list(output=output.splitlines())
if not plugins: if not out:
module.exit_json( module.exit_json(
failed=False, failed=False,
changed=False, changed=False,
@@ -301,7 +280,12 @@ def main():
rc=rc, rc=rc,
) )
if all(plugin["name"] != plugin_name for plugin in plugins): found = False
for line in out:
if line[0] == plugin_name:
found = True
break
if not found:
module.exit_json( module.exit_json(
failed=False, failed=False,
changed=False, changed=False,

View File

@@ -16,7 +16,7 @@ version_added: 1.0.0
author: author:
- Abhijeet Kasurde (@Akasurde) - Abhijeet Kasurde (@Akasurde)
requirements: requirements:
- "helm >= 3.0.0 (https://github.com/helm/helm/releases)" - "helm (https://github.com/helm/helm/releases)"
description: description:
- Gather information about Helm plugins installed in namespace. - Gather information about Helm plugins installed in namespace.
options: options:
@@ -98,16 +98,29 @@ def main():
supports_check_mode=True, supports_check_mode=True,
) )
# Validate helm version >= 3.0.0 # Validate Helm version >=3.0.0,<4.0.0
module.validate_helm_version() module.validate_helm_version()
plugin_name = module.params.get("plugin_name") plugin_name = module.params.get("plugin_name")
plugin_list = []
rc, output, err, command = module.get_helm_plugin_list() rc, output, err, command = module.get_helm_plugin_list()
plugins = parse_helm_plugin_list(output=output.splitlines()) out = 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] 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
module.exit_json( module.exit_json(
changed=True, changed=True,
@@ -115,7 +128,7 @@ def main():
stdout=output, stdout=output,
stderr=err, stderr=err,
rc=rc, rc=rc,
plugin_list=plugins, plugin_list=plugin_list,
) )

View File

@@ -21,7 +21,7 @@ description:
- There are options for unpacking the chart after download. - There are options for unpacking the chart after download.
requirements: requirements:
- "helm >= 3.0.0 (https://github.com/helm/helm/releases)" - "helm >= 3.0, <4.0.0 (https://github.com/helm/helm/releases)"
options: options:
chart_ref: chart_ref:
@@ -372,7 +372,7 @@ def main():
mutually_exclusive=[("chart_version", "chart_devel")], mutually_exclusive=[("chart_version", "chart_devel")],
) )
# Validate Helm version >=3.0.0 # Validate Helm version >=3.0.0,<4.0.0
module.validate_helm_version() module.validate_helm_version()
helm_version = module.get_helm_version() helm_version = module.get_helm_version()

View File

@@ -20,7 +20,7 @@ author:
- Yuriy Novostavskiy (@yurnov) - Yuriy Novostavskiy (@yurnov)
requirements: requirements:
- "helm (https://github.com/helm/helm/releases) >= 3.8.0" - "helm (https://github.com/helm/helm/releases) >= 3.8.0, <4.0.0"
description: description:
- Helm registry authentication module allows you to login C(helm registry login) and logout C(helm registry logout) from a Helm registry. - Helm registry authentication module allows you to login C(helm registry login) and logout C(helm registry logout) from a Helm registry.
@@ -75,14 +75,6 @@ options:
- Path to the CA certificate SSL file for verify registry server certificate. - Path to the CA certificate SSL file for verify registry server certificate.
required: false required: false
type: path 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: binary_path:
description: description:
- The path of a helm binary to use. - The path of a helm binary to use.
@@ -156,7 +148,6 @@ def arg_spec():
key_file=dict(type="path", required=False), key_file=dict(type="path", required=False),
cert_file=dict(type="path", required=False), cert_file=dict(type="path", required=False),
ca_file=dict(type="path", required=False), ca_file=dict(type="path", required=False),
plain_http=dict(type="bool", default=False),
) )
@@ -169,7 +160,6 @@ def login(
key_file, key_file,
cert_file, cert_file,
ca_file, ca_file,
plain_http,
): ):
login_command = command + " registry login " + host login_command = command + " registry login " + host
@@ -187,8 +177,6 @@ def login(
if ca_file is not None: if ca_file is not None:
login_command += " --ca-file=" + ca_file login_command += " --ca-file=" + ca_file
if plain_http:
login_command += " --plain-http"
return login_command return login_command
@@ -206,8 +194,8 @@ def main():
supports_check_mode=True, supports_check_mode=True,
) )
# Validate Helm version >=3.8.0 # Validate Helm version >=3.0.0,<4.0.0
module.validate_helm_version(version="3.8.0") module.validate_helm_version()
changed = False changed = False
@@ -219,19 +207,6 @@ def main():
key_file = module.params.get("key_file") key_file = module.params.get("key_file")
cert_file = module.params.get("cert_file") cert_file = module.params.get("cert_file")
ca_file = module.params.get("ca_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() helm_cmd = module.get_helm_binary()
@@ -240,15 +215,7 @@ def main():
changed = True changed = True
elif state == "present": elif state == "present":
helm_cmd = login( helm_cmd = login(
helm_cmd, helm_cmd, host, insecure, username, password, key_file, cert_file, ca_file
host,
insecure,
username,
password,
key_file,
cert_file,
ca_file,
plain_http,
) )
changed = True changed = True
@@ -271,6 +238,7 @@ def main():
command=helm_cmd, command=helm_cmd,
) )
helm_version = module.get_helm_version()
if LooseVersion(helm_version) >= LooseVersion("3.18.0") and state == "absent": if LooseVersion(helm_version) >= LooseVersion("3.18.0") and state == "absent":
# https://github.com/ansible-collections/kubernetes.core/issues/944 # https://github.com/ansible-collections/kubernetes.core/issues/944
module.warn( module.warn(

View File

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

View File

@@ -21,10 +21,6 @@ author:
description: description:
- Render chart templates to an output directory or as text of concatenated yaml documents. - 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: options:
binary_path: binary_path:
description: description:
@@ -351,7 +347,7 @@ def main():
if not IMP_YAML: if not IMP_YAML:
module.fail_json(msg=missing_required_lib("yaml"), exception=IMP_YAML_ERR) module.fail_json(msg=missing_required_lib("yaml"), exception=IMP_YAML_ERR)
# Validate Helm version >=3.0.0 # Validate Helm version >=3.0.0,<4.0.0
module.validate_helm_version() module.validate_helm_version()
helm_cmd = module.get_helm_binary() helm_cmd = module.get_helm_binary()

View File

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

View File

@@ -120,21 +120,6 @@ EXAMPLES = r"""
namespace: default namespace: default
wait_sleep: 10 wait_sleep: 10
wait_timeout: 360 wait_timeout: 360
- name: Wait for OpenShift bootstrap to complete
kubernetes.core.k8s_info:
api_version: v1
kind: ConfigMap
name: bootstrap
namespace: kube-system
register: ocp_bootstrap_status
until: >
ocp_bootstrap_status.resources is defined and
(ocp_bootstrap_status.resources | length > 0) and
(ocp_bootstrap_status.resources[0].data.status is defined) and
(ocp_bootstrap_status.resources[0].data.status == 'complete')
retries: 60
delay: 15
""" """
RETURN = r""" RETURN = r"""

View File

@@ -1,441 +0,0 @@
#!/usr/bin/python
#
# Copyright (c) Ansible Project
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
DOCUMENTATION = r"""
---
module: kubeconfig
short_description: Generate, update, and optionally write Kubernetes kubeconfig files
version_added: "6.5.0"
author: "Youssef Khalid Ali (@YoussefKhalidAli)"
description:
- Build, update, and manage Kubernetes kubeconfig files using structured input.
- Supports loading an existing kubeconfig file and merging clusters, users, and contexts.
- Can optionally write the resulting kubeconfig to a destination path.
- Ensures idempotent behavior by only updating files when changes occur.
requirements:
- "PyYAML >= 5.1"
notes:
- Input data is merged by resource name (cluster, user, context).
- Updates under O(clusters), O(users), and O(contexts) are matched by C(name) against the kubeconfig loaded from O(path).
- For an existing C(name), each entry's C(behavior) suboption controls the update.
- The default is V(merge), which merges nested C(cluster), C(user), and C(context) data so unspecified keys are preserved.
- With V(replace), the previous entry for that name is dropped and only the new definition is used.
- With V(keep), the existing entry is left unchanged.
- This can be used to move kubeconfig files to a different location with different content.
- This module does not validate cluster connectivity or authentication.
- The module supports C(check_mode) and will not write files when enabled.
- The structure follows standard Kubernetes kubeconfig format as defined in the Kubernetes documentation.
- Tokens and sensitive data should be protected using ansible-vault or environment variables.
options:
path:
description:
- Path to an existing kubeconfig file to load and merge from.
- If the file does not exist, a new kubeconfig will be created.
- This becomes the default destination if O(dest) is not specified.
type: str
required: true
dest:
description:
- Destination path where the final kubeconfig should be written.
- If not specified, the kubeconfig will be saved to O(path).
- Allows copying and modifying a kubeconfig to a new location.
type: str
required: false
clusters:
description:
- List of cluster definitions to merge into the kubeconfig.
- Each cluster is identified by its C(name).
- When C(name) matches an existing cluster, the default C(behavior) is V(merge).
- See the C(behavior) suboption for V(replace) and V(keep).
type: list
elements: dict
required: false
default: []
suboptions:
name:
description:
- Unique name identifier for the cluster.
type: str
required: true
behavior:
description:
- How to handle merging if a cluster with this name already exists.
- C(merge) - Update only the specified fields, preserve others (default).
- C(replace) - Replace the entire cluster definition.
- C(keep) - Keep existing cluster, skip this entry.
type: str
choices: ['merge', 'replace', 'keep']
default: merge
cluster:
description:
- Cluster configuration details.
type: dict
required: true
suboptions:
server:
description:
- Kubernetes API server URL (e.g., C(https://k8s.example.com:6443)).
type: str
required: true
certificate-authority:
description:
- Path to a CA certificate file for validating the API server certificate.
type: str
certificate-authority-data:
description:
- Base64 encoded CA certificate data.
- Use this instead of C(certificate-authority) for embedded certificates.
type: str
insecure-skip-tls-verify:
description:
- If true, the server's certificate will not be validated.
type: bool
proxy-url:
description:
- Optional proxy URL for cluster connections.
type: str
tls-server-name:
description:
- Server name to use for server certificate validation.
type: str
users:
description:
- List of user authentication configurations.
- Each user is identified by its C(name).
- When C(name) matches an existing user, the default C(behavior) is V(merge).
- See the C(behavior) suboption for V(replace) and V(keep).
type: list
elements: dict
required: false
default: []
suboptions:
name:
description:
- Unique name identifier for the user.
type: str
required: true
behavior:
description:
- How to handle merging if a user with this name already exists.
- C(merge) - Update only the specified fields, preserve others (default).
- C(replace) - Replace the entire user definition.
- C(keep) - Keep existing user, skip this entry.
type: str
choices: ['merge', 'replace', 'keep']
default: merge
user:
description:
- User authentication configuration.
type: dict
required: true
suboptions:
token:
description:
- Bearer token for authentication.
type: str
username:
description:
- Username for basic authentication.
type: str
password:
description:
- Password for basic authentication.
type: str
client-certificate:
description:
- Path to client certificate file.
- Used for certificate-based authentication.
type: str
client-key:
description:
- Path to client private key file.
- Must be provided with C(client-certificate).
type: str
client-certificate-data:
description:
- Base64 encoded client certificate.
- Use instead of C(client-certificate) for embedded certificates.
type: str
client-key-data:
description:
- Base64 encoded client private key.
- Use instead of C(client-key) for embedded keys.
type: str
auth-provider:
description:
- Authentication provider configuration (e.g., for GCP, Azure).
type: dict
exec:
description:
- Exec-based credential plugin configuration.
- Used for external authentication providers.
type: dict
contexts:
description:
- List of context definitions linking users and clusters.
- Each context is identified by its C(name).
- When C(name) matches an existing context, the default C(behavior) is V(merge).
- See the C(behavior) suboption for V(replace) and V(keep).
type: list
elements: dict
required: false
default: []
suboptions:
name:
description:
- Unique name identifier for the context.
type: str
required: true
behavior:
description:
- How to handle merging if a context with this name already exists.
- C(merge) - Update only the specified fields, preserve others (default).
- C(replace) - Replace the entire context definition.
- C(keep) - Keep existing context, skip this entry.
type: str
choices: ['merge', 'replace', 'keep']
default: merge
context:
description:
- Context configuration linking cluster and user.
type: dict
required: true
suboptions:
cluster:
description:
- Name of the cluster to use (must match a cluster name in O(clusters)).
type: str
required: true
user:
description:
- Name of the user to authenticate as (must match a user name in O(users)).
type: str
required: true
namespace:
description:
- Default namespace to use for this context.
- If not specified, defaults to C(default).
type: str
preferences:
description:
- Kubeconfig preferences.
- Used for client-side settings like color output, default editor, etc.
type: dict
required: false
default: {}
current_context:
description:
- Name of the context to set as current/active.
- This context will be used by default when using kubectl.
- Must match one of the context names defined in O(contexts).
type: str
required: false
seealso:
- name: Kubernetes kubeconfig documentation
description: Official Kubernetes documentation for kubeconfig files
link: https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/
- name: kubectl config documentation
description: kubectl commands for working with kubeconfig files
link: https://kubernetes.io/docs/reference/kubectl/generated/kubectl_config/
"""
EXAMPLES = r"""
# Create a new kubeconfig file with a single cluster
- name: Create basic kubeconfig
kubernetes.core.kubeconfig:
path: /home/user/.kube/config
clusters:
- name: production-cluster
cluster:
server: https://prod.k8s.example.com:6443
certificate-authority-data: LS0tLS1CRUdJTi...
users:
- name: admin-user
user:
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9...
contexts:
- name: prod-admin
context:
cluster: production-cluster
user: admin-user
namespace: production
current_context: prod-admin
- name: Copy and modify kubeconfig
kubernetes.core.kubeconfig:
path: /home/user/.kube/config
dest: /home/user/.kube/config-backup
clusters:
- name: new-cluster
cluster:
server: https://new.example.com:6443
- name: Switch current context
kubernetes.core.kubeconfig:
path: ~/.kube/config
current_context: prod-context
- name: Update user credentials
kubernetes.core.kubeconfig:
path: ~/.kube/config
users:
- name: admin-user
user:
token: "{{ new_admin_token }}"
"""
RETURN = r"""
kubeconfig:
description: The complete kubeconfig data structure.
type: dict
returned: always
dest:
description: The path where the kubeconfig was written.
type: str
returned: always
sample: /home/user/.kube/config
"""
import os
import traceback
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
from ansible.module_utils.common.text.converters import to_native
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
extract_sensitive_values_from_kubeconfig,
)
from ansible_collections.kubernetes.core.plugins.module_utils.kubeconfig import (
hash_data,
load_yaml_file,
merge_by_name,
write_file,
)
try:
import yaml
IMP_YAML = True
IMP_YAML_ERR = None
except ImportError:
IMP_YAML = False
IMP_YAML_ERR = traceback.format_exc()
def run_module():
module_args = dict(
path=dict(type="str", required=True),
dest=dict(type="str", required=False),
clusters=dict(type="list", elements="dict", required=False, default=[]),
users=dict(type="list", elements="dict", required=False, default=[]),
contexts=dict(type="list", elements="dict", required=False, default=[]),
preferences=dict(type="dict", required=False, default={}),
current_context=dict(type="str", required=False),
)
module = AnsibleModule(argument_spec=module_args, supports_check_mode=True)
path = module.params["path"]
dest = module.params["dest"] or path
clusters_input = module.params["clusters"]
users_input = module.params["users"]
contexts_input = module.params["contexts"]
preferences = module.params["preferences"]
current_context = module.params["current_context"]
# Load existing kubeconfig
try:
if not IMP_YAML:
module.fail_json(
msg=missing_required_lib("pyyaml"),
exception=IMP_YAML_ERR,
)
existing = load_yaml_file(path) if path else {}
except Exception as e:
module.fail_json(
msg="Failed to load existing kubeconfig: %s" % to_native(e),
exception=traceback.format_exc(),
)
clusters = merge_by_name(existing.get("clusters", []), clusters_input)
users = merge_by_name(existing.get("users", []), users_input)
contexts = merge_by_name(existing.get("contexts", []), contexts_input)
# Build final kubeconfig
kubeconfig = {
"apiVersion": "v1",
"kind": "Config",
"preferences": preferences or existing.get("preferences", {}),
"clusters": clusters,
"users": users,
"contexts": contexts,
"current-context": current_context or existing.get("current-context") or "",
}
changed = False
old_data = {}
if os.path.exists(dest):
try:
with open(dest, "r") as f:
old_data = yaml.safe_load(f) or {}
except Exception as e:
module.fail_json(
msg="Failed to read destination file: %s" % to_native(e),
exception=traceback.format_exc(),
)
old_hash = hash_data(old_data)
new_hash = hash_data(kubeconfig)
if old_hash != new_hash:
if not module.check_mode:
try:
write_file(dest, kubeconfig)
except Exception as e:
module.fail_json(
msg="Failed to write kubeconfig: %s" % to_native(e),
exception=traceback.format_exc(),
)
changed = True
if isinstance(kubeconfig, dict):
module.no_log_values.update(
extract_sensitive_values_from_kubeconfig(kubeconfig)
)
module.exit_json(
changed=changed,
kubeconfig=kubeconfig,
dest=dest,
msg=(
"Kubeconfig file has been updated."
if changed
else "Kubeconfig file is already up to date."
),
)
def main():
run_module()
if __name__ == "__main__":
main()

View File

@@ -1,14 +0,0 @@
# SonarCloud project configuration for kubernetes.core
# Parameters: https://docs.sonarqube.org/latest/analysis/analysis-parameters/
sonar.projectKey=ansible-collections_kubernetes.core
sonar.organization=ansible-collections
sonar.sources=.
sonar.projectName=kubernetes.core
sonar.python.coverage.reportPaths=coverage.xml
sonar.tests=tests/unit,tests/integration
sonar.python.version=3.12
sonar.newCode.referenceBranch=main
sonar.exclusions=tests/**,.tox/**

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,5 @@
#!/usr/bin/env bash
set -eux
export ANSIBLE_CALLBACKS_ENABLED=profile_tasks
export ANSIBLE_ROLES_PATH=../
ansible-playbook playbook.yaml "$@"

View File

@@ -0,0 +1,15 @@
---
- 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,22 +1,10 @@
--- ---
- 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 - name: Run tests
include_tasks: run_test.yml include_tasks: run_test.yml
loop_control:
loop_var: helm_version
with_items:
- "v3.15.4"
- "v3.16.0"
- "v3.17.0"
- "v4.0.0"

View File

@@ -1,19 +1,25 @@
--- ---
- 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 }}" - name: "Install {{ helm_version }}"
include_role: include_role:
name: install_helm name: install_helm
- name: Main helm tests - name: Main helm tests with Helm v3
when: helm_version != "v4.0.0"
block: 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: "Ensure we honor the environment variables" - name: "Ensure we honor the environment variables"
include_tasks: test_read_envvars.yml include_tasks: test_read_envvars.yml
when: helm_version != "v4.0.0"
- name: Deploy charts - name: Deploy charts
include_tasks: "tests_chart/{{ test_chart_type }}.yml" include_tasks: "tests_chart/{{ test_chart_type }}.yml"
@@ -33,6 +39,9 @@
- name: test helm dependency update - name: test helm dependency update
include_tasks: test_up_dep.yml include_tasks: test_up_dep.yml
- name: Test helm uninstall
include_tasks: test_helm_uninstall.yml
- name: Test helm install with chart name containing space - name: Test helm install with chart name containing space
include_tasks: test_helm_with_space_into_chart_name.yml include_tasks: test_helm_with_space_into_chart_name.yml
@@ -49,15 +58,12 @@
- name: Test helm skip_schema_validation - name: Test helm skip_schema_validation
include_tasks: test_skip_schema_validation.yml include_tasks: test_skip_schema_validation.yml
always: - name: Test helm version
- name: Remove helm-diff plugin include_tasks: test_helm_version.yml
helm_plugin:
binary_path: "{{ helm_binary }}"
plugin_name: diff
state: absent
ignore_errors: true
- name: Clean helm install - name: Clean helm install
ansible.builtin.file: file:
path: "/tmp/helm/" path: "{{ item }}"
state: absent state: absent
with_items:
- "/tmp/helm/"

View File

@@ -5,7 +5,7 @@
name: test name: test
chart_ref: "{{ chart_test }}" chart_ref: "{{ chart_test }}"
namespace: "helm-test" namespace: "helm-test"
ignore_errors: true ignore_errors: yes
register: helm_missing_binary register: helm_missing_binary
- name: Assert that helm is not installed - name: Assert that helm is not installed

View File

@@ -38,28 +38,6 @@
- '"--reset-then-reuse-values" not in install.command' - '"--reset-then-reuse-values" not in install.command'
- release_value["status"]["release_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 - name: Upgrade chart using reset_then_reuse_values=true
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
@@ -95,4 +73,3 @@
kind: Namespace kind: Namespace
name: "{{ helm_namespace }}" name: "{{ helm_namespace }}"
state: absent state: absent
wait: false

View File

@@ -38,21 +38,6 @@
- '"--reuse-values=True" not in install.command' - '"--reuse-values=True" not in install.command'
- release_value["status"]["release_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 - name: Upgrade chart using reuse_values=true
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"

View File

@@ -19,20 +19,6 @@
- install is changed - install is changed
- '"--take-ownership" not in install.command' - '"--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) - name: Upgrade chart (take-onwership flag set)
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
@@ -43,9 +29,6 @@
values: values:
commonLabels: commonLabels:
take-onwership: "set" take-onwership: "set"
global:
redis:
password: "{{ redis_secret.resources.0.data['redis-password'] | b64decode }}"
register: upgrade register: upgrade
ignore_errors: true ignore_errors: true
@@ -72,9 +55,6 @@
values: values:
commonLabels: commonLabels:
take-onwership: "not-set" take-onwership: "not-set"
global:
redis:
password: "{{ redis_secret.resources.0.data['redis-password'] | b64decode }}"
register: upgrade register: upgrade
ignore_errors: true ignore_errors: true

View File

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

View File

@@ -0,0 +1,47 @@
---
- name: Test helm reuse_values
vars:
helm_namespace: "{{ test_namespace[14] }}"
chart_release_values:
replica:
replicaCount: 3
master:
count: 1
kind: Deployment
chart_reuse_values:
replica:
replicaCount: 1
master:
count: 3
block:
- name: Initial chart installation
helm:
binary_path: "{{ helm_binary }}"
chart_ref: oci://registry-1.docker.io/bitnamicharts/redis
release_name: test-redis
release_namespace: "{{ helm_namespace }}"
create_namespace: true
release_values: "{{ chart_release_values }}"
register: install
ignore_errors: true
when: helm_version == "v4.0.0"
- name: Debug install result
debug:
var: install
when: helm_version == "v4.0.0"
- name: Ensure helm installation was failed for v4.0.0
assert:
that:
- install is failed
- "'Helm version must be >=3.0.0,<4.0.0' in install.msg"
when: helm_version == "v4.0.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 }}" binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}" name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_test_version }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
ignore_errors: true ignore_errors: yes
register: install_fail register: install_fail
- name: "Assert that Install fail {{ chart_test }} from {{ source }}" - name: "Assert that Install fail {{ chart_test }} from {{ source }}"
@@ -46,7 +46,7 @@
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}" name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_test_version }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
create_namespace: true create_namespace: true
register: install_check_mode register: install_check_mode
@@ -64,18 +64,17 @@
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}" name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_test_version }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
create_namespace: true create_namespace: true
register: install register: install
- name: "Assert that {{ chart_test }} chart version {{ chart_test_version }} is installed from {{ source }}" - name: "Assert that {{ chart_test }} chart is installed from {{ source }}"
assert: assert:
that: that:
- install is changed - install is changed
- install.status.chart == chart_test+"-"+chart_test_version - install.status.chart == chart_test+"-"+chart_test_version
- install.status.status | lower == 'deployed' - install.status.status | lower == 'deployed'
- install.status.release_values == {}
- name: Check helm_info content - name: Check helm_info content
helm_info: helm_info:
@@ -93,7 +92,7 @@
- deployed - deployed
register: release_state_content_info register: release_state_content_info
- name: "Assert that {{ chart_test }} chart version {{ chart_test_version }} is installed from {{ source }} with helm_info" - name: "Assert that {{ chart_test }} is installed from {{ source }} with helm_info"
assert: assert:
that: that:
- content_info.status.chart == chart_test+"-"+chart_test_version - content_info.status.chart == chart_test+"-"+chart_test_version
@@ -105,10 +104,9 @@
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}" name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_test_version }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
register: install register: install
diff: true
- name: Assert idempotency - name: Assert idempotency
assert: assert:
@@ -122,7 +120,7 @@
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}" name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_test_version }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
values: "{{ chart_test_values }}" values: "{{ chart_test_values }}"
register: install register: install
@@ -133,18 +131,17 @@
- install is changed - install is changed
- install.status.status | lower == 'deployed' - install.status.status | lower == 'deployed'
- install.status.chart == chart_test+"-"+chart_test_version - install.status.chart == chart_test+"-"+chart_test_version
- install.status['release_values'] == chart_test_values - "install.status['release_values'].revisionHistoryLimit == 0"
- name: Check idempotency after adding vars - name: Check idempotency after adding vars
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}" name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_test_version }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
values: "{{ chart_test_values }}" values: "{{ chart_test_values }}"
register: install register: install
diff: true
- name: Assert idempotency after add vars - name: Assert idempotency after add vars
assert: assert:
@@ -152,14 +149,14 @@
- install is not changed - install is not changed
- install.status.status | lower == 'deployed' - install.status.status | lower == 'deployed'
- install.status.chart == chart_test+"-"+chart_test_version - install.status.chart == chart_test+"-"+chart_test_version
- install.status['release_values'] == chart_test_values - "install.status['release_values'].revisionHistoryLimit == 0"
- name: "Remove Vars to {{ chart_test }} from {{ source }}" - name: "Remove Vars to {{ chart_test }} from {{ source }}"
helm: helm:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}" name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_test_version }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
register: install register: install
@@ -176,10 +173,9 @@
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}" name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_test_version }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
register: install register: install
diff: true
- name: Assert idempotency after removing vars - name: Assert idempotency after removing vars
assert: assert:
@@ -194,7 +190,7 @@
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}" name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source_upgrade | default(chart_source) }}" chart_ref: "{{ chart_source_upgrade | default(chart_source) }}"
chart_version: "{{ chart_test_version_upgrade }}" chart_version: "{{ chart_source_version_upgrade | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
register: install register: install
@@ -210,10 +206,9 @@
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}" name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source_upgrade | default(chart_source) }}" chart_ref: "{{ chart_source_upgrade | default(chart_source) }}"
chart_version: "{{ chart_test_version_upgrade }}" chart_version: "{{ chart_source_version_upgrade | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
register: install register: install
diff: true
- name: Assert idempotency after upgrade - name: Assert idempotency after upgrade
assert: assert:
@@ -242,7 +237,6 @@
name: "{{ chart_release_name }}" name: "{{ chart_release_name }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
register: install register: install
diff: true
- name: Assert idempotency - name: Assert idempotency
assert: assert:
@@ -255,7 +249,7 @@
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: "{{ chart_release_replaced_name }}" name: "{{ chart_release_replaced_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_test_version }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
register: install register: install
@@ -283,7 +277,7 @@
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: "{{ chart_release_replaced_name }}" name: "{{ chart_release_replaced_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_test_version }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
replace: True replace: True
register: install register: install
@@ -311,7 +305,7 @@
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}" name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_test_version }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
values_files: values_files:
- "{{ role_path }}/files/values.yaml" - "{{ role_path }}/files/values.yaml"
@@ -330,7 +324,7 @@
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}" name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_test_version }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
values_files: values_files:
- "{{ role_path }}/files/values.yaml" - "{{ role_path }}/files/values.yaml"
@@ -352,7 +346,7 @@
helm_template: helm_template:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_test_version }}" chart_version: "{{ chart_source_version | default(omit) }}"
output_dir: "{{ temp_dir }}" output_dir: "{{ temp_dir }}"
values_files: values_files:
- "{{ role_path }}/files/values.yaml" - "{{ role_path }}/files/values.yaml"
@@ -378,7 +372,7 @@
helm_template: helm_template:
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_test_version }}" chart_version: "{{ chart_source_version | default(omit) }}"
disable_hook: True disable_hook: True
release_name: "myrelease" release_name: "myrelease"
release_namespace: "myreleasenamespace" release_namespace: "myreleasenamespace"
@@ -404,7 +398,7 @@
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
name: "{{ chart_release_name }}" name: "{{ chart_release_name }}"
chart_ref: "{{ chart_source }}" chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_test_version }}" chart_version: "{{ chart_source_version | default(omit) }}"
namespace: "{{ helm_namespace }}" namespace: "{{ helm_namespace }}"
create_namespace: true create_namespace: true
context: does-not-exist context: does-not-exist
@@ -423,7 +417,6 @@
state: absent state: absent
path: "{{ temp_dir }}" path: "{{ temp_dir }}"
ignore_errors: true ignore_errors: true
when: temp_dir is defined
- name: Remove helm namespace - name: Remove helm namespace
k8s: k8s:

View File

@@ -5,38 +5,18 @@
name: test_helm name: test_helm
repo_url: "{{ chart_test_repo }}" repo_url: "{{ chart_test_repo }}"
- name: Create temporary file to save values in - name: Install Chart from repository
ansible.builtin.tempfile: include_tasks: "../tests_chart.yml"
suffix: .helm_values vars:
register: value_file
- vars:
source: repository source: repository
chart_test: k8status chart_source: "test_helm/{{ chart_test }}"
chart_source: "test_helm/k8status" chart_source_version: "{{ chart_test_version }}"
chart_test_version: "0.16.1" chart_source_version_upgrade: "{{ chart_test_version_upgrade }}"
chart_test_version_upgrade: "0.16.2"
helm_namespace: "{{ test_namespace[7] }}" 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 - name: Remove chart repo
ansible.builtin.include_tasks: "../tests_chart.yml" helm_repository:
binary_path: "{{ helm_binary }}"
always: name: test_helm
- name: Remove temporary file repo_url: "{{ chart_test_repo }}"
ansible.builtin.file: state: absent
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,11 +3,6 @@
include_tasks: "../tests_chart.yml" include_tasks: "../tests_chart.yml"
vars: vars:
source: url source: url
chart_test: "k8status" chart_source: "https://github.com/kubernetes/ingress-nginx/releases/download/helm-chart-{{ chart_test_version }}/{{ chart_test }}-{{ chart_test_version }}.tgz"
chart_test_values: chart_source_upgrade: "https://github.com/kubernetes/ingress-nginx/releases/download/helm-chart-{{ chart_test_version_upgrade }}/{{ chart_test }}-{{ chart_test_version_upgrade }}.tgz"
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] }}" helm_namespace: "{{ test_namespace[8] }}"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,21 @@
--- ---
- ansible.builtin.include_tasks: run_tests.yml - name: Test helm with in-memory kubeconfig
loop: "{{ helm_versions }}" include_tasks: "from_in_memory_kubeconfig.yml"
loop_control: loop_control:
loop_var: helm_version 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"

View File

@@ -1,15 +0,0 @@
---
- 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,6 +5,16 @@
suffix: .helm suffix: .helm
register: _dir 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: - set_fact:
saved_kubeconfig_path: "{{ _dir.path }}/config" saved_kubeconfig_path: "{{ _dir.path }}/config"
@@ -34,7 +44,6 @@
ca_cert: "{{ test_ca_cert | default(omit) }}" ca_cert: "{{ test_ca_cert | default(omit) }}"
state: present state: present
plugin_path: https://github.com/hydeenoble/helm-subenv plugin_path: https://github.com/hydeenoble/helm-subenv
verify: false
register: plugin register: plugin
- assert: - assert:

View File

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

View File

@@ -1,4 +1,3 @@
[all] [all]
helm-3.12.3 helm_version=v3.12.3 test_namespace=helm-plain-http-v3-12-3 tests_should_failed=true 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-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

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

View File

@@ -13,6 +13,10 @@
vars: vars:
helm_install_path: "{{ install_path.path }}" helm_install_path: "{{ install_path.path }}"
- name: Set helm binary path
ansible.builtin.set_fact:
helm_binary: "{{ install_path.path }}/{{ ansible_system | lower }}-amd64/helm"
# helm # helm
- name: Run helm with plain_http - name: Run helm with plain_http
kubernetes.core.helm: kubernetes.core.helm:

View File

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

View File

@@ -1,8 +1,165 @@
--- ---
- name: Run tests - name: Install env plugin in check mode
include_tasks: run_tests.yml helm_plugin:
loop_control: binary_path: "{{ helm_binary }}"
loop_var: helm_version state: present
with_items: plugin_path: https://github.com/adamreese/helm-env
- "v3.17.0" register: check_install_env
- "v4.0.0" 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

View File

@@ -1,195 +0,0 @@
---
- 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.8.0
- 3.1.0 - 3.1.0
- 3.0.0 - 3.0.0
- 4.0.0 - 2.3.0
- block: - block:
- name: Create temp directory for helm tests - name: Create temp directory for helm tests
@@ -20,13 +20,37 @@
- set_fact: - set_fact:
destination: "{{ temp_dir }}" destination: "{{ temp_dir }}"
- name: Install Helm versions - name: Create Helm directories
ansible.builtin.include_role: file:
name: install_helm state: directory
loop: "{{ helm_versions }}" 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 == "Helm version must be >=3.0.0,<4.0.0, current version is 2.3.0"
vars: vars:
helm_version: "v{{ item }}" helm_path: "{{ temp_dir }}/2.3.0/linux-amd64/helm"
helm_install_path: "{{ temp_dir }}/{{ item }}"
# Testing helm pull with helm version == 3.0.0 # Testing helm pull with helm version == 3.0.0
- block: - block:
@@ -79,7 +103,7 @@
- _result.msg == "Parameter chart_ca_cert requires helm >= 3.1.0, current version is 3.0.0" - _result.msg == "Parameter chart_ca_cert requires helm >= 3.1.0, current version is 3.0.0"
vars: vars:
helm_path: "{{ temp_dir }}/3.0.0/helm" helm_path: "{{ temp_dir }}/3.0.0/linux-amd64/helm"
# Testing helm pull with helm version == 3.1.0 # Testing helm pull with helm version == 3.1.0
- block: - block:
@@ -119,7 +143,7 @@
- _result.msg == "Parameter skip_tls_certs_check requires helm >= 3.3.0, current version is 3.1.0" - _result.msg == "Parameter skip_tls_certs_check requires helm >= 3.3.0, current version is 3.1.0"
vars: vars:
helm_path: "{{ temp_dir }}/3.1.0/helm" helm_path: "{{ temp_dir }}/3.1.0/linux-amd64/helm"
# Testing helm pull with helm version == 3.8.0 # Testing helm pull with helm version == 3.8.0
- block: - block:
@@ -293,7 +317,7 @@
- _chart_after_force.stat.isdir - _chart_after_force.stat.isdir
vars: vars:
helm_path: "{{ temp_dir }}/3.8.0/helm" helm_path: "{{ temp_dir }}/3.8.0/linux-amd64/helm"
always: always:

View File

@@ -5,9 +5,5 @@ username: testuser
password: testpassword password: testpassword
wrong_password: 'WrongPassword' wrong_password: 'WrongPassword'
registry_name: oci_registry registry_name: oci_registry
registry_port: 5002 registry_port: 5000
test_chart: https://github.com/grafana/helm-charts/releases/download/k8s-monitoring-1.6.8/k8s-monitoring-1.6.8.tgz 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

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

View File

@@ -0,0 +1,182 @@
---
- 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 idempotency of logout with helm < 3.18.0
when: _helm_version.stdout is ansible.builtin.version('v3.18.0', '<')
block:
- 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 or 'basic credential not found' 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' 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"
- "'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

@@ -1,60 +0,0 @@
---
- 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

@@ -1,108 +0,0 @@
---
- 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,2 +1,5 @@
time=1 time=20
helm_repository helm_repository
helm_info
helm
helm_template

View File

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

View File

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

View File

@@ -1,6 +1,101 @@
--- ---
- name: Run test for helm_repository module - name: "Ensure test_helm_repo doesn't exist"
ansible.builtin.include_tasks: run_tests.yml helm_repository:
loop: "{{ helm_versions }}" binary_path: "{{ helm_binary }}"
loop_control: name: test_helm_repo
loop_var: helm_version 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

View File

@@ -1,105 +0,0 @@
---
- name: "Install helm version {{ helm_version }}"
ansible.builtin.include_role:
name: install_helm
- 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: true
- 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

View File

@@ -1,5 +1,3 @@
--- ---
helm_binary: "/tmp/helm/{{ ansible_system | lower }}-amd64/helm"
helm_namespace: helm-set-values helm_namespace: helm-set-values
helm_versions:
- v3.10.3
- v4.0.0

View File

@@ -25,14 +25,79 @@
- user_values.status["release_values"]["phase"] == "integration" - user_values.status["release_values"]["phase"] == "integration"
- user_values.status["release_values"]["versioned"] is false - user_values.status["release_values"]["versioned"] is false
- block: # install chart using set_values and release_values
- name: create temporary file to save values in - name: Install helm binary (> 3.10.0) requires to use set-json
tempfile: include_role:
suffix: .yml name: install_helm
register: ymlfile vars:
helm_version: "v3.10.3"
- ansible.builtin.include_tasks: run_tests.yml - name: Install helm using set_values parameters
loop: "{{ helm_versions }}" helm:
binary_path: "{{ helm_binary }}"
chart_ref: oci://registry-1.docker.io/bitnamicharts/apache
release_name: test-apache
release_namespace: "{{ helm_namespace }}"
create_namespace: true
set_values:
- value: 'master.image={"registry": "docker.io", "repository": "bitnami/apache", "tag": "2.4.54-debian-11-r74"}'
value_type: json
release_values:
replicaCount: 3
- name: Get release info
helm_info:
binary_path: "{{ helm_binary }}"
release_name: test-apache
release_namespace: "{{ helm_namespace }}"
register: values
- name: Assert that release was created with user-defined variables
assert:
that:
- values.status["release_values"].replicaCount == 3
- values.status["release_values"].master.image.registry == "docker.io"
- values.status["release_values"].master.image.repository == "bitnami/apache"
- values.status["release_values"].master.image.tag == "2.4.54-debian-11-r74"
# install chart using set_values and values_files
- name: create temporary file to save values in
tempfile:
suffix: .yml
register: ymlfile
- block:
- name: copy content into values file
copy:
content: |
---
mode: distributed
dest: "{{ ymlfile.path }}"
- name: Install helm using set_values parameters
helm:
binary_path: "{{ helm_binary }}"
chart_ref: oci://registry-1.docker.io/bitnamicharts/minio
release_name: test-minio
release_namespace: "{{ helm_namespace }}"
create_namespace: true
set_values:
- value: 'disableWebUI=true'
values_files:
- "{{ ymlfile.path }}"
- name: Get release info
helm_info:
binary_path: "{{ helm_binary }}"
release_name: test-minio
release_namespace: "{{ helm_namespace }}"
register: values
- name: Assert that release was created with user-defined variables
assert:
that:
- values.status["release_values"].mode == "distributed"
- values.status["release_values"].disableWebUI is true
always: always:
- name: Delete temporary file - name: Delete temporary file

View File

@@ -1,68 +0,0 @@
---
# install chart using set_values and release_values
- name: 'Install helm binary (> 3.10.0) requires to use set-json (helm_version={{ item }})'
include_role:
name: install_helm
vars:
helm_version: "{{ item }}"
- name: Install helm using set_values parameters
helm:
binary_path: "{{ helm_binary }}"
chart_ref: oci://registry-1.docker.io/bitnamicharts/apache
release_name: 'test-apache-{{ item }}'
release_namespace: "{{ helm_namespace }}"
create_namespace: true
set_values:
- value: 'master.image={"registry": "docker.io", "repository": "bitnami/apache", "tag": "2.4.54-debian-11-r74"}'
value_type: json
release_values:
replicaCount: 3
- name: Get release info
helm_info:
binary_path: "{{ helm_binary }}"
release_name: 'test-apache-{{ item }}'
release_namespace: "{{ helm_namespace }}"
register: values
- name: Assert that release was created with user-defined variables
assert:
that:
- values.status["release_values"].replicaCount == 3
- values.status["release_values"].master.image.registry == "docker.io"
- values.status["release_values"].master.image.repository == "bitnami/apache"
- values.status["release_values"].master.image.tag == "2.4.54-debian-11-r74"
# install chart using set_values and values_files
- name: copy content into values file
copy:
content: |
---
mode: distributed
dest: "{{ ymlfile.path }}"
- name: Install helm using set_values parameters
helm:
binary_path: "{{ helm_binary }}"
chart_ref: oci://registry-1.docker.io/bitnamicharts/minio
release_name: 'test-minio-{{ item }}'
release_namespace: "{{ helm_namespace }}"
create_namespace: true
set_values:
- value: 'disableWebUI=true'
values_files:
- "{{ ymlfile.path }}"
- name: Get release info
helm_info:
binary_path: "{{ helm_binary }}"
release_name: 'test-minio-{{ item }}'
release_namespace: "{{ helm_namespace }}"
register: values
- name: Assert that release was created with user-defined variables
assert:
that:
- values.status["release_values"].mode == "distributed"
- values.status["release_values"].disableWebUI is true

View File

@@ -1,4 +0,0 @@
helm
helm_template
helm_info
helm_repository

View File

@@ -1,2 +0,0 @@
[all]
v3.15.4

View File

@@ -1,11 +0,0 @@
- name: Run tests for Helm v3.15.4
hosts: all
connection: local
gather_facts: true
vars:
ansible_python_interpreter: "{{ ansible_playbook_python }}"
helm_version: "{{ inventory_hostname }}"
roles:
- role: helm

View File

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

View File

@@ -1,4 +0,0 @@
helm
helm_template
helm_info
helm_repository

View File

@@ -1,2 +0,0 @@
[all]
v3.16.0

View File

@@ -1,11 +0,0 @@
- name: Run tests for Helm v3.16.0
hosts: all
connection: local
gather_facts: true
vars:
ansible_python_interpreter: "{{ ansible_playbook_python }}"
helm_version: "{{ inventory_hostname }}"
roles:
- role: helm

View File

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

View File

@@ -1,4 +0,0 @@
helm
helm_template
helm_info
helm_repository

View File

@@ -1,2 +0,0 @@
[all]
v3.17.0

View File

@@ -1,11 +0,0 @@
- name: Run tests for Helm v3.17.0
hosts: all
connection: local
gather_facts: true
vars:
ansible_python_interpreter: "{{ ansible_playbook_python }}"
helm_version: "{{ inventory_hostname }}"
roles:
- role: helm

View File

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

View File

@@ -1,4 +0,0 @@
helm
helm_template
helm_info
helm_repository

View File

@@ -1,2 +0,0 @@
[all]
v4.0.0

View File

@@ -1,11 +0,0 @@
- name: Run tests for Helm v4.0.0
hosts: all
connection: local
gather_facts: true
vars:
ansible_python_interpreter: "{{ ansible_playbook_python }}"
helm_version: "{{ inventory_hostname }}"
roles:
- role: helm

View File

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

View File

@@ -1,4 +1,4 @@
--- ---
helm_version: v3.16.4 helm_version: v3.16.4
helm_install_path: /tmp/helm helm_install_path: /tmp/helm
helm_default_archive_name: "https://get.helm.sh/helm-{{ helm_version }}-{{ ansible_system | lower }}-{{ ansible_architecture | lower }}.tar.gz" helm_default_archive_name: "helm-{{ helm_version }}-{{ ansible_system | lower }}-amd64.tar.gz"

View File

@@ -4,27 +4,12 @@
path: "{{ helm_install_path }}" path: "{{ helm_install_path }}"
state: directory state: directory
- ansible.builtin.set_fact: - name: Unarchive Helm binary
os_path: "{{ lookup('env', 'PATH') }}" unarchive:
src: "https://get.helm.sh/{{ helm_archive_name | default(helm_default_archive_name) }}"
- name: Download the Helm install script dest: "{{ helm_install_path }}"
ansible.builtin.get_url: remote_src: yes
url: "https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-{{ major_version }}" retries: 10
dest: /tmp/get_helm.sh delay: 5
mode: '0700' register: result
vars: until: result is not failed
major_version: "{{ helm_version | split('.') | first | replace('v', '') }}"
- name: Run the install script (helm version = {{ helm_version }})
ansible.builtin.command: /tmp/get_helm.sh
environment:
DESIRED_VERSION: "{{ helm_version }}"
HELM_INSTALL_DIR: "{{ helm_install_path }}"
PATH: "{{ os_path }}:{{ helm_install_path }}"
VERIFY_CHECKSUM: "false"
register: helm_install_result
changed_when: "'is already at the latest version' not in helm_install_result.stdout"
- name: Save Helm binary path for later use
ansible.builtin.set_fact:
helm_binary: "{{ helm_install_path }}/helm"

View File

@@ -1,7 +1,3 @@
--- ---
test_namespace: "drain" test_namespace: "drain"
k8s_wait_timeout: 400 k8s_wait_timeout: 400
daemonset_name: promotheus
deployment_name: busybox-emptydir
pod1_name: "busybox-1"
pod2_name: "busybox-2"

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