mirror of
https://github.com/ansible-collections/kubernetes.core.git
synced 2026-05-11 20:12:18 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef829b8a56 | ||
|
|
d86a652c36 | ||
|
|
a4242f0131 | ||
|
|
d75e9a0fa3 | ||
|
|
5044cfc030 | ||
|
|
ddd7e79a12 | ||
|
|
edc979ff11 | ||
|
|
37c1f911cb | ||
|
|
80a5bf623a | ||
|
|
8f653558f6 | ||
|
|
1c0734dd4e | ||
|
|
e6d138dbf0 | ||
|
|
eed4ebb0af | ||
|
|
d3031fcbd3 | ||
|
|
e756cedf33 |
@@ -2,8 +2,5 @@
|
|||||||
profile: production
|
profile: production
|
||||||
|
|
||||||
exclude_paths:
|
exclude_paths:
|
||||||
- .ansible/
|
|
||||||
- .github/
|
|
||||||
- tests/integration
|
- tests/integration
|
||||||
- tests/unit
|
|
||||||
- tests/sanity
|
- tests/sanity
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
# https://docs.ansible.com/ansible-lint/docs/rules/
|
|
||||||
# no-changed-when is not requried for examples
|
|
||||||
plugins/connection/kubectl.py no-changed-when
|
|
||||||
# false positive result
|
|
||||||
plugins/connection/kubectl.py var-naming[no-reserved]
|
|
||||||
plugins/connection/kubectl.py jinja[invalid]
|
|
||||||
60
.github/stale.yml
vendored
Normal file
60
.github/stale.yml
vendored
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
---
|
||||||
|
# Configuration for probot-stale - https://github.com/probot/stale
|
||||||
|
|
||||||
|
# Number of days of inactivity before an Issue or Pull Request becomes stale
|
||||||
|
daysUntilStale: 90
|
||||||
|
|
||||||
|
# Number of days of inactivity before an Issue or Pull Request with the stale
|
||||||
|
# label is closed. Set to false to disable. If disabled, issues still need to be
|
||||||
|
# closed manually, but will remain marked as stale.
|
||||||
|
daysUntilClose: 30
|
||||||
|
|
||||||
|
# Only issues or pull requests with all of these labels are check if stale.
|
||||||
|
# Defaults to `[]` (disabled)
|
||||||
|
onlyLabels: []
|
||||||
|
|
||||||
|
# Issues or Pull Requests with these labels will never be considered stale. Set
|
||||||
|
# to `[]` to disable
|
||||||
|
exemptLabels:
|
||||||
|
- security
|
||||||
|
- planned
|
||||||
|
- priority/critical
|
||||||
|
- lifecycle/frozen
|
||||||
|
- verified
|
||||||
|
|
||||||
|
# Set to true to ignore issues in a project (defaults to false)
|
||||||
|
exemptProjects: false
|
||||||
|
|
||||||
|
# Set to true to ignore issues in a milestone (defaults to false)
|
||||||
|
exemptMilestones: true
|
||||||
|
|
||||||
|
# Set to true to ignore issues with an assignee (defaults to false)
|
||||||
|
exemptAssignees: false
|
||||||
|
|
||||||
|
# Label to use when marking as stale
|
||||||
|
staleLabel: lifecycle/stale
|
||||||
|
|
||||||
|
# Limit the number of actions per hour, from 1-30. Default is 30
|
||||||
|
limitPerRun: 30
|
||||||
|
|
||||||
|
pulls:
|
||||||
|
markComment: |-
|
||||||
|
PRs go stale after 90 days of inactivity.
|
||||||
|
If there is no further activity, the PR will be closed in another 30 days.
|
||||||
|
|
||||||
|
unmarkComment: >-
|
||||||
|
This pull request is no longer stale.
|
||||||
|
|
||||||
|
closeComment: >-
|
||||||
|
This pull request has been closed due to inactivity.
|
||||||
|
|
||||||
|
issues:
|
||||||
|
markComment: |-
|
||||||
|
Issues go stale after 90 days of inactivity.
|
||||||
|
If there is no further activity, the issue will be closed in another 30 days.
|
||||||
|
|
||||||
|
unmarkComment: >-
|
||||||
|
This issue is no longer stale.
|
||||||
|
|
||||||
|
closeComment: >-
|
||||||
|
This issue has been closed due to inactivity.
|
||||||
30
.github/workflows/integration-tests.yaml
vendored
30
.github/workflows/integration-tests.yaml
vendored
@@ -26,7 +26,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: ${{ env.source_dir }}
|
path: ${{ env.source_dir }}
|
||||||
fetch-depth: "0"
|
fetch-depth: "0"
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
|
||||||
|
|
||||||
- name: list changes for pull request
|
- name: list changes for pull request
|
||||||
id: splitter
|
id: splitter
|
||||||
@@ -51,20 +50,18 @@ jobs:
|
|||||||
source: "./source"
|
source: "./source"
|
||||||
cloud_common: "./cloudcommon"
|
cloud_common: "./cloudcommon"
|
||||||
ansible_posix: "./ansible_posix"
|
ansible_posix: "./ansible_posix"
|
||||||
community_general: "./community_general"
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
# 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 }}"
|
||||||
steps:
|
steps:
|
||||||
- name: Read target
|
- name: Read target
|
||||||
id: read-targets
|
id: read-targets
|
||||||
@@ -108,7 +105,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
|
||||||
@@ -122,15 +118,7 @@ jobs:
|
|||||||
path: ${{ env.ansible_posix }}
|
path: ${{ env.ansible_posix }}
|
||||||
ref: main
|
ref: main
|
||||||
|
|
||||||
- name: checkout ansible-collections/community.general
|
|
||||||
uses: ansible-network/github_actions/.github/actions/checkout_dependency@main
|
|
||||||
with:
|
|
||||||
repository: ansible-collections/community.general
|
|
||||||
path: ${{ env.community_general }}
|
|
||||||
ref: main
|
|
||||||
|
|
||||||
- name: install cloud.common collection
|
- name: install cloud.common collection
|
||||||
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
|
||||||
@@ -142,12 +130,6 @@ jobs:
|
|||||||
install_python_dependencies: true
|
install_python_dependencies: true
|
||||||
source_path: ${{ env.ansible_posix }}
|
source_path: ${{ env.ansible_posix }}
|
||||||
|
|
||||||
- name: install community.general collection
|
|
||||||
uses: ansible-network/github_actions/.github/actions/build_install_collection@main
|
|
||||||
with:
|
|
||||||
install_python_dependencies: false
|
|
||||||
source_path: ${{ env.community_general }}
|
|
||||||
|
|
||||||
- name: create kubernetes cluster
|
- name: create kubernetes cluster
|
||||||
uses: helm/kind-action@v1.8.0
|
uses: helm/kind-action@v1.8.0
|
||||||
with:
|
with:
|
||||||
|
|||||||
28
.github/workflows/label-new-prs.yaml
vendored
28
.github/workflows/label-new-prs.yaml
vendored
@@ -1,28 +0,0 @@
|
|||||||
---
|
|
||||||
name: label new prs
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
types:
|
|
||||||
- opened
|
|
||||||
- reopened
|
|
||||||
- converted_to_draft
|
|
||||||
- ready_for_review
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
add_label:
|
|
||||||
if: github.actor != 'patchback[bot]'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
pull-requests: write
|
|
||||||
steps:
|
|
||||||
- name: Add 'needs_triage' label if the pr is not a draft
|
|
||||||
uses: actions-ecosystem/action-add-labels@v1
|
|
||||||
if: github.event.pull_request.draft == false
|
|
||||||
with:
|
|
||||||
labels: needs_triage
|
|
||||||
|
|
||||||
- name: Remove 'needs_triage' label if the pr is a draft
|
|
||||||
uses: actions-ecosystem/action-remove-labels@v1
|
|
||||||
if: github.event.pull_request.draft == true
|
|
||||||
with:
|
|
||||||
labels: needs_triage
|
|
||||||
7
.github/workflows/linters.yaml
vendored
7
.github/workflows/linters.yaml
vendored
@@ -19,7 +19,6 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: run-ansible-lint
|
|
||||||
uses: ansible/ansible-lint@main
|
- name: Run ansible-lint
|
||||||
with:
|
uses: ansible/ansible-lint@v24.2.3
|
||||||
gh_action_ref: "v25.5.0"
|
|
||||||
|
|||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -13,7 +13,6 @@ changelogs/.plugin-cache.yaml
|
|||||||
tests/output
|
tests/output
|
||||||
tests/integration/cloud-config-*
|
tests/integration/cloud-config-*
|
||||||
.cache
|
.cache
|
||||||
.ansible
|
|
||||||
|
|
||||||
# Helm charts
|
# Helm charts
|
||||||
tests/integration/*-chart-*.tgz
|
tests/integration/*-chart-*.tgz
|
||||||
@@ -21,6 +20,3 @@ tests/integration/*-chart-*.tgz
|
|||||||
# ansible-test generated file
|
# ansible-test generated file
|
||||||
tests/integration/inventory
|
tests/integration/inventory
|
||||||
tests/integration/*-*.yml
|
tests/integration/*-*.yml
|
||||||
|
|
||||||
# VS Code settings
|
|
||||||
.vscode/
|
|
||||||
|
|||||||
@@ -5,25 +5,16 @@ rules:
|
|||||||
braces:
|
braces:
|
||||||
max-spaces-inside: 1
|
max-spaces-inside: 1
|
||||||
level: error
|
level: error
|
||||||
|
|
||||||
brackets:
|
brackets:
|
||||||
max-spaces-inside: 1
|
max-spaces-inside: 1
|
||||||
level: error
|
level: error
|
||||||
comments:
|
|
||||||
min-spaces-from-content: 1
|
|
||||||
comments-indentation: false
|
|
||||||
document-start: disable
|
document-start: disable
|
||||||
line-length: disable
|
line-length: disable
|
||||||
truthy: disable
|
truthy: disable
|
||||||
indentation:
|
indentation:
|
||||||
spaces: 2
|
spaces: 2
|
||||||
indent-sequences: consistent
|
indent-sequences: consistent
|
||||||
octal-values:
|
|
||||||
forbid-implicit-octal: true
|
|
||||||
forbid-explicit-octal: true
|
|
||||||
ignore: |
|
ignore: |
|
||||||
.cache
|
.cache
|
||||||
.tox
|
.tox
|
||||||
.ansible
|
|
||||||
tests/output
|
tests/output
|
||||||
plugins/connection/kubectl.py
|
|
||||||
|
|||||||
229
CHANGELOG.rst
229
CHANGELOG.rst
@@ -4,235 +4,6 @@ Kubernetes Collection Release Notes
|
|||||||
|
|
||||||
.. contents:: Topics
|
.. contents:: Topics
|
||||||
|
|
||||||
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
|
|
||||||
======
|
|
||||||
|
|
||||||
Release Summary
|
|
||||||
---------------
|
|
||||||
|
|
||||||
This release includes bugfixes for k8s service field handling, k8s_cp init containers support, and removes deprecated ansible.module_utils.six imports.
|
|
||||||
|
|
||||||
Bugfixes
|
|
||||||
--------
|
|
||||||
|
|
||||||
- Remove ``ansible.module_utils.six`` imports to avoid warnings (https://github.com/ansible-collections/kubernetes.core/pull/998).
|
|
||||||
- Update the `k8s_cp` module to also work for init containers (https://github.com/ansible-collections/kubernetes.core/pull/971).
|
|
||||||
- module_utils/k8s/service - hide fields first before creating diffs (https://github.com/ansible-collections/kubernetes.core/pull/915).
|
|
||||||
|
|
||||||
v5.4.0
|
|
||||||
======
|
|
||||||
|
|
||||||
Release Summary
|
|
||||||
---------------
|
|
||||||
|
|
||||||
This release updates the ``helm_registry_auth`` module to match the behavior of ``helm >= 3.18.0`` which reports a successful logout regardless of the current state (i.e., no idempotency).
|
|
||||||
|
|
||||||
Minor Changes
|
|
||||||
-------------
|
|
||||||
|
|
||||||
- Module ``helm_registry_auth`` does not support idempotency with ``helm >= 3.18.0`` (https://github.com/ansible-collections/kubernetes.core/pull/946)
|
|
||||||
|
|
||||||
v5.3.0
|
|
||||||
======
|
|
||||||
|
|
||||||
Release Summary
|
|
||||||
---------------
|
|
||||||
|
|
||||||
This release includes minor changes, bug fixes and also bumps ``ansible-lint`` version to ``25.1.2``.
|
|
||||||
|
|
||||||
Minor Changes
|
|
||||||
-------------
|
|
||||||
|
|
||||||
- Bump version of ``ansible-lint`` to 25.1.2 (https://github.com/ansible-collections/kubernetes.core/pull/919).
|
|
||||||
- action/k8s_info - update templating mechanism with changes from ``ansible-core 2.19`` (https://github.com/ansible-collections/kubernetes.core/pull/888).
|
|
||||||
- helm - add ``reset_then_reuse_values`` support to helm module (https://github.com/ansible-collections/kubernetes.core/issues/803).
|
|
||||||
- helm - add support for ``insecure_skip_tls_verify`` option to helm and helm_repository(https://github.com/ansible-collections/kubernetes.core/issues/694).
|
|
||||||
|
|
||||||
Bugfixes
|
|
||||||
--------
|
|
||||||
|
|
||||||
- module_utils/k8s/service - fix issue when trying to delete resource using ``delete_options`` and ``check_mode=true`` (https://github.com/ansible-collections/kubernetes.core/issues/892).
|
|
||||||
|
|
||||||
v5.2.0
|
|
||||||
======
|
|
||||||
|
|
||||||
Release Summary
|
|
||||||
---------------
|
|
||||||
|
|
||||||
This release adds more functionality to the hidden_fields option and support for waiting on ClusterOperators to reach a ready state.
|
|
||||||
|
|
||||||
Minor Changes
|
|
||||||
-------------
|
|
||||||
|
|
||||||
- k8s - Extend hidden_fields to allow the expression of more complex field types to be hidden (https://github.com/ansible-collections/kubernetes.core/pull/872)
|
|
||||||
- k8s_info - Extend hidden_fields to allow the expression of more complex field types to be hidden (https://github.com/ansible-collections/kubernetes.core/pull/872)
|
|
||||||
- waiter.py - add ClusterOperator support. The module can now check OpenShift cluster health by verifying ClusterOperator status requiring 'Available: True', 'Degraded: False', and 'Progressing: False' for success. (https://github.com/ansible-collections/kubernetes.core/issues/869)
|
|
||||||
|
|
||||||
v5.1.0
|
|
||||||
======
|
|
||||||
|
|
||||||
Release Summary
|
|
||||||
---------------
|
|
||||||
|
|
||||||
This release came with new module ``helm_registry_auth``, improvements to the error messages in the k8s_drain module, new parameter ``insecure_registry`` for ``helm_template`` module and several bug fixes.
|
|
||||||
|
|
||||||
Minor Changes
|
|
||||||
-------------
|
|
||||||
|
|
||||||
- Bump version of ``ansible-lint`` to minimum 24.7.0 (https://github.com/ansible-collections/kubernetes.core/pull/765).
|
|
||||||
- Parameter insecure_registry added to helm_template as equivalent of insecure-skip-tls-verify (https://github.com/ansible-collections/kubernetes.core/pull/805).
|
|
||||||
- k8s_drain - Improve error message for pod disruption budget when draining a node (https://github.com/ansible-collections/kubernetes.core/issues/797).
|
|
||||||
|
|
||||||
Bugfixes
|
|
||||||
--------
|
|
||||||
|
|
||||||
- helm - Helm version checks did not support RC versions. They now accept any version tags. (https://github.com/ansible-collections/kubernetes.core/pull/745).
|
|
||||||
- helm_pull - Apply no_log=True to pass_credentials to silence false positive warning. (https://github.com/ansible-collections/kubernetes.core/pull/796).
|
|
||||||
- k8s_drain - Fix k8s_drain does not wait for single pod (https://github.com/ansible-collections/kubernetes.core/issues/769).
|
|
||||||
- k8s_drain - Fix k8s_drain runs into a timeout when evicting a pod which is part of a stateful set (https://github.com/ansible-collections/kubernetes.core/issues/792).
|
|
||||||
- kubeconfig option should not appear in module invocation log (https://github.com/ansible-collections/kubernetes.core/issues/782).
|
|
||||||
- kustomize - kustomize plugin fails with deprecation warnings (https://github.com/ansible-collections/kubernetes.core/issues/639).
|
|
||||||
- waiter - Fix waiting for daemonset when desired number of pods is 0. (https://github.com/ansible-collections/kubernetes.core/pull/756).
|
|
||||||
|
|
||||||
New Modules
|
|
||||||
-----------
|
|
||||||
|
|
||||||
- helm_registry_auth - Helm registry authentication module
|
|
||||||
|
|
||||||
v5.0.0
|
|
||||||
======
|
|
||||||
|
|
||||||
Release Summary
|
|
||||||
---------------
|
|
||||||
|
|
||||||
This major release drops support for ``ansible-core<2.15``.
|
|
||||||
|
|
||||||
Minor Changes
|
|
||||||
-------------
|
|
||||||
|
|
||||||
- connection/kubectl.py - Added an example of using the kubectl connection plugin to the documentation (https://github.com/ansible-collections/kubernetes.core/pull/741).
|
|
||||||
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 6.0.0 (https://github.com/ansible-collections/kubernetes.core/pull/734).
|
|
||||||
|
|
||||||
Breaking Changes / Porting Guide
|
|
||||||
--------------------------------
|
|
||||||
|
|
||||||
- Remove support for ``ansible-core<2.15`` (https://github.com/ansible-collections/kubernetes.core/pull/737).
|
|
||||||
|
|
||||||
v4.0.0
|
|
||||||
======
|
|
||||||
|
|
||||||
Release Summary
|
|
||||||
---------------
|
|
||||||
|
|
||||||
This major release brings several bug fixes. We have also removed support for ``ansible-core<2.15`` and deprecated functions and class from ``module_utils/common.py``.
|
|
||||||
|
|
||||||
Minor Changes
|
|
||||||
-------------
|
|
||||||
|
|
||||||
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 5.0 (https://github.com/ansible-collections/kubernetes.core/pull/723).
|
|
||||||
- k8s - The module and K8sService were changed so warnings returned by the K8S API are now displayed to the user.
|
|
||||||
|
|
||||||
Removed Features (previously deprecated)
|
|
||||||
----------------------------------------
|
|
||||||
|
|
||||||
- k8s - Support for ``merge_type=json`` has been removed in version 4.0.0. Please use ``kubernetes.core.k8s_json_patch`` instead (https://github.com/ansible-collections/kubernetes.core/pull/722).
|
|
||||||
- k8s_exec - the previously deprecated ``result.return_code`` return value has been removed, consider using ``result.rc`` instead (https://github.com/ansible-collections/kubernetes.core/pull/726).
|
|
||||||
- module_utils/common.py - the previously deprecated ``K8sAnsibleMixin`` class has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
|
|
||||||
- module_utils/common.py - the previously deprecated ``configuration_digest()`` function has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
|
|
||||||
- module_utils/common.py - the previously deprecated ``get_api_client()`` function has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
|
|
||||||
- module_utils/common.py - the previously deprecated ``unique_string()`` function has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
|
|
||||||
|
|
||||||
Bugfixes
|
|
||||||
--------
|
|
||||||
|
|
||||||
- Resolve Collections util resource discovery fails when complex subresources present (https://github.com/ansible-collections/kubernetes.core/pull/676).
|
|
||||||
- align `helmdiff_check()` function commandline rendering with the `deploy()` function (https://github.com/ansible-collections/kubernetes.core/pull/670).
|
|
||||||
- avoid unsafe conditions in integration tests (https://github.com/ansible-collections/kubernetes.core/pull/665).
|
|
||||||
- helm - use ``reuse-values`` when running ``helm diff`` command (https://github.com/ansible-collections/kubernetes.core/issues/680).
|
|
||||||
- integrations test helm_kubeconfig - set helm version to v3.10.3 to avoid incompatability with new bitnami charts (https://github.com/ansible-collections/kubernetes.core/pull/670).
|
|
||||||
|
|
||||||
v3.3.1
|
|
||||||
======
|
|
||||||
|
|
||||||
Release Summary
|
|
||||||
---------------
|
|
||||||
|
|
||||||
This release fixes the CI issues with the ``linters`` workflow.
|
|
||||||
|
|
||||||
v3.3.0
|
|
||||||
======
|
|
||||||
|
|
||||||
Release Summary
|
|
||||||
---------------
|
|
||||||
|
|
||||||
This release comes with improvements to the error messages in the k8s_drain module and several bug fixes.
|
|
||||||
|
|
||||||
Minor Changes
|
|
||||||
-------------
|
|
||||||
|
|
||||||
- k8s_drain - Improve error message for pod disruption budget when draining a node (https://github.com/ansible-collections/kubernetes.core/issues/797).
|
|
||||||
|
|
||||||
Bugfixes
|
|
||||||
--------
|
|
||||||
|
|
||||||
- helm - Helm version checks did not support RC versions. They now accept any version tags. (https://github.com/ansible-collections/kubernetes.core/pull/745).
|
|
||||||
- helm_pull - Apply no_log=True to pass_credentials to silence false positive warning. (https://github.com/ansible-collections/kubernetes.core/pull/796).
|
|
||||||
- k8s_drain - Fix k8s_drain does not wait for single pod (https://github.com/ansible-collections/kubernetes.core/issues/769).
|
|
||||||
- k8s_drain - Fix k8s_drain runs into a timeout when evicting a pod which is part of a stateful set (https://github.com/ansible-collections/kubernetes.core/issues/792).
|
|
||||||
- kubeconfig option should not appear in module invocation log (https://github.com/ansible-collections/kubernetes.core/issues/782).
|
|
||||||
- kustomize - kustomize plugin fails with deprecation warnings (https://github.com/ansible-collections/kubernetes.core/issues/639).
|
|
||||||
- waiter - Fix waiting for daemonset when desired number of pods is 0. (https://github.com/ansible-collections/kubernetes.core/pull/756).
|
|
||||||
|
|
||||||
v3.2.0
|
|
||||||
======
|
|
||||||
|
|
||||||
Release Summary
|
|
||||||
---------------
|
|
||||||
|
|
||||||
This release comes with documentation updates.
|
|
||||||
|
|
||||||
Minor Changes
|
|
||||||
-------------
|
|
||||||
|
|
||||||
- connection/kubectl.py - Added an example of using the kubectl connection plugin to the documentation (https://github.com/ansible-collections/kubernetes.core/pull/741).
|
|
||||||
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 5.0 (https://github.com/ansible-collections/kubernetes.core/pull/723).
|
|
||||||
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 6.0.0 (https://github.com/ansible-collections/kubernetes.core/pull/734).
|
|
||||||
|
|
||||||
v3.1.0
|
v3.1.0
|
||||||
======
|
======
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ Where modules have multiple parameters we recommend running through the 4-step m
|
|||||||
|
|
||||||
For general information on running the integration tests see the
|
For general information on running the integration tests see the
|
||||||
[Integration Tests page of the Module Development Guide](https://docs.ansible.com/ansible/devel/dev_guide/testing_integration.html#testing-integration),
|
[Integration Tests page of the Module Development Guide](https://docs.ansible.com/ansible/devel/dev_guide/testing_integration.html#testing-integration),
|
||||||
especially the section on configuration for cloud tests.
|
especially the section on configuration for cloud tests. For questions about writing tests the Ansible Kubernetes community can be found on Libera.Chat IRC as detailed below.
|
||||||
|
|
||||||
### Updating documentation
|
### Updating documentation
|
||||||
|
|
||||||
@@ -70,3 +70,11 @@ Review the changes and create a pull request using updated files.
|
|||||||
The `kubernetes.core` collection follows the Ansible project's
|
The `kubernetes.core` collection follows the Ansible project's
|
||||||
[Code of Conduct](https://docs.ansible.com/ansible/devel/community/code_of_conduct.html).
|
[Code of Conduct](https://docs.ansible.com/ansible/devel/community/code_of_conduct.html).
|
||||||
Please read and familiarize yourself with this document.
|
Please read and familiarize yourself with this document.
|
||||||
|
|
||||||
|
### IRC
|
||||||
|
Our IRC channels may require you to register your nickname. If you receive an error when you connect, see
|
||||||
|
[Libera.Chat's Nickname Registration guide](https://libera.chat/guides/registration) for instructions.
|
||||||
|
|
||||||
|
The `#ansible-kubernetes` channel on [libera.chat](https://libera.chat/) IRC is the main and official place to discuss use and development of the `kubernetes.core` collection.
|
||||||
|
|
||||||
|
For more information about Ansible's Kubernetes integration, browse the resources in the [Kubernetes Working Group](https://github.com/ansible/community/wiki/Kubernetes) Community wiki page.
|
||||||
|
|||||||
2
Makefile
2
Makefile
@@ -1,5 +1,5 @@
|
|||||||
# Also needs to be updated in galaxy.yml
|
# Also needs to be updated in galaxy.yml
|
||||||
VERSION = 5.4.2
|
VERSION = 3.0.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]))'`
|
||||||
|
|||||||
89
README.md
89
README.md
@@ -1,29 +1,15 @@
|
|||||||
# Kubernetes Collection for Ansible
|
# Kubernetes Collection for Ansible
|
||||||
|
|
||||||
|
[](https://github.com/ansible-collections/kubernetes.core/actions) [](https://codecov.io/gh/ansible-collections/kubernetes.core)
|
||||||
|
|
||||||
This repository hosts the `kubernetes.core` (formerly known as `community.kubernetes`) Ansible Collection.
|
This repository hosts the `kubernetes.core` (formerly known as `community.kubernetes`) Ansible Collection.
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
## Communication
|
|
||||||
|
|
||||||
* Join the Ansible forum:
|
|
||||||
* [Get Help](https://forum.ansible.com/c/help/6): get help or help others.
|
|
||||||
* [Posts tagged with 'kubernetes'](https://forum.ansible.com/tag/kubernetes): subscribe to participate in collection-related conversations.
|
|
||||||
* [Social Spaces](https://forum.ansible.com/c/chat/4): gather and interact with fellow enthusiasts.
|
|
||||||
* [News & Announcements](https://forum.ansible.com/c/news/5): track project-wide announcements including social events.
|
|
||||||
|
|
||||||
* The Ansible [Bullhorn newsletter](https://docs.ansible.com/ansible/devel/community/communication.html#the-bullhorn): used to announce releases and important changes.
|
|
||||||
|
|
||||||
For more information about communication, see the [Ansible communication guide](https://docs.ansible.com/ansible/devel/community/communication.html).
|
|
||||||
|
|
||||||
## Requirements
|
|
||||||
|
|
||||||
<!--start requires_ansible-->
|
<!--start requires_ansible-->
|
||||||
## Ansible Version Compatibility
|
## Ansible version compatibility
|
||||||
|
|
||||||
This collection has been tested against following Ansible versions: **>=2.15.0**.
|
This collection has been tested against following Ansible versions: **>=2.14.0**.
|
||||||
|
|
||||||
For collections that support Ansible 2.9, please ensure you update your `network_os` to use the
|
For collections that support Ansible 2.9, please ensure you update your `network_os` to use the
|
||||||
fully qualified collection name (for example, `cisco.ios.ios`).
|
fully qualified collection name (for example, `cisco.ios.ios`).
|
||||||
@@ -32,41 +18,37 @@ A collection may contain metadata that identifies these versions.
|
|||||||
PEP440 is the schema used to describe the versions of Ansible.
|
PEP440 is the schema used to describe the versions of Ansible.
|
||||||
<!--end requires_ansible-->
|
<!--end requires_ansible-->
|
||||||
|
|
||||||
### Helm Version Compatibility
|
## Python Support
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
* Collection supports 3.9+
|
* Collection supports 3.9+
|
||||||
|
|
||||||
Note: Python2 is deprecated from [1st January 2020](https://www.python.org/doc/sunset-python-2/). Please switch to Python3.
|
Note: Python2 is deprecated from [1st January 2020](https://www.python.org/doc/sunset-python-2/). Please switch to Python3.
|
||||||
|
|
||||||
### Kubernetes Version Support
|
## Kubernetes Version Support
|
||||||
|
|
||||||
This collection supports Kubernetes versions >= 1.24.
|
This collection supports Kubernetes versions >= 1.24.
|
||||||
|
|
||||||
### Included Content
|
## Included content
|
||||||
|
|
||||||
Click on the name of a plugin or module to view that content's documentation:
|
Click on the name of a plugin or module to view that content's documentation:
|
||||||
|
|
||||||
<!--start collection content-->
|
<!--start collection content-->
|
||||||
### Connection Plugins
|
### Connection plugins
|
||||||
Name | Description
|
Name | Description
|
||||||
--- | ---
|
--- | ---
|
||||||
[kubernetes.core.kubectl](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.kubectl_connection.rst)|Execute tasks in pods running on Kubernetes.
|
[kubernetes.core.kubectl](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.kubectl_connection.rst)|Execute tasks in pods running on Kubernetes.
|
||||||
|
|
||||||
### K8s filter Plugins
|
### K8s filter plugins
|
||||||
Name | Description
|
Name | Description
|
||||||
--- | ---
|
--- | ---
|
||||||
kubernetes.core.k8s_config_resource_name|Generate resource name for the given resource of type ConfigMap, Secret
|
kubernetes.core.k8s_config_resource_name|Generate resource name for the given resource of type ConfigMap, Secret
|
||||||
|
|
||||||
### Inventory Plugins
|
### Inventory plugins
|
||||||
Name | Description
|
Name | Description
|
||||||
--- | ---
|
--- | ---
|
||||||
[kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_inventory.rst)|Kubernetes (K8s) inventory source
|
[kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_inventory.rst)|Kubernetes (K8s) inventory source
|
||||||
|
|
||||||
### Lookup Plugins
|
### Lookup plugins
|
||||||
Name | Description
|
Name | Description
|
||||||
--- | ---
|
--- | ---
|
||||||
[kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_lookup.rst)|Query the K8s API
|
[kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_lookup.rst)|Query the K8s API
|
||||||
@@ -80,7 +62,6 @@ Name | Description
|
|||||||
[kubernetes.core.helm_plugin](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_plugin_module.rst)|Manage Helm plugins
|
[kubernetes.core.helm_plugin](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_plugin_module.rst)|Manage Helm plugins
|
||||||
[kubernetes.core.helm_plugin_info](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_plugin_info_module.rst)|Gather information about Helm plugins
|
[kubernetes.core.helm_plugin_info](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_plugin_info_module.rst)|Gather information about Helm plugins
|
||||||
[kubernetes.core.helm_pull](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_pull_module.rst)|download a chart from a repository and (optionally) unpack it in local directory.
|
[kubernetes.core.helm_pull](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_pull_module.rst)|download a chart from a repository and (optionally) unpack it in local directory.
|
||||||
[kubernetes.core.helm_registry_auth](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_registry_auth_module.rst)|Helm registry authentication module
|
|
||||||
[kubernetes.core.helm_repository](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_repository_module.rst)|Manage Helm repositories.
|
[kubernetes.core.helm_repository](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_repository_module.rst)|Manage Helm repositories.
|
||||||
[kubernetes.core.helm_template](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_template_module.rst)|Render chart templates
|
[kubernetes.core.helm_template](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_template_module.rst)|Render chart templates
|
||||||
[kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_module.rst)|Manage Kubernetes (K8s) objects
|
[kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_module.rst)|Manage Kubernetes (K8s) objects
|
||||||
@@ -98,7 +79,9 @@ Name | Description
|
|||||||
|
|
||||||
<!--end collection content-->
|
<!--end collection content-->
|
||||||
|
|
||||||
## Installation
|
## Installation and Usage
|
||||||
|
|
||||||
|
### Installing the Collection from Ansible Galaxy
|
||||||
|
|
||||||
Before using the Kubernetes collection, you need to install it with the Ansible Galaxy CLI:
|
Before using the Kubernetes collection, you need to install it with the Ansible Galaxy CLI:
|
||||||
|
|
||||||
@@ -110,7 +93,7 @@ You can also include it in a `requirements.yml` file and install it via `ansible
|
|||||||
---
|
---
|
||||||
collections:
|
collections:
|
||||||
- name: kubernetes.core
|
- name: kubernetes.core
|
||||||
version: 5.4.2
|
version: 3.0.0
|
||||||
```
|
```
|
||||||
|
|
||||||
### Installing the Kubernetes Python Library
|
### Installing the Kubernetes Python Library
|
||||||
@@ -119,7 +102,7 @@ Content in this collection requires the [Kubernetes Python client](https://pypi.
|
|||||||
|
|
||||||
pip3 install kubernetes
|
pip3 install kubernetes
|
||||||
|
|
||||||
## Use Cases
|
### Using modules from the Kubernetes Collection in your playbooks
|
||||||
|
|
||||||
It's preferable to use content in this collection using their Fully Qualified Collection Namespace (FQCN), for example `kubernetes.core.k8s_info`:
|
It's preferable to use content in this collection using their Fully Qualified Collection Namespace (FQCN), for example `kubernetes.core.k8s_info`:
|
||||||
|
|
||||||
@@ -187,7 +170,8 @@ If upgrading older playbooks which were built prior to Ansible 2.10 and this col
|
|||||||
|
|
||||||
For documentation on how to use individual modules and other content included in this collection, please see the links in the 'Included content' section earlier in this README.
|
For documentation on how to use individual modules and other content included in this collection, please see the links in the 'Included content' section earlier in this README.
|
||||||
|
|
||||||
## Ansible Turbo Mode Tech Preview
|
## Ansible Turbo mode Tech Preview
|
||||||
|
|
||||||
|
|
||||||
The ``kubernetes.core`` collection supports Ansible Turbo mode as a tech preview via the ``cloud.common`` collection. By default, this feature is disabled. To enable Turbo mode for modules, set the environment variable `ENABLE_TURBO_MODE=1` on the managed node. For example:
|
The ``kubernetes.core`` collection supports Ansible Turbo mode as a tech preview via the ``cloud.common`` collection. By default, this feature is disabled. To enable Turbo mode for modules, set the environment variable `ENABLE_TURBO_MODE=1` on the managed node. For example:
|
||||||
|
|
||||||
@@ -205,16 +189,12 @@ defined in the playbook using `environment` keyword as above, you must set it us
|
|||||||
|
|
||||||
Please read more about Ansible Turbo mode - [here](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/ansible_turbo_mode.rst).
|
Please read more about Ansible Turbo mode - [here](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/ansible_turbo_mode.rst).
|
||||||
|
|
||||||
## Contributing to this Collection
|
## Testing and Development
|
||||||
|
|
||||||
If you want to develop new content for this collection or improve what's already here, the easiest way to work on the collection is to clone it into one of the configured [`COLLECTIONS_PATHS`](https://docs.ansible.com/ansible/latest/reference_appendices/config.html#collections-paths), and work on it there.
|
If you want to develop new content for this collection or improve what's already here, the easiest way to work on the collection is to clone it into one of the configured [`COLLECTIONS_PATHS`](https://docs.ansible.com/ansible/latest/reference_appendices/config.html#collections-paths), and work on it there.
|
||||||
|
|
||||||
See [Contributing to kubernetes.core](CONTRIBUTING.md).
|
See [Contributing to kubernetes.core](CONTRIBUTING.md).
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
[](https://github.com/ansible-collections/kubernetes.core/actions/workflows/linters.yaml) [](https://github.com/ansible-collections/kubernetes.core/actions/workflows/integration-tests.yaml) [](https://github.com/ansible-collections/kubernetes.core/actions/workflows/sanity-tests.yaml) [](https://github.com/ansible-collections/kubernetes.core/actions/workflows/unit-tests.yaml) [](https://app.codecov.io/gh/ansible-collections/kubernetes.core)
|
|
||||||
|
|
||||||
### Testing with `ansible-test`
|
### Testing with `ansible-test`
|
||||||
|
|
||||||
The `tests` directory contains configuration for running sanity and integration tests using [`ansible-test`](https://docs.ansible.com/ansible/latest/dev_guide/testing_integration.html).
|
The `tests` directory contains configuration for running sanity and integration tests using [`ansible-test`](https://docs.ansible.com/ansible/latest/dev_guide/testing_integration.html).
|
||||||
@@ -227,7 +207,7 @@ You can run the collection's test suites with the commands:
|
|||||||
|
|
||||||
### Testing with `molecule`
|
### Testing with `molecule`
|
||||||
|
|
||||||
There are also integration tests in the `molecule` directory which are meant to be run against a local Kubernetes cluster, e.g. using [KinD](https://kind.sigs.k8s.io) or [Minikube](https://minikube.sigs.k8s.io). To set up a local cluster using KinD and run Molecule:
|
There are also integration tests in the `molecule` directory which are meant to be run against a local Kubernetes cluster, e.g. using [KinD](https://kind.sigs.k8s.io) or [Minikube](https://minikube.sigs.k8s.io). To setup a local cluster using KinD and run Molecule:
|
||||||
|
|
||||||
kind create cluster
|
kind create cluster
|
||||||
make test-molecule
|
make test-molecule
|
||||||
@@ -251,35 +231,12 @@ After the version is published, verify it exists on the [Kubernetes Collection G
|
|||||||
|
|
||||||
The process for uploading a supported release to Automation Hub is documented separately.
|
The process for uploading a supported release to Automation Hub is documented separately.
|
||||||
|
|
||||||
## Support
|
## More Information
|
||||||
|
|
||||||
<!--List available communication channels. In addition to channels specific to your collection, we also recommend to use the following ones.-->
|
For more information about Ansible's Kubernetes integration, join the `#ansible-kubernetes` channel on [libera.chat](https://libera.chat/) IRC, and browse the resources in the [Kubernetes Working Group](https://github.com/ansible/community/wiki/Kubernetes) Community wiki page.
|
||||||
|
|
||||||
> **Note:** The `stable-4` branch, which handles all `4.x.y` releases of this collection, is no longer supported. This means that no backports nor releases will be performed on the `stable-4` branch.
|
|
||||||
|
|
||||||
We announce releases and important changes through Ansible's [The Bullhorn newsletter](https://github.com/ansible/community/wiki/News#the-bullhorn). Be sure you are [subscribed](https://eepurl.com/gZmiEP).
|
|
||||||
|
|
||||||
We take part in the global quarterly [Ansible Contributor Summit](https://github.com/ansible/community/wiki/Contributor-Summit) virtually or in-person. Track [The Bullhorn newsletter](https://eepurl.com/gZmiEP) and join us.
|
|
||||||
|
|
||||||
For more information about communication, refer to the [Ansible Communication guide](https://docs.ansible.com/ansible/devel/community/communication.html).
|
|
||||||
|
|
||||||
For the latest supported versions, refer to the release notes below.
|
|
||||||
|
|
||||||
If you encounter issues or have questions, you can submit a support request through the following channels:
|
|
||||||
- GitHub Issues: Report bugs, request features, or ask questions by opening an issue in the [GitHub repository](https://github.com/ansible-collections/kubernetes.core/).
|
|
||||||
|
|
||||||
## Release Notes
|
|
||||||
|
|
||||||
See the [raw generated changelog](https://github.com/ansible-collections/kubernetes.core/blob/main/CHANGELOG.rst).
|
|
||||||
|
|
||||||
## Code of Conduct
|
|
||||||
|
|
||||||
We follow the [Ansible Code of Conduct](https://docs.ansible.com/ansible/devel/community/code_of_conduct.html) in all our interactions within this project.
|
|
||||||
|
|
||||||
If you encounter abusive behavior, please refer to the [policy violations](https://docs.ansible.com/ansible/devel/community/code_of_conduct.html#policy-violations) section of the Code for information on how to raise a complaint.
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
GNU General Public License v3.0 or later
|
GNU General Public License v3.0 or later
|
||||||
|
|
||||||
See LICENSE to see the full text.
|
See LICENCE to see the full text.
|
||||||
|
|||||||
@@ -854,265 +854,3 @@ releases:
|
|||||||
- 652-fix-json-patch-action.yml
|
- 652-fix-json-patch-action.yml
|
||||||
- 654-helm-expand-user.yml
|
- 654-helm-expand-user.yml
|
||||||
release_date: '2024-05-16'
|
release_date: '2024-05-16'
|
||||||
3.2.0:
|
|
||||||
changes:
|
|
||||||
minor_changes:
|
|
||||||
- connection/kubectl.py - Added an example of using the kubectl connection plugin
|
|
||||||
to the documentation (https://github.com/ansible-collections/kubernetes.core/pull/741).
|
|
||||||
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 5.0 (https://github.com/ansible-collections/kubernetes.core/pull/723).
|
|
||||||
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 6.0.0
|
|
||||||
(https://github.com/ansible-collections/kubernetes.core/pull/734).
|
|
||||||
release_summary: This release comes with documentation updates.
|
|
||||||
fragments:
|
|
||||||
- 20240530-defer-removal-and-ansible-core-support-update.yaml
|
|
||||||
- 20240601-doc-example-of-using-kubectl.yaml
|
|
||||||
- 3.2.0.yml
|
|
||||||
- inventory-update_removal_date.yml
|
|
||||||
release_date: '2024-06-14'
|
|
||||||
3.3.0:
|
|
||||||
changes:
|
|
||||||
bugfixes:
|
|
||||||
- helm - Helm version checks did not support RC versions. They now accept any
|
|
||||||
version tags. (https://github.com/ansible-collections/kubernetes.core/pull/745).
|
|
||||||
- helm_pull - Apply no_log=True to pass_credentials to silence false positive
|
|
||||||
warning. (https://github.com/ansible-collections/kubernetes.core/pull/796).
|
|
||||||
- k8s_drain - Fix k8s_drain does not wait for single pod (https://github.com/ansible-collections/kubernetes.core/issues/769).
|
|
||||||
- k8s_drain - Fix k8s_drain runs into a timeout when evicting a pod which is
|
|
||||||
part of a stateful set (https://github.com/ansible-collections/kubernetes.core/issues/792).
|
|
||||||
- kubeconfig option should not appear in module invocation log (https://github.com/ansible-collections/kubernetes.core/issues/782).
|
|
||||||
- kustomize - kustomize plugin fails with deprecation warnings (https://github.com/ansible-collections/kubernetes.core/issues/639).
|
|
||||||
- waiter - Fix waiting for daemonset when desired number of pods is 0. (https://github.com/ansible-collections/kubernetes.core/pull/756).
|
|
||||||
minor_changes:
|
|
||||||
- k8s_drain - Improve error message for pod disruption budget when draining
|
|
||||||
a node (https://github.com/ansible-collections/kubernetes.core/issues/797).
|
|
||||||
release_summary: This release comes with improvements to the error messages
|
|
||||||
in the k8s_drain module and several bug fixes.
|
|
||||||
fragments:
|
|
||||||
- 20240530-ansible-core-support-update.yaml
|
|
||||||
- 20240611-helm-rc-version.yaml
|
|
||||||
- 20240620-fix-kustomize-plugin-fails-with-deprecation-warnings.yml
|
|
||||||
- 20241102-fix-ci-post-2.18-issue.yaml
|
|
||||||
- 20241213-kubeconfig-set-no_log-true.yaml
|
|
||||||
- 756-fix-daemonset-waiting.yaml
|
|
||||||
- 770-fix-k8s-drain-doesnt-wait-for-single-pod.yaml
|
|
||||||
- 793-fix-k8s-drain-runs-into-timeout.yaml
|
|
||||||
- 796-false-positive-helmull.yaml
|
|
||||||
- 798-drain-pdb-error-message.yaml
|
|
||||||
- readme_template_update.yml
|
|
||||||
release_date: '2025-01-20'
|
|
||||||
3.3.1:
|
|
||||||
changes:
|
|
||||||
release_summary: This release fixes the CI issues with the ``linters`` workflow.
|
|
||||||
fragments:
|
|
||||||
- release_summary.yml
|
|
||||||
release_date: '2025-03-26'
|
|
||||||
4.0.0:
|
|
||||||
changes:
|
|
||||||
bugfixes:
|
|
||||||
- Resolve Collections util resource discovery fails when complex subresources
|
|
||||||
present (https://github.com/ansible-collections/kubernetes.core/pull/676).
|
|
||||||
- align `helmdiff_check()` function commandline rendering with the `deploy()`
|
|
||||||
function (https://github.com/ansible-collections/kubernetes.core/pull/670).
|
|
||||||
- avoid unsafe conditions in integration tests (https://github.com/ansible-collections/kubernetes.core/pull/665).
|
|
||||||
- helm - use ``reuse-values`` when running ``helm diff`` command (https://github.com/ansible-collections/kubernetes.core/issues/680).
|
|
||||||
- integrations test helm_kubeconfig - set helm version to v3.10.3 to avoid incompatability
|
|
||||||
with new bitnami charts (https://github.com/ansible-collections/kubernetes.core/pull/670).
|
|
||||||
minor_changes:
|
|
||||||
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 5.0 (https://github.com/ansible-collections/kubernetes.core/pull/723).
|
|
||||||
- k8s - The module and K8sService were changed so warnings returned by the K8S
|
|
||||||
API are now displayed to the user.
|
|
||||||
release_summary: This major release brings several bug fixes. We have also removed
|
|
||||||
support for ``ansible-core<2.15`` and deprecated functions and class from
|
|
||||||
``module_utils/common.py``.
|
|
||||||
removed_features:
|
|
||||||
- k8s - Support for ``merge_type=json`` has been removed in version 4.0.0. Please
|
|
||||||
use ``kubernetes.core.k8s_json_patch`` instead (https://github.com/ansible-collections/kubernetes.core/pull/722).
|
|
||||||
- k8s_exec - the previously deprecated ``result.return_code`` return value has
|
|
||||||
been removed, consider using ``result.rc`` instead (https://github.com/ansible-collections/kubernetes.core/pull/726).
|
|
||||||
- module_utils/common.py - the previously deprecated ``K8sAnsibleMixin`` class
|
|
||||||
has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
|
|
||||||
- module_utils/common.py - the previously deprecated ``configuration_digest()``
|
|
||||||
function has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
|
|
||||||
- module_utils/common.py - the previously deprecated ``get_api_client()`` function
|
|
||||||
has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
|
|
||||||
- module_utils/common.py - the previously deprecated ``unique_string()`` function
|
|
||||||
has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
|
|
||||||
fragments:
|
|
||||||
- 20231206-fix-unsafe-condition-in-integration.yml
|
|
||||||
- 20240117-fix-helm-diff-cmd-line-rendering.yml
|
|
||||||
- 20240222-Collections-util-resource-discovery-fails-when-complex-subresources-present.yml
|
|
||||||
- 20240228-fix-helm-diff-with-reuse-values.yml
|
|
||||||
- 20240423-k8s-display-warnings-to-users.yml
|
|
||||||
- 4.0.0.yaml
|
|
||||||
- inventory-update_removal_date.yml
|
|
||||||
- k8s-merge_type-removed.yml
|
|
||||||
- module_utils-common-remove-deprecated-functions-and-class.yaml
|
|
||||||
release_date: '2024-05-24'
|
|
||||||
5.0.0:
|
|
||||||
changes:
|
|
||||||
breaking_changes:
|
|
||||||
- Remove support for ``ansible-core<2.15`` (https://github.com/ansible-collections/kubernetes.core/pull/737).
|
|
||||||
minor_changes:
|
|
||||||
- connection/kubectl.py - Added an example of using the kubectl connection plugin
|
|
||||||
to the documentation (https://github.com/ansible-collections/kubernetes.core/pull/741).
|
|
||||||
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 6.0.0
|
|
||||||
(https://github.com/ansible-collections/kubernetes.core/pull/734).
|
|
||||||
release_summary: This major release drops support for ``ansible-core<2.15``.
|
|
||||||
fragments:
|
|
||||||
- 20240530-ansible-core-support-update.yaml
|
|
||||||
- 20240530-defer-removal-and-ansible-core-support-update.yaml
|
|
||||||
- 5.0.0.yml
|
|
||||||
release_date: '2024-05-31'
|
|
||||||
5.1.0:
|
|
||||||
changes:
|
|
||||||
bugfixes:
|
|
||||||
- helm - Helm version checks did not support RC versions. They now accept any
|
|
||||||
version tags. (https://github.com/ansible-collections/kubernetes.core/pull/745).
|
|
||||||
- helm_pull - Apply no_log=True to pass_credentials to silence false positive
|
|
||||||
warning. (https://github.com/ansible-collections/kubernetes.core/pull/796).
|
|
||||||
- k8s_drain - Fix k8s_drain does not wait for single pod (https://github.com/ansible-collections/kubernetes.core/issues/769).
|
|
||||||
- k8s_drain - Fix k8s_drain runs into a timeout when evicting a pod which is
|
|
||||||
part of a stateful set (https://github.com/ansible-collections/kubernetes.core/issues/792).
|
|
||||||
- kubeconfig option should not appear in module invocation log (https://github.com/ansible-collections/kubernetes.core/issues/782).
|
|
||||||
- kustomize - kustomize plugin fails with deprecation warnings (https://github.com/ansible-collections/kubernetes.core/issues/639).
|
|
||||||
- waiter - Fix waiting for daemonset when desired number of pods is 0. (https://github.com/ansible-collections/kubernetes.core/pull/756).
|
|
||||||
minor_changes:
|
|
||||||
- Bump version of ``ansible-lint`` to minimum 24.7.0 (https://github.com/ansible-collections/kubernetes.core/pull/765).
|
|
||||||
- Parameter insecure_registry added to helm_template as equivalent of insecure-skip-tls-verify
|
|
||||||
(https://github.com/ansible-collections/kubernetes.core/pull/805).
|
|
||||||
- k8s_drain - Improve error message for pod disruption budget when draining
|
|
||||||
a node (https://github.com/ansible-collections/kubernetes.core/issues/797).
|
|
||||||
release_summary: This release came with new module ``helm_registry_auth``, improvements
|
|
||||||
to the error messages in the k8s_drain module, new parameter ``insecure_registry``
|
|
||||||
for ``helm_template`` module and several bug fixes.
|
|
||||||
fragments:
|
|
||||||
- 0-readme.yml
|
|
||||||
- 20240601-doc-example-of-using-kubectl.yaml
|
|
||||||
- 20240611-helm-rc-version.yaml
|
|
||||||
- 20240620-fix-kustomize-plugin-fails-with-deprecation-warnings.yml
|
|
||||||
- 20241102-fix-ci-post-2.18-issue.yaml
|
|
||||||
- 20241103-completly-remove-obsolate-communication-channel.yaml
|
|
||||||
- 20241207-add-insecure-skip-tls-verify-to-helm-template.yaml
|
|
||||||
- 20241213-kubeconfig-set-no_log-true.yaml
|
|
||||||
- 756-fix-daemonset-waiting.yaml
|
|
||||||
- 765-bump-ansible-lint-version.yml
|
|
||||||
- 770-fix-k8s-drain-doesnt-wait-for-single-pod.yaml
|
|
||||||
- 793-fix-k8s-drain-runs-into-timeout.yaml
|
|
||||||
- 796-false-positive-helmull.yaml
|
|
||||||
- 798-drain-pdb-error-message.yaml
|
|
||||||
- readme_template_update.yml
|
|
||||||
modules:
|
|
||||||
- description: Helm registry authentication module
|
|
||||||
name: helm_registry_auth
|
|
||||||
namespace: ''
|
|
||||||
release_date: '2025-01-20'
|
|
||||||
5.2.0:
|
|
||||||
changes:
|
|
||||||
minor_changes:
|
|
||||||
- k8s - Extend hidden_fields to allow the expression of more complex field types
|
|
||||||
to be hidden (https://github.com/ansible-collections/kubernetes.core/pull/872)
|
|
||||||
- k8s_info - Extend hidden_fields to allow the expression of more complex field
|
|
||||||
types to be hidden (https://github.com/ansible-collections/kubernetes.core/pull/872)
|
|
||||||
- 'waiter.py - add ClusterOperator support. The module can now check OpenShift
|
|
||||||
cluster health by verifying ClusterOperator status requiring ''Available:
|
|
||||||
True'', ''Degraded: False'', and ''Progressing: False'' for success. (https://github.com/ansible-collections/kubernetes.core/issues/869)'
|
|
||||||
release_summary: This release adds more functionality to the hidden_fields option
|
|
||||||
and support for waiting on ClusterOperators to reach a ready state.
|
|
||||||
fragments:
|
|
||||||
- 5.2.0.yml
|
|
||||||
- 643-extend-hidden-fields.yaml
|
|
||||||
- 879-clusteroperator-waiter.py.yaml
|
|
||||||
release_date: '2025-03-27'
|
|
||||||
5.3.0:
|
|
||||||
changes:
|
|
||||||
bugfixes:
|
|
||||||
- module_utils/k8s/service - fix issue when trying to delete resource using
|
|
||||||
`delete_options` and `check_mode=true` (https://github.com/ansible-collections/kubernetes.core/issues/892).
|
|
||||||
minor_changes:
|
|
||||||
- kubernetes.core - Bump version of ``ansible-lint`` to ``25.1.2`` (https://github.com/ansible-collections/kubernetes.core/pull/919).
|
|
||||||
- action/k8s_info - update templating mechanism with changes from ``ansible-core
|
|
||||||
2.19`` (https://github.com/ansible-collections/kubernetes.core/pull/888).
|
|
||||||
- helm - add ``reset_then_reuse_values`` support to helm module (https://github.com/ansible-collections/kubernetes.core/issues/803).
|
|
||||||
- helm - add support for ``insecure_skip_tls_verify`` option to helm and ``helm_repository`` (https://github.com/ansible-collections/kubernetes.core/issues/694).
|
|
||||||
release_summary: This release includes minor changes, bug fixes and also bumps
|
|
||||||
``ansible-lint`` version to ``25.1.2``.
|
|
||||||
fragments:
|
|
||||||
- 20250324-k8s_info-templating.yaml
|
|
||||||
- 5.3.0.yml
|
|
||||||
- 694-add-insecure-skip-tls-verify.yml
|
|
||||||
- 800-helm-add-reset_then_reuse_values-support.yml
|
|
||||||
- 898-k8s-dont-delete-in-check-mode.yaml
|
|
||||||
- 919-update-ansible-lint-version.yaml
|
|
||||||
release_date: '2025-05-16'
|
|
||||||
5.4.0:
|
|
||||||
changes:
|
|
||||||
minor_changes:
|
|
||||||
- Module ``helm_registry_auth`` does not support idempotency with ``helm >=
|
|
||||||
3.18.0`` (https://github.com/ansible-collections/kubernetes.core/pull/946).
|
|
||||||
release_summary: This release updates the ``helm_registry_auth`` module to match
|
|
||||||
the behavior of ``helm >= 3.18.0`` which reports a successful logout regardless
|
|
||||||
of the current state (i.e., no idempotency).
|
|
||||||
fragments:
|
|
||||||
- 20250411-kubeconfig-no_log-revert.yaml
|
|
||||||
- 20250503-fix-unit-tests.yml
|
|
||||||
- 20250605-fix-helm_registry_auth-integration_test.yaml
|
|
||||||
- 5.4.0.yml
|
|
||||||
release_date: '2025-08-12'
|
|
||||||
5.4.1:
|
|
||||||
changes:
|
|
||||||
bugfixes:
|
|
||||||
- Remove ``ansible.module_utils.six`` imports to avoid warnings (https://github.com/ansible-collections/kubernetes.core/pull/998).
|
|
||||||
- Update the `k8s_cp` module to also work for init containers (https://github.com/ansible-collections/kubernetes.core/pull/971).
|
|
||||||
- module_utils/k8s/service - hide fields first before creating diffs (https://github.com/ansible-collections/kubernetes.core/pull/915).
|
|
||||||
release_summary: This release includes bugfixes for k8s service field handling,
|
|
||||||
k8s_cp init containers support, and removes deprecated ansible.module_utils.six
|
|
||||||
imports.
|
|
||||||
fragments:
|
|
||||||
- 20250428-k8s-service-hide-fields-first.yaml
|
|
||||||
- 20250731-fix-k8s_cp-initcontainers.yaml
|
|
||||||
- 20250922-remove-ansible-six-imports.yaml
|
|
||||||
- 5.4.1.yml
|
|
||||||
release_date: '2025-10-07'
|
|
||||||
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'
|
|
||||||
|
|||||||
@@ -289,29 +289,6 @@ Parameters
|
|||||||
<div>Provide a URL for accessing the API. Can also be specified via <code>K8S_AUTH_HOST</code> environment variable.</div>
|
<div>Provide a URL for accessing the API. Can also be specified via <code>K8S_AUTH_HOST</code> environment variable.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>insecure_skip_tls_verify</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">boolean</span>
|
|
||||||
</div>
|
|
||||||
<div style="font-style: italic; font-size: small; color: darkgreen">added in 5.3.0</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
|
||||||
<li><div style="color: blue"><b>no</b> ←</div></li>
|
|
||||||
<li>yes</li>
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Skip tls certificate checks for the chart download.</div>
|
|
||||||
<div>Do not confuse with the <code>validate_certs</code> option.</div>
|
|
||||||
<div>This option is only available for helm >= 3.16.0.</div>
|
|
||||||
<div style="font-size: small; color: darkgreen"><br/>aliases: skip_tls_certs_check</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -458,28 +435,6 @@ Parameters
|
|||||||
<div>mutually exclusive with with <code>history_max</code>.</div>
|
<div>mutually exclusive with with <code>history_max</code>.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>reset_then_reuse_values</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">boolean</span>
|
|
||||||
</div>
|
|
||||||
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.0.0</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
|
||||||
<li><div style="color: blue"><b>no</b> ←</div></li>
|
|
||||||
<li>yes</li>
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>When upgrading package, reset the values to the ones built into the chart, apply the last release's values and merge in any overrides from parameters O(release_values), O(values_files) or O(set_values).</div>
|
|
||||||
<div>If O(reset_values) or O(reuse_values) is set to V(True), this is ignored.</div>
|
|
||||||
<div>This feature requires helm diff >= 3.9.12.</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -488,7 +443,7 @@ Parameters
|
|||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">boolean</span>
|
<span style="color: purple">boolean</span>
|
||||||
</div>
|
</div>
|
||||||
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.5.0</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
@@ -508,7 +463,7 @@ Parameters
|
|||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">boolean</span>
|
<span style="color: purple">boolean</span>
|
||||||
</div>
|
</div>
|
||||||
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.5.0</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
|||||||
@@ -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, <4.0.0 (https://github.com/helm/helm/releases)
|
- helm >= 3.0 (https://github.com/helm/helm/releases)
|
||||||
|
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
@@ -174,28 +174,6 @@ Parameters
|
|||||||
<div>location to write the chart.</div>
|
<div>location to write the chart.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>force</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">boolean</span>
|
|
||||||
</div>
|
|
||||||
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.3.0</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
|
||||||
<li><div style="color: blue"><b>no</b> ←</div></li>
|
|
||||||
<li>yes</li>
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Force download of the chart even if it already exists in the destination directory.</div>
|
|
||||||
<div>By default, the module will skip downloading if the chart with the same version already exists for idempotency.</div>
|
|
||||||
<div>When used with O(untar_chart=true), will remove any existing chart directory before extracting.</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="1">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -301,8 +279,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Whether or not to check tls certificate for the chart download.</div>
|
<div>Whether or not to check tls certificate for the chart download.</div>
|
||||||
<div>Requires helm >= 3.3.0. Alias <code>insecure_skip_tls_verify</code> added in 5.3.0.</div>
|
<div>Requires helm >= 3.3.0.</div>
|
||||||
<div style="font-size: small; color: darkgreen"><br/>aliases: insecure_skip_tls_verify</div>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -398,28 +375,11 @@ Examples
|
|||||||
username: myuser
|
username: myuser
|
||||||
password: mypassword123
|
password: mypassword123
|
||||||
|
|
||||||
- name: Download Chart (force re-download even if exists)
|
|
||||||
kubernetes.core.helm_pull:
|
|
||||||
chart_ref: redis
|
|
||||||
repo_url: https://charts.bitnami.com/bitnami
|
|
||||||
chart_version: '17.0.0'
|
|
||||||
destination: /path/to/chart
|
|
||||||
force: yes
|
|
||||||
|
|
||||||
- name: Download and untar chart (force re-extraction even if directory exists)
|
|
||||||
kubernetes.core.helm_pull:
|
|
||||||
chart_ref: redis
|
|
||||||
repo_url: https://charts.bitnami.com/bitnami
|
|
||||||
chart_version: '17.0.0'
|
|
||||||
destination: /path/to/chart
|
|
||||||
untar_chart: yes
|
|
||||||
force: yes
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Return Values
|
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
|
||||||
|
|
||||||
@@ -446,23 +406,6 @@ Common return values are documented `here <https://docs.ansible.com/projects/ans
|
|||||||
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">helm pull --repo test ...</div>
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">helm pull --repo test ...</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
|
||||||
<b>msg</b>
|
|
||||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">string</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>when chart already exists</td>
|
|
||||||
<td>
|
|
||||||
<div>A message indicating the result of the operation.</div>
|
|
||||||
<br/>
|
|
||||||
<div style="font-size: smaller"><b>Sample:</b></div>
|
|
||||||
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">Chart redis version 17.0.0 already exists in destination directory</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="1">
|
||||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
|||||||
@@ -1,333 +0,0 @@
|
|||||||
.. _kubernetes.core.helm_registry_auth_module:
|
|
||||||
|
|
||||||
|
|
||||||
**********************************
|
|
||||||
kubernetes.core.helm_registry_auth
|
|
||||||
**********************************
|
|
||||||
|
|
||||||
**Helm registry authentication module**
|
|
||||||
|
|
||||||
|
|
||||||
Version added: 5.1.0
|
|
||||||
|
|
||||||
.. contents::
|
|
||||||
:local:
|
|
||||||
:depth: 1
|
|
||||||
|
|
||||||
|
|
||||||
Synopsis
|
|
||||||
--------
|
|
||||||
- Helm registry authentication module allows you to login ``helm registry login`` and logout ``helm registry logout`` from a Helm registry.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Requirements
|
|
||||||
------------
|
|
||||||
The below requirements are needed on the host that executes this module.
|
|
||||||
|
|
||||||
- helm (https://github.com/helm/helm/releases) >= 3.8.0, <4.0.0
|
|
||||||
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<table border=0 cellpadding=0 class="documentation-table">
|
|
||||||
<tr>
|
|
||||||
<th colspan="1">Parameter</th>
|
|
||||||
<th>Choices/<font color="blue">Defaults</font></th>
|
|
||||||
<th width="100%">Comments</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>binary_path</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">path</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>The path of a helm binary to use.</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>ca_file</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">path</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Path to the CA certificate SSL file for verify registry server certificate.</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>cert_file</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">path</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Path to the client certificate SSL file for identify registry client using this certificate file.</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>host</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">string</span>
|
|
||||||
/ <span style="color: red">required</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Provide a URL for accessing the registry.</div>
|
|
||||||
<div style="font-size: small; color: darkgreen"><br/>aliases: registry_url</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>insecure</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">boolean</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
|
||||||
<li><div style="color: blue"><b>no</b> ←</div></li>
|
|
||||||
<li>yes</li>
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Allow connections to SSL sites without certs.</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>key_file</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">path</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Path to the client key SSL file for identify registry client using this key file.</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>password</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">string</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Password for the registry.</div>
|
|
||||||
<div style="font-size: small; color: darkgreen"><br/>aliases: repo_password</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>state</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">string</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
|
||||||
<li><div style="color: blue"><b>present</b> ←</div></li>
|
|
||||||
<li>absent</li>
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Desired state of the registry.</div>
|
|
||||||
<div>If set to V(present) attempt to log in to the remote registry server using the URL specified in O(host).</div>
|
|
||||||
<div>If set to V(absent) attempt to log out from the remote registry server using the URL specified in O(host).</div>
|
|
||||||
<div>As helm >= 3.18.0 reports successful logout even if the user is not logged in, this module will report a change regardless of the current state.</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>username</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">string</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Username for the registry.</div>
|
|
||||||
<div style="font-size: small; color: darkgreen"><br/>aliases: repo_username</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Examples
|
|
||||||
--------
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
- name: Login to remote registry
|
|
||||||
kubernetes.core.helm_registry_auth:
|
|
||||||
username: admin
|
|
||||||
password: "sample_password"
|
|
||||||
host: localhost:5000
|
|
||||||
|
|
||||||
- name: Logout from remote registry
|
|
||||||
kubernetes.core.helm_registry_auth:
|
|
||||||
state: absent
|
|
||||||
host: localhost:5000
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<table border=0 cellpadding=0 class="documentation-table">
|
|
||||||
<tr>
|
|
||||||
<th colspan="1">Key</th>
|
|
||||||
<th>Returned</th>
|
|
||||||
<th width="100%">Description</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
|
||||||
<b>command</b>
|
|
||||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">string</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>always</td>
|
|
||||||
<td>
|
|
||||||
<div>Full <code>helm</code> command executed</div>
|
|
||||||
<br/>
|
|
||||||
<div style="font-size: smaller"><b>Sample:</b></div>
|
|
||||||
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">/usr/local/bin/helm registry login oci-registry.domain.example --username=admin --password-stdin --insecure</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
|
||||||
<b>failed</b>
|
|
||||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">boolean</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>always</td>
|
|
||||||
<td>
|
|
||||||
<div>Indicate if the <code>helm</code> command failed</div>
|
|
||||||
<br/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
|
||||||
<b>stderr</b>
|
|
||||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">string</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>always</td>
|
|
||||||
<td>
|
|
||||||
<div>Full <code>helm</code> command stderr, in case you want to display it or examine the event log. Please be note that helm binnary may print messages to stderr even if the command is successful.</div>
|
|
||||||
<br/>
|
|
||||||
<div style="font-size: smaller"><b>Sample:</b></div>
|
|
||||||
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">Login Succeeded\n</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
|
||||||
<b>stderr_lines</b>
|
|
||||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">list</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>always</td>
|
|
||||||
<td>
|
|
||||||
<div>Full <code>helm</code> command stderr, in case you want to display it or examine the event log</div>
|
|
||||||
<br/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
|
||||||
<b>stdout</b>
|
|
||||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">string</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>always</td>
|
|
||||||
<td>
|
|
||||||
<div>Full <code>helm</code> command stdout, in case you want to display it or examine the event log</div>
|
|
||||||
<br/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
|
||||||
<b>stout_lines</b>
|
|
||||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">list</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>always</td>
|
|
||||||
<td>
|
|
||||||
<div>Full <code>helm</code> command stdout, in case you want to display it or examine the event log</div>
|
|
||||||
<br/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<br/><br/>
|
|
||||||
|
|
||||||
|
|
||||||
Status
|
|
||||||
------
|
|
||||||
|
|
||||||
|
|
||||||
Authors
|
|
||||||
~~~~~~~
|
|
||||||
|
|
||||||
- Yuriy Novostavskiy (@yurnov)
|
|
||||||
@@ -143,27 +143,6 @@ Parameters
|
|||||||
<div>Provide a URL for accessing the API. Can also be specified via <code>K8S_AUTH_HOST</code> environment variable.</div>
|
<div>Provide a URL for accessing the API. Can also be specified via <code>K8S_AUTH_HOST</code> environment variable.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>insecure_skip_tls_verify</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">boolean</span>
|
|
||||||
</div>
|
|
||||||
<div style="font-style: italic; font-size: small; color: darkgreen">added in 5.3.0</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
|
||||||
<li><div style="color: blue"><b>no</b> ←</div></li>
|
|
||||||
<li>yes</li>
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Skip tls certificate checks for the repository url.</div>
|
|
||||||
<div style="font-size: small; color: darkgreen"><br/>aliases: skip_tls_certs_check</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="1">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
|||||||
@@ -158,26 +158,6 @@ Parameters
|
|||||||
<div>Include custom resource descriptions in rendered templates.</div>
|
<div>Include custom resource descriptions in rendered templates.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>insecure_registry</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">boolean</span>
|
|
||||||
</div>
|
|
||||||
<div style="font-style: italic; font-size: small; color: darkgreen">added in 5.1.0</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
|
||||||
<li><div style="color: blue"><b>no</b> ←</div></li>
|
|
||||||
<li>yes</li>
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Skip TLS certificate checks for the chart download</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
|||||||
@@ -512,7 +512,6 @@ Notes
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
- the tar binary is required on the container when copying from local filesystem to pod.
|
- the tar binary is required on the container when copying from local filesystem to pod.
|
||||||
- the (init) container has to be started before you copy files or directories to it.
|
|
||||||
- To avoid SSL certificate validation errors when ``validate_certs`` is *True*, the full certificate chain for the API server must be provided via ``ca_cert`` or in the kubeconfig file.
|
- To avoid SSL certificate validation errors when ``validate_certs`` is *True*, the full certificate chain for the API server must be provided via ``ca_cert`` or in the kubeconfig file.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -423,7 +423,7 @@ Parameters
|
|||||||
<span style="color: purple">list</span>
|
<span style="color: purple">list</span>
|
||||||
/ <span style="color: purple">elements=string</span>
|
/ <span style="color: purple">elements=string</span>
|
||||||
</div>
|
</div>
|
||||||
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.5.0</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
@@ -595,8 +595,7 @@ Examples
|
|||||||
kubernetes.core.k8s_drain:
|
kubernetes.core.k8s_drain:
|
||||||
state: drain
|
state: drain
|
||||||
name: foo
|
name: foo
|
||||||
delete_options:
|
force: yes
|
||||||
force: yes
|
|
||||||
|
|
||||||
- name: Drain node "foo", but abort if there are pods not managed by a ReplicationController, Job, or DaemonSet, and use a grace period of 15 minutes.
|
- name: Drain node "foo", but abort if there are pods not managed by a ReplicationController, Job, or DaemonSet, and use a grace period of 15 minutes.
|
||||||
kubernetes.core.k8s_drain:
|
kubernetes.core.k8s_drain:
|
||||||
|
|||||||
@@ -168,13 +168,14 @@ Parameters
|
|||||||
<span style="color: purple">list</span>
|
<span style="color: purple">list</span>
|
||||||
/ <span style="color: purple">elements=string</span>
|
/ <span style="color: purple">elements=string</span>
|
||||||
</div>
|
</div>
|
||||||
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.5.0</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Hide fields matching any of the field definitions in the result</div>
|
<div>Hide fields matching any of the field definitions in the result</div>
|
||||||
<div>An example might be <code>hidden_fields=[metadata.managedFields]</code> or V(hidden_fields=[spec.containers[0].env[3].value]) or V(hidden_fields=[metadata.annotations[kubectl.kubernetes.io/last-applied-configuration]])</div>
|
<div>An example might be <code>hidden_fields=[metadata.managedFields]</code></div>
|
||||||
|
<div>Only field definitions that don't reference list items are supported (so V(spec.containers[0]) would not work)</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -701,21 +702,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
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ DEPRECATED
|
|||||||
----------
|
----------
|
||||||
:Removed in collection release after
|
:Removed in collection release after
|
||||||
:Why: As discussed in https://github.com/ansible-collections/kubernetes.core/issues/31, we decided to
|
:Why: As discussed in https://github.com/ansible-collections/kubernetes.core/issues/31, we decided to
|
||||||
remove the k8s inventory plugin in release 6.0.0.
|
remove the k8s inventory plugin in release 4.0.0.
|
||||||
|
|
||||||
:Alternative: Use :ref:`kubernetes.core.k8s_info <kubernetes.core.k8s_info_module>` and :ref:`ansible.builtin.add_host <ansible.builtin.add_host_module>` instead.
|
:Alternative: Use :ref:`kubernetes.core.k8s_info <kubernetes.core.k8s_info_module>` and :ref:`ansible.builtin.add_host <ansible.builtin.add_host_module>` instead.
|
||||||
|
|
||||||
@@ -357,7 +357,7 @@ Status
|
|||||||
------
|
------
|
||||||
|
|
||||||
|
|
||||||
- This inventory will be removed in version 6.0.0. *[deprecated]*
|
- This inventory will be removed in version 4.0.0. *[deprecated]*
|
||||||
- For more information see `DEPRECATED`_.
|
- For more information see `DEPRECATED`_.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ Parameters
|
|||||||
<td>
|
<td>
|
||||||
<div><code>apply</code> compares the desired resource definition with the previously supplied resource definition, ignoring properties that are automatically generated</div>
|
<div><code>apply</code> compares the desired resource definition with the previously supplied resource definition, ignoring properties that are automatically generated</div>
|
||||||
<div><code>apply</code> works better with Services than 'force=yes'</div>
|
<div><code>apply</code> works better with Services than 'force=yes'</div>
|
||||||
<div>Mutually exclusive with <code>merge_type</code>.</div>
|
<div>mutually exclusive with <code>merge_type</code></div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -216,7 +216,7 @@ Parameters
|
|||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">boolean</span>
|
<span style="color: purple">boolean</span>
|
||||||
</div>
|
</div>
|
||||||
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.5.0</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
@@ -389,13 +389,14 @@ Parameters
|
|||||||
<span style="color: purple">list</span>
|
<span style="color: purple">list</span>
|
||||||
/ <span style="color: purple">elements=string</span>
|
/ <span style="color: purple">elements=string</span>
|
||||||
</div>
|
</div>
|
||||||
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.5.0</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Hide fields matching this option in the result</div>
|
<div>Hide fields matching this option in the result</div>
|
||||||
<div>An example might be <code>hidden_fields=[metadata.managedFields]</code> or V(hidden_fields=[spec.containers[0].env[3].value]) or V(hidden_fields=[metadata.annotations[kubectl.kubernetes.io/last-applied-configuration]])</div>
|
<div>An example might be <code>hidden_fields=[metadata.managedFields]</code></div>
|
||||||
|
<div>Only field definitions that don't reference list items are supported (so V(spec.containers[0]) would not work)</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -512,17 +513,18 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li>json</li>
|
||||||
<li>merge</li>
|
<li>merge</li>
|
||||||
<li>strategic-merge</li>
|
<li>strategic-merge</li>
|
||||||
</ul>
|
</ul>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Whether to override the default patch merge approach with a specific type. By default, the strategic merge will typically be used.</div>
|
<div>Whether to override the default patch merge approach with a specific type. By default, the strategic merge will typically be used.</div>
|
||||||
<div>For example, Custom Resource Definitions typically aren't updatable by the usual strategic merge. You may want to use <code>merge</code> if you see "strategic merge patch format is not supported".</div>
|
<div>For example, Custom Resource Definitions typically aren't updatable by the usual strategic merge. You may want to use <code>merge</code> if you see "strategic merge patch format is not supported"</div>
|
||||||
<div>See <a href='https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/#use-a-json-merge-patch-to-update-a-deployment'>https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/#use-a-json-merge-patch-to-update-a-deployment</a></div>
|
<div>See <a href='https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/#use-a-json-merge-patch-to-update-a-deployment'>https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/#use-a-json-merge-patch-to-update-a-deployment</a></div>
|
||||||
<div>If more than one <code>merge_type</code> is given, the merge_types will be tried in order. This defaults to <code>['strategic-merge', 'merge']</code>, which is ideal for using the same parameters on resource kinds that combine Custom Resources and built-in resources.</div>
|
<div>If more than one <code>merge_type</code> is given, the merge_types will be tried in order. This defaults to <code>['strategic-merge', 'merge']</code>, which is ideal for using the same parameters on resource kinds that combine Custom Resources and built-in resources.</div>
|
||||||
<div>Mutually exclusive with <code>apply</code>.</div>
|
<div>mutually exclusive with <code>apply</code></div>
|
||||||
<div><em>merge_type=json</em> has been removed in version 4.0.0. Please use <span class='module'>kubernetes.core.k8s_json_patch</span> instead.</div>
|
<div><em>merge_type=json</em> is deprecated and will be removed in version 4.0.0. Please use <span class='module'>kubernetes.core.k8s_json_patch</span> instead.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -365,82 +365,6 @@ Parameters
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Examples
|
|
||||||
--------
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
- name: Run a command in a pod using local kubectl with kubeconfig file ~/.kube/config
|
|
||||||
hosts: localhost
|
|
||||||
gather_facts: no
|
|
||||||
vars:
|
|
||||||
ansible_connection: kubernetes.core.kubectl
|
|
||||||
ansible_kubectl_namespace: my-namespace
|
|
||||||
ansible_kubectl_pod: my-pod
|
|
||||||
ansible_kubectl_container: my-container
|
|
||||||
tasks:
|
|
||||||
# be aware that the command is executed as the user that started the container
|
|
||||||
# and requires python to be installed in the image
|
|
||||||
- name: Run a command in a pod
|
|
||||||
ansible.builtin.command: echo "Hello, World!"
|
|
||||||
|
|
||||||
- name: Run a command in a pod using local kubectl with inventory variables
|
|
||||||
# Example inventory:
|
|
||||||
# k8s:
|
|
||||||
# hosts:
|
|
||||||
# foo.example.com:
|
|
||||||
# ansible_connection: kubernetes.core.kubectl
|
|
||||||
# ansible_kubectl_kubeconfig: /root/.kube/foo.example.com.config
|
|
||||||
# ansible_kubectl_pod: my-foo-pod
|
|
||||||
# ansible_kubectl_container: my-foo-container
|
|
||||||
# ansible_kubectl_namespace: my-foo-namespace
|
|
||||||
# bar.example.com:
|
|
||||||
# ansible_connection: kubernetes.core.kubectl
|
|
||||||
# ansible_kubectl_kubeconfig: /root/.kube/bar.example.com.config
|
|
||||||
# ansible_kubectl_pod: my-bar-pod
|
|
||||||
# ansible_kubectl_container: my-bar-container
|
|
||||||
# ansible_kubectl_namespace: my-bar-namespace
|
|
||||||
hosts: k8s
|
|
||||||
gather_facts: no
|
|
||||||
tasks:
|
|
||||||
# be aware that the command is executed as the user that started the container
|
|
||||||
# and requires python to be installed in the image
|
|
||||||
- name: Run a command in a pod
|
|
||||||
ansible.builtin.command: echo "Hello, World!"
|
|
||||||
|
|
||||||
- name: Run a command in a pod using dynamic inventory
|
|
||||||
hosts: localhost
|
|
||||||
gather_facts: no
|
|
||||||
vars:
|
|
||||||
kubeconfig: /root/.kube/config
|
|
||||||
namespace: my-namespace
|
|
||||||
my_app: my-app
|
|
||||||
tasks:
|
|
||||||
- name: Get My App pod info based on label
|
|
||||||
kubernetes.core.k8s_info:
|
|
||||||
kubeconfig: "{{ kubeconfig }}"
|
|
||||||
namespace: "{{ namespace }}"
|
|
||||||
kind: Pod
|
|
||||||
label_selectors: app.kubernetes.io/name = "{{ my_app }}"
|
|
||||||
register: my_app_pod
|
|
||||||
|
|
||||||
- name: Get My App pod name
|
|
||||||
ansible.builtin.set_fact:
|
|
||||||
my_app_pod_name: "{{ my_app_pod.resources[0].metadata.name }}"
|
|
||||||
|
|
||||||
- name: Add My App pod to inventory
|
|
||||||
ansible.builtin.add_host:
|
|
||||||
name: "{{ my_app_pod_name }}"
|
|
||||||
ansible_connection: kubernetes.core.kubectl
|
|
||||||
ansible_kubectl_kubeconfig: "{{ kubeconfig }}"
|
|
||||||
ansible_kubectl_pod: "{{ my_app_pod_name }}"
|
|
||||||
ansible_kubectl_namespace: "{{ namespace }}"
|
|
||||||
|
|
||||||
- name: Run a command in My App pod
|
|
||||||
# be aware that the command is executed as the user that started the container
|
|
||||||
# and requires python to be installed in the image
|
|
||||||
ansible.builtin.command: echo "Hello, World!"
|
|
||||||
delegate_to: "{{ my_app_pod_name }}"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ tags:
|
|||||||
- openshift
|
- openshift
|
||||||
- okd
|
- okd
|
||||||
- cluster
|
- cluster
|
||||||
version: 5.4.2
|
version: 3.1.0
|
||||||
build_ignore:
|
build_ignore:
|
||||||
- .DS_Store
|
- .DS_Store
|
||||||
- "*.tar.gz"
|
- "*.tar.gz"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
requires_ansible: '>=2.15.0'
|
requires_ansible: '>=2.14.0'
|
||||||
|
|
||||||
action_groups:
|
action_groups:
|
||||||
helm:
|
helm:
|
||||||
@@ -8,16 +8,13 @@ action_groups:
|
|||||||
- helm_repository
|
- helm_repository
|
||||||
k8s:
|
k8s:
|
||||||
- k8s
|
- k8s
|
||||||
- k8s_cluster_info
|
|
||||||
- k8s_cp
|
|
||||||
- k8s_drain
|
|
||||||
- k8s_exec
|
- k8s_exec
|
||||||
- k8s_info
|
- k8s_info
|
||||||
- k8s_json_patch
|
|
||||||
- k8s_log
|
- k8s_log
|
||||||
- k8s_rollback
|
|
||||||
- k8s_scale
|
- k8s_scale
|
||||||
- k8s_service
|
- k8s_service
|
||||||
|
- k8s_cp
|
||||||
|
- k8s_drain
|
||||||
|
|
||||||
plugin_routing:
|
plugin_routing:
|
||||||
inventory:
|
inventory:
|
||||||
@@ -25,10 +22,10 @@ plugin_routing:
|
|||||||
redirect: community.okd.openshift
|
redirect: community.okd.openshift
|
||||||
k8s:
|
k8s:
|
||||||
deprecation:
|
deprecation:
|
||||||
removal_version: 6.0.0
|
removal_version: 4.0.0
|
||||||
warning_text: >-
|
warning_text: >-
|
||||||
The k8s inventory plugin has been deprecated and
|
The k8s inventory plugin has been deprecated and
|
||||||
will be removed in release 6.0.0.
|
will be removed in release 4.0.0.
|
||||||
modules:
|
modules:
|
||||||
k8s_auth:
|
k8s_auth:
|
||||||
redirect: community.okd.k8s_auth
|
redirect: community.okd.k8s_auth
|
||||||
|
|||||||
@@ -22,20 +22,33 @@ from ansible.errors import (
|
|||||||
)
|
)
|
||||||
from ansible.module_utils._text import to_bytes, to_native, to_text
|
from ansible.module_utils._text import to_bytes, to_native, to_text
|
||||||
from ansible.module_utils.parsing.convert_bool import boolean
|
from ansible.module_utils.parsing.convert_bool import boolean
|
||||||
|
from ansible.module_utils.six import iteritems, string_types
|
||||||
from ansible.plugins.action import ActionBase
|
from ansible.plugins.action import ActionBase
|
||||||
|
|
||||||
try:
|
|
||||||
from ansible.template import trust_as_template
|
|
||||||
except ImportError:
|
|
||||||
trust_as_template = None
|
|
||||||
|
|
||||||
|
class RemoveOmit(object):
|
||||||
|
def __init__(self, buffer, omit_value):
|
||||||
|
try:
|
||||||
|
import yaml
|
||||||
|
except ImportError:
|
||||||
|
raise AnsibleError("Failed to import the required Python library (PyYAML).")
|
||||||
|
self.data = yaml.safe_load_all(buffer)
|
||||||
|
self.omit = omit_value
|
||||||
|
|
||||||
def _from_yaml_to_definition(buffer):
|
def remove_omit(self, data):
|
||||||
try:
|
if isinstance(data, dict):
|
||||||
import yaml
|
result = dict()
|
||||||
except ImportError:
|
for key, value in iteritems(data):
|
||||||
raise AnsibleError("Failed to import the required Python library (PyYAML).")
|
if value == self.omit:
|
||||||
return list(yaml.safe_load_all(buffer))
|
continue
|
||||||
|
result[key] = self.remove_omit(value)
|
||||||
|
return result
|
||||||
|
if isinstance(data, list):
|
||||||
|
return [self.remove_omit(v) for v in data if v != self.omit]
|
||||||
|
return data
|
||||||
|
|
||||||
|
def output(self):
|
||||||
|
return [self.remove_omit(d) for d in self.data]
|
||||||
|
|
||||||
|
|
||||||
ENV_KUBECONFIG_PATH_SEPARATOR = ";" if platform.system() == "Windows" else ":"
|
ENV_KUBECONFIG_PATH_SEPARATOR = ";" if platform.system() == "Windows" else ":"
|
||||||
@@ -99,7 +112,7 @@ class ActionModule(ActionBase):
|
|||||||
"trim_blocks": True,
|
"trim_blocks": True,
|
||||||
"lstrip_blocks": False,
|
"lstrip_blocks": False,
|
||||||
}
|
}
|
||||||
if isinstance(template, str):
|
if isinstance(template, string_types):
|
||||||
# treat this as raw_params
|
# treat this as raw_params
|
||||||
template_param["path"] = template
|
template_param["path"] = template
|
||||||
elif isinstance(template, dict):
|
elif isinstance(template, dict):
|
||||||
@@ -119,7 +132,7 @@ class ActionModule(ActionBase):
|
|||||||
):
|
):
|
||||||
if s_type in template_args:
|
if s_type in template_args:
|
||||||
value = ensure_type(template_args[s_type], "string")
|
value = ensure_type(template_args[s_type], "string")
|
||||||
if value is not None and not isinstance(value, str):
|
if value is not None and not isinstance(value, string_types):
|
||||||
raise AnsibleActionFail(
|
raise AnsibleActionFail(
|
||||||
"%s is expected to be a string, but got %s instead"
|
"%s is expected to be a string, but got %s instead"
|
||||||
% (s_type, type(value))
|
% (s_type, type(value))
|
||||||
@@ -194,8 +207,9 @@ class ActionModule(ActionBase):
|
|||||||
"'template' is only a supported parameter for the 'k8s' module."
|
"'template' is only a supported parameter for the 'k8s' module."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
omit_value = task_vars.get("omit")
|
||||||
template_params = []
|
template_params = []
|
||||||
if isinstance(template, str) or isinstance(template, dict):
|
if isinstance(template, string_types) or isinstance(template, dict):
|
||||||
template_params.append(self.get_template_args(template))
|
template_params.append(self.get_template_args(template))
|
||||||
elif isinstance(template, list):
|
elif isinstance(template, list):
|
||||||
for element in template:
|
for element in template:
|
||||||
@@ -216,18 +230,17 @@ class ActionModule(ActionBase):
|
|||||||
old_vars = self._templar.available_variables
|
old_vars = self._templar.available_variables
|
||||||
|
|
||||||
default_environment = {}
|
default_environment = {}
|
||||||
if trust_as_template is None:
|
for key in (
|
||||||
for key in (
|
"newline_sequence",
|
||||||
"newline_sequence",
|
"variable_start_string",
|
||||||
"variable_start_string",
|
"variable_end_string",
|
||||||
"variable_end_string",
|
"block_start_string",
|
||||||
"block_start_string",
|
"block_end_string",
|
||||||
"block_end_string",
|
"trim_blocks",
|
||||||
"trim_blocks",
|
"lstrip_blocks",
|
||||||
"lstrip_blocks",
|
):
|
||||||
):
|
if hasattr(self._templar.environment, key):
|
||||||
if hasattr(self._templar.environment, key):
|
default_environment[key] = getattr(self._templar.environment, key)
|
||||||
default_environment[key] = getattr(self._templar.environment, key)
|
|
||||||
for template_item in template_params:
|
for template_item in template_params:
|
||||||
# We need to convert unescaped sequences to proper escaped sequences for Jinja2
|
# We need to convert unescaped sequences to proper escaped sequences for Jinja2
|
||||||
newline_sequence = template_item["newline_sequence"]
|
newline_sequence = template_item["newline_sequence"]
|
||||||
@@ -244,35 +257,26 @@ class ActionModule(ActionBase):
|
|||||||
with self.get_template_data(template_item["path"]) as template_data:
|
with self.get_template_data(template_item["path"]) as template_data:
|
||||||
# add ansible 'template' vars
|
# add ansible 'template' vars
|
||||||
temp_vars = copy.deepcopy(task_vars)
|
temp_vars = copy.deepcopy(task_vars)
|
||||||
overrides = {}
|
for key, value in iteritems(template_item):
|
||||||
for key, value in template_item.items():
|
|
||||||
if hasattr(self._templar.environment, key):
|
if hasattr(self._templar.environment, key):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
overrides[key] = value
|
setattr(self._templar.environment, key, value)
|
||||||
if trust_as_template is None:
|
else:
|
||||||
setattr(self._templar.environment, key, value)
|
|
||||||
elif trust_as_template is None:
|
|
||||||
setattr(
|
setattr(
|
||||||
self._templar.environment,
|
self._templar.environment,
|
||||||
key,
|
key,
|
||||||
default_environment.get(key),
|
default_environment.get(key),
|
||||||
)
|
)
|
||||||
self._templar.available_variables = temp_vars
|
self._templar.available_variables = temp_vars
|
||||||
if trust_as_template:
|
result = self._templar.do_template(
|
||||||
template_data = trust_as_template(template_data)
|
template_data,
|
||||||
result = self._templar.template(
|
preserve_trailing_newlines=True,
|
||||||
template_data,
|
escape_backslashes=False,
|
||||||
preserve_trailing_newlines=True,
|
)
|
||||||
escape_backslashes=False,
|
if omit_value is not None:
|
||||||
overrides=overrides,
|
result_template.extend(RemoveOmit(result, omit_value).output())
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
result = self._templar.do_template(
|
result_template.append(result)
|
||||||
template_data,
|
|
||||||
preserve_trailing_newlines=True,
|
|
||||||
escape_backslashes=False,
|
|
||||||
)
|
|
||||||
result_template.extend(_from_yaml_to_definition(result))
|
|
||||||
self._templar.available_variables = old_vars
|
self._templar.available_variables = old_vars
|
||||||
resource_definition = self._task.args.get("definition", None)
|
resource_definition = self._task.args.get("definition", None)
|
||||||
if not resource_definition:
|
if not resource_definition:
|
||||||
@@ -302,7 +306,7 @@ class ActionModule(ActionBase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def get_kubeconfig(self, kubeconfig, remote_transport, new_module_args):
|
def get_kubeconfig(self, kubeconfig, remote_transport, new_module_args):
|
||||||
if isinstance(kubeconfig, str):
|
if isinstance(kubeconfig, string_types):
|
||||||
# find the kubeconfig in the expected search path
|
# find the kubeconfig in the expected search path
|
||||||
if not remote_transport:
|
if not remote_transport:
|
||||||
# kubeconfig is local
|
# kubeconfig is local
|
||||||
|
|||||||
@@ -181,81 +181,6 @@ DOCUMENTATION = r"""
|
|||||||
aliases: [ kubectl_verify_ssl ]
|
aliases: [ kubectl_verify_ssl ]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
EXAMPLES = r"""
|
|
||||||
|
|
||||||
- name: Run a command in a pod using local kubectl with kubeconfig file ~/.kube/config
|
|
||||||
hosts: localhost
|
|
||||||
gather_facts: no
|
|
||||||
vars:
|
|
||||||
ansible_connection: kubernetes.core.kubectl
|
|
||||||
ansible_kubectl_namespace: my-namespace
|
|
||||||
ansible_kubectl_pod: my-pod
|
|
||||||
ansible_kubectl_container: my-container
|
|
||||||
tasks:
|
|
||||||
# be aware that the command is executed as the user that started the container
|
|
||||||
# and requires python to be installed in the image
|
|
||||||
- name: Run a command in a pod
|
|
||||||
ansible.builtin.command: echo "Hello, World!"
|
|
||||||
|
|
||||||
- name: Run a command in a pod using local kubectl with inventory variables
|
|
||||||
# Example inventory:
|
|
||||||
# k8s:
|
|
||||||
# hosts:
|
|
||||||
# foo.example.com:
|
|
||||||
# ansible_connection: kubernetes.core.kubectl
|
|
||||||
# ansible_kubectl_kubeconfig: /root/.kube/foo.example.com.config
|
|
||||||
# ansible_kubectl_pod: my-foo-pod
|
|
||||||
# ansible_kubectl_container: my-foo-container
|
|
||||||
# ansible_kubectl_namespace: my-foo-namespace
|
|
||||||
# bar.example.com:
|
|
||||||
# ansible_connection: kubernetes.core.kubectl
|
|
||||||
# ansible_kubectl_kubeconfig: /root/.kube/bar.example.com.config
|
|
||||||
# ansible_kubectl_pod: my-bar-pod
|
|
||||||
# ansible_kubectl_container: my-bar-container
|
|
||||||
# ansible_kubectl_namespace: my-bar-namespace
|
|
||||||
hosts: k8s
|
|
||||||
gather_facts: no
|
|
||||||
tasks:
|
|
||||||
# be aware that the command is executed as the user that started the container
|
|
||||||
# and requires python to be installed in the image
|
|
||||||
- name: Run a command in a pod
|
|
||||||
ansible.builtin.command: echo "Hello, World!"
|
|
||||||
|
|
||||||
- name: Run a command in a pod using dynamic inventory
|
|
||||||
hosts: localhost
|
|
||||||
gather_facts: no
|
|
||||||
vars:
|
|
||||||
kubeconfig: /root/.kube/config
|
|
||||||
namespace: my-namespace
|
|
||||||
my_app: my-app
|
|
||||||
tasks:
|
|
||||||
- name: Get My App pod info based on label
|
|
||||||
kubernetes.core.k8s_info:
|
|
||||||
kubeconfig: "{{ kubeconfig }}"
|
|
||||||
namespace: "{{ namespace }}"
|
|
||||||
kind: Pod
|
|
||||||
label_selectors: app.kubernetes.io/name = "{{ my_app }}"
|
|
||||||
register: my_app_pod
|
|
||||||
|
|
||||||
- name: Get My App pod name
|
|
||||||
ansible.builtin.set_fact:
|
|
||||||
my_app_pod_name: "{{ my_app_pod.resources[0].metadata.name }}"
|
|
||||||
|
|
||||||
- name: Add My App pod to inventory
|
|
||||||
ansible.builtin.add_host:
|
|
||||||
name: "{{ my_app_pod_name }}"
|
|
||||||
ansible_connection: kubernetes.core.kubectl
|
|
||||||
ansible_kubectl_kubeconfig: "{{ kubeconfig }}"
|
|
||||||
ansible_kubectl_pod: "{{ my_app_pod_name }}"
|
|
||||||
ansible_kubectl_namespace: "{{ namespace }}"
|
|
||||||
|
|
||||||
- name: Run a command in My App pod
|
|
||||||
# be aware that the command is executed as the user that started the container
|
|
||||||
# and requires python to be installed in the image
|
|
||||||
ansible.builtin.command: echo "Hello, World!"
|
|
||||||
delegate_to: "{{ my_app_pod_name }}"
|
|
||||||
"""
|
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
@@ -265,7 +190,6 @@ import tempfile
|
|||||||
|
|
||||||
from ansible.errors import AnsibleError, AnsibleFileNotFound
|
from ansible.errors import AnsibleError, AnsibleFileNotFound
|
||||||
from ansible.module_utils._text import to_bytes
|
from ansible.module_utils._text import to_bytes
|
||||||
from ansible.module_utils.parsing.convert_bool import boolean
|
|
||||||
from ansible.module_utils.six.moves import shlex_quote
|
from ansible.module_utils.six.moves import shlex_quote
|
||||||
from ansible.parsing.yaml.loader import AnsibleLoader
|
from ansible.parsing.yaml.loader import AnsibleLoader
|
||||||
from ansible.plugins.connection import BUFSIZE, ConnectionBase
|
from ansible.plugins.connection import BUFSIZE, ConnectionBase
|
||||||
@@ -325,12 +249,9 @@ class Connection(ConnectionBase):
|
|||||||
# Build command options based on doc string
|
# Build command options based on doc string
|
||||||
doc_yaml = AnsibleLoader(self.documentation).get_single_data()
|
doc_yaml = AnsibleLoader(self.documentation).get_single_data()
|
||||||
for key in doc_yaml.get("options"):
|
for key in doc_yaml.get("options"):
|
||||||
if key == "validate_certs" and self.get_option(key) != "":
|
if key.endswith("verify_ssl") and self.get_option(key) != "":
|
||||||
# Translate validate_certs to --insecure-skip-tls-verify flag
|
# Translate verify_ssl to skip_verify_ssl, and output as string
|
||||||
# validate_certs=True means verify certs (don't skip verification)
|
skip_verify_ssl = not self.get_option(key)
|
||||||
# validate_certs=False means don't verify certs (skip verification)
|
|
||||||
validate_certs_value = boolean(self.get_option(key), strict=False)
|
|
||||||
skip_verify_ssl = not validate_certs_value
|
|
||||||
local_cmd.append(
|
local_cmd.append(
|
||||||
"{0}={1}".format(
|
"{0}={1}".format(
|
||||||
self.connection_options[key], str(skip_verify_ssl).lower()
|
self.connection_options[key], str(skip_verify_ssl).lower()
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ DOCUMENTATION = """
|
|||||||
- Uses k8s.(yml|yaml) YAML configuration file to set parameter values.
|
- Uses k8s.(yml|yaml) YAML configuration file to set parameter values.
|
||||||
|
|
||||||
deprecated:
|
deprecated:
|
||||||
removed_in: 6.0.0
|
removed_in: 4.0.0
|
||||||
why: |
|
why: |
|
||||||
As discussed in U(https://github.com/ansible-collections/kubernetes.core/issues/31), we decided to
|
As discussed in U(https://github.com/ansible-collections/kubernetes.core/issues/31), we decided to
|
||||||
remove the k8s inventory plugin in release 6.0.0.
|
remove the k8s inventory plugin in release 4.0.0.
|
||||||
alternative: "Use M(kubernetes.core.k8s_info) and M(ansible.builtin.add_host) instead."
|
alternative: "Use M(kubernetes.core.k8s_info) and M(ansible.builtin.add_host) instead."
|
||||||
|
|
||||||
options:
|
options:
|
||||||
@@ -125,19 +125,19 @@ import json
|
|||||||
|
|
||||||
from ansible.errors import AnsibleError
|
from ansible.errors import AnsibleError
|
||||||
from ansible.plugins.inventory import BaseInventoryPlugin, Cacheable, Constructable
|
from ansible.plugins.inventory import BaseInventoryPlugin, Cacheable, Constructable
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
|
||||||
try:
|
HAS_K8S_MODULE_HELPER,
|
||||||
from kubernetes.dynamic.exceptions import DynamicApiError
|
k8s_import_exception,
|
||||||
|
)
|
||||||
HAS_K8S_MODULE_HELPER = True
|
|
||||||
k8s_import_exception = None
|
|
||||||
except ImportError as e:
|
|
||||||
HAS_K8S_MODULE_HELPER = False
|
|
||||||
k8s_import_exception = e
|
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
||||||
get_api_client,
|
get_api_client,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
from kubernetes.dynamic.exceptions import DynamicApiError
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def format_dynamic_api_exc(exc):
|
def format_dynamic_api_exc(exc):
|
||||||
if exc.body:
|
if exc.body:
|
||||||
@@ -164,8 +164,8 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
|||||||
super(InventoryModule, self).parse(inventory, loader, path)
|
super(InventoryModule, self).parse(inventory, loader, path)
|
||||||
|
|
||||||
self.display.deprecated(
|
self.display.deprecated(
|
||||||
"The 'k8s' inventory plugin has been deprecated and will be removed in release 6.0.0",
|
"The 'k8s' inventory plugin has been deprecated and will be removed in release 4.0.0",
|
||||||
version="6.0.0",
|
version="4.0.0",
|
||||||
collection_name="kubernetes.core",
|
collection_name="kubernetes.core",
|
||||||
)
|
)
|
||||||
cache_key = self._get_cache_prefix(path)
|
cache_key = self._get_cache_prefix(path)
|
||||||
|
|||||||
@@ -86,48 +86,14 @@ DOCUMENTATION = """
|
|||||||
description:
|
description:
|
||||||
- Provide a username for authenticating with the API. Can also be specified via K8S_AUTH_USERNAME environment
|
- Provide a username for authenticating with the API. Can also be specified via K8S_AUTH_USERNAME environment
|
||||||
variable.
|
variable.
|
||||||
no_proxy:
|
|
||||||
description:
|
|
||||||
- The comma separated list of hosts/domains/IP/CIDR that shouldn't go through proxy.
|
|
||||||
Can also be specified via K8S_AUTH_NO_PROXY environment variable.
|
|
||||||
- Please note that this module does not pick up typical proxy settings from the environment (e.g. NO_PROXY).
|
|
||||||
- This feature requires kubernetes>=19.15.0.
|
|
||||||
When kubernetes library is less than 19.15.0, it fails even if no_proxy is set correctly.
|
|
||||||
type: str
|
|
||||||
password:
|
password:
|
||||||
description:
|
description:
|
||||||
- Provide a password for authenticating with the API. Can also be specified via K8S_AUTH_PASSWORD environment
|
- Provide a password for authenticating with the API. Can also be specified via K8S_AUTH_PASSWORD environment
|
||||||
variable.
|
variable.
|
||||||
proxy:
|
|
||||||
description:
|
|
||||||
- The URL of an HTTP proxy to use for the connection. Can also be specified via K8S_AUTH_PROXY environment variable.
|
|
||||||
- Please note that this module does not pick up typical proxy settings from the environment (e.g. HTTP_PROXY).
|
|
||||||
type: str
|
|
||||||
proxy_headers:
|
|
||||||
description:
|
|
||||||
- The Header used for the HTTP proxy.
|
|
||||||
- Documentation can be found here
|
|
||||||
U(https://urllib3.readthedocs.io/en/latest/reference/urllib3.util.html?highlight=proxy_headers#urllib3.util.make_headers).
|
|
||||||
type: dict
|
|
||||||
suboptions:
|
|
||||||
proxy_basic_auth:
|
|
||||||
type: str
|
|
||||||
description:
|
|
||||||
- Colon-separated username:password for proxy basic authentication header.
|
|
||||||
- Can also be specified via K8S_AUTH_PROXY_HEADERS_PROXY_BASIC_AUTH environment.
|
|
||||||
basic_auth:
|
|
||||||
type: str
|
|
||||||
description:
|
|
||||||
- Colon-separated username:password for basic authentication header.
|
|
||||||
- Can also be specified via K8S_AUTH_PROXY_HEADERS_BASIC_AUTH environment.
|
|
||||||
user_agent:
|
|
||||||
type: str
|
|
||||||
description:
|
|
||||||
- String representing the user-agent you want, such as foo/1.0.
|
|
||||||
- Can also be specified via K8S_AUTH_PROXY_HEADERS_USER_AGENT environment.
|
|
||||||
client_cert:
|
client_cert:
|
||||||
description:
|
description:
|
||||||
- Path to a certificate used to authenticate with the API. Can also be specified via K8S_AUTH_CERT_FILE environment
|
- Path to a certificate used to authenticate with the API. Can also be specified via K8S_AUTH_CERT_FILE
|
||||||
|
environment
|
||||||
variable.
|
variable.
|
||||||
aliases: [ cert_file ]
|
aliases: [ cert_file ]
|
||||||
client_key:
|
client_key:
|
||||||
|
|||||||
@@ -94,8 +94,7 @@ def get_binary_from_path(name, opt_dirs=None):
|
|||||||
|
|
||||||
def run_command(command):
|
def run_command(command):
|
||||||
cmd = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
cmd = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
stdout, stderr = cmd.communicate()
|
return cmd.communicate()
|
||||||
return cmd.returncode, stdout, stderr
|
|
||||||
|
|
||||||
|
|
||||||
class LookupModule(LookupBase):
|
class LookupModule(LookupBase):
|
||||||
@@ -141,18 +140,9 @@ class LookupModule(LookupBase):
|
|||||||
if enable_helm:
|
if enable_helm:
|
||||||
command += ["--enable-helm"]
|
command += ["--enable-helm"]
|
||||||
|
|
||||||
(ret, out, err) = run_command(command)
|
(out, err) = run_command(command)
|
||||||
if ret != 0:
|
if err:
|
||||||
if err:
|
raise AnsibleLookupError(
|
||||||
raise AnsibleLookupError(
|
"kustomize command failed with: {0}".format(err.decode("utf-8"))
|
||||||
"kustomize command failed. exit code: {0}, error: {1}".format(
|
)
|
||||||
ret, err.decode("utf-8")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
raise AnsibleLookupError(
|
|
||||||
"kustomize command failed with unknown error. exit code: {0}".format(
|
|
||||||
ret
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return [out.decode("utf-8")]
|
return [out.decode("utf-8")]
|
||||||
|
|||||||
@@ -149,7 +149,6 @@ def k8s_apply(resource, definition, **kwargs):
|
|||||||
force_conflicts=kwargs.get("force_conflicts"),
|
force_conflicts=kwargs.get("force_conflicts"),
|
||||||
field_manager=kwargs.get("field_manager"),
|
field_manager=kwargs.get("field_manager"),
|
||||||
dry_run=kwargs.get("dry_run"),
|
dry_run=kwargs.get("dry_run"),
|
||||||
serialize=kwargs.get("serialize"),
|
|
||||||
)
|
)
|
||||||
if not existing:
|
if not existing:
|
||||||
return resource.create(
|
return resource.create(
|
||||||
@@ -159,7 +158,6 @@ def k8s_apply(resource, definition, **kwargs):
|
|||||||
return resource.get(
|
return resource.get(
|
||||||
name=definition["metadata"]["name"],
|
name=definition["metadata"]["name"],
|
||||||
namespace=definition["metadata"].get("namespace"),
|
namespace=definition["metadata"].get("namespace"),
|
||||||
**kwargs
|
|
||||||
)
|
)
|
||||||
return resource.patch(
|
return resource.patch(
|
||||||
body=desired,
|
body=desired,
|
||||||
|
|||||||
@@ -1,64 +1,16 @@
|
|||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
from ansible.module_utils.six import string_types
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
|
|
||||||
def list_dict_str(value):
|
def list_dict_str(value):
|
||||||
if isinstance(value, (list, dict, str)):
|
if isinstance(value, (list, dict, string_types)):
|
||||||
return value
|
return value
|
||||||
raise TypeError
|
raise TypeError
|
||||||
|
|
||||||
|
|
||||||
def extract_sensitive_values_from_kubeconfig(kubeconfig_data):
|
|
||||||
"""
|
|
||||||
Extract only sensitive string values from kubeconfig data for no_log_values.
|
|
||||||
|
|
||||||
:arg kubeconfig_data: Dictionary containing kubeconfig data
|
|
||||||
:returns: Set of sensitive string values to be added to no_log_values
|
|
||||||
"""
|
|
||||||
values = set()
|
|
||||||
sensitive_fields = {
|
|
||||||
"token",
|
|
||||||
"password",
|
|
||||||
"secret",
|
|
||||||
"client-key-data",
|
|
||||||
"client-certificate-data",
|
|
||||||
"certificate-authority-data",
|
|
||||||
"api_key",
|
|
||||||
"access-token",
|
|
||||||
"refresh-token",
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check API version and warn if not v1
|
|
||||||
if isinstance(kubeconfig_data, dict):
|
|
||||||
api_version = kubeconfig_data.get("apiVersion", "v1")
|
|
||||||
if api_version != "v1":
|
|
||||||
warnings.warn(
|
|
||||||
f"Kubeconfig API version '{api_version}' is not 'v1'. "
|
|
||||||
f"Sensitive field redaction is only guaranteed for API version 'v1'. "
|
|
||||||
f"Some sensitive data may not be properly redacted from the logs.",
|
|
||||||
UserWarning,
|
|
||||||
)
|
|
||||||
|
|
||||||
def _extract_recursive(data, current_path=""):
|
|
||||||
if isinstance(data, dict):
|
|
||||||
for key, value in data.items():
|
|
||||||
path = f"{current_path}.{key}" if current_path else key
|
|
||||||
if key in sensitive_fields:
|
|
||||||
if isinstance(value, str):
|
|
||||||
values.add(value)
|
|
||||||
else:
|
|
||||||
_extract_recursive(value, path)
|
|
||||||
elif isinstance(data, list):
|
|
||||||
for i, item in enumerate(data):
|
|
||||||
_extract_recursive(item, f"{current_path}[{i}]")
|
|
||||||
|
|
||||||
_extract_recursive(kubeconfig_data)
|
|
||||||
return values
|
|
||||||
|
|
||||||
|
|
||||||
AUTH_PROXY_HEADERS_SPEC = dict(
|
AUTH_PROXY_HEADERS_SPEC = dict(
|
||||||
proxy_basic_auth=dict(type="str", no_log=True),
|
proxy_basic_auth=dict(type="str", no_log=True),
|
||||||
basic_auth=dict(type="str", no_log=True),
|
basic_auth=dict(type="str", no_log=True),
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -96,7 +96,7 @@ class K8SCopy(metaclass=ABCMeta):
|
|||||||
return error, stdout, stderr
|
return error, stdout, stderr
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.module.fail_json(
|
self.module.fail_json(
|
||||||
msg="Error while running/parsing from pod {0}/{1} command='{2}' : {3}".format(
|
msg="Error while running/parsing from pod {1}/{2} command='{0}' : {3}".format(
|
||||||
self.namespace, self.name, cmd, to_native(e)
|
self.namespace, self.name, cmd, to_native(e)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -278,15 +278,11 @@ class K8SCopyFromPod(K8SCopy):
|
|||||||
def run(self):
|
def run(self):
|
||||||
self.files_to_copy = self.list_remote_files()
|
self.files_to_copy = self.list_remote_files()
|
||||||
if self.files_to_copy == []:
|
if self.files_to_copy == []:
|
||||||
# Using warn method instead of passing warnings to exit_json as it is
|
|
||||||
# deprecated in ansible-core>=2.19.0
|
|
||||||
self._module.warn(
|
|
||||||
"No file found from directory '{0}' into remote Pod.".format(
|
|
||||||
self.remote_path
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.module.exit_json(
|
self.module.exit_json(
|
||||||
changed=False,
|
changed=False,
|
||||||
|
warning="No file found from directory '{0}' into remote Pod.".format(
|
||||||
|
self.remote_path
|
||||||
|
),
|
||||||
)
|
)
|
||||||
self.copy()
|
self.copy()
|
||||||
|
|
||||||
@@ -439,21 +435,11 @@ def check_pod(svc):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
result = svc.client.get(resource, name=name, namespace=namespace)
|
result = svc.client.get(resource, name=name, namespace=namespace)
|
||||||
containers = dict(
|
containers = [
|
||||||
{
|
c["name"] for c in result.to_dict()["status"]["containerStatuses"]
|
||||||
c["name"]: c
|
]
|
||||||
for cl in ["initContainerStatuses", "containerStatuses"]
|
if container and container not in containers:
|
||||||
for c in result.to_dict()["status"].get(cl, [])
|
|
||||||
}
|
|
||||||
)
|
|
||||||
if container and container not in containers.keys():
|
|
||||||
module.fail_json(msg="Pod has no container {0}".format(container))
|
module.fail_json(msg="Pod has no container {0}".format(container))
|
||||||
if (
|
return containers
|
||||||
container
|
|
||||||
and container in containers
|
|
||||||
and not bool(containers[container].get("started", False))
|
|
||||||
):
|
|
||||||
module.fail_json(msg="Pod container {0} is not started".format(container))
|
|
||||||
return containers.keys()
|
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
_fail(exc)
|
_fail(exc)
|
||||||
|
|||||||
@@ -15,9 +15,7 @@ import tempfile
|
|||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
|
from ansible.module_utils.six import string_types
|
||||||
extract_sensitive_values_from_kubeconfig,
|
|
||||||
)
|
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
|
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
|
||||||
LooseVersion,
|
LooseVersion,
|
||||||
)
|
)
|
||||||
@@ -79,6 +77,7 @@ def write_temp_kubeconfig(server, validate_certs=True, ca_cert=None, kubeconfig=
|
|||||||
|
|
||||||
|
|
||||||
class AnsibleHelmModule(object):
|
class AnsibleHelmModule(object):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
An Ansible module class for Kubernetes.core helm modules
|
An Ansible module class for Kubernetes.core helm modules
|
||||||
"""
|
"""
|
||||||
@@ -115,19 +114,12 @@ class AnsibleHelmModule(object):
|
|||||||
kubeconfig_content = None
|
kubeconfig_content = None
|
||||||
kubeconfig = self.params.get("kubeconfig")
|
kubeconfig = self.params.get("kubeconfig")
|
||||||
if kubeconfig:
|
if kubeconfig:
|
||||||
if isinstance(kubeconfig, str):
|
if isinstance(kubeconfig, string_types):
|
||||||
with open(os.path.expanduser(kubeconfig)) as fd:
|
with open(os.path.expanduser(kubeconfig)) as fd:
|
||||||
kubeconfig_content = yaml.safe_load(fd)
|
kubeconfig_content = yaml.safe_load(fd)
|
||||||
elif isinstance(kubeconfig, dict):
|
elif isinstance(kubeconfig, dict):
|
||||||
kubeconfig_content = kubeconfig
|
kubeconfig_content = kubeconfig
|
||||||
|
|
||||||
# Redact sensitive fields from kubeconfig for logging purposes
|
|
||||||
if kubeconfig_content:
|
|
||||||
# Add original sensitive values to no_log_values to prevent them from appearing in logs
|
|
||||||
self._module.no_log_values.update(
|
|
||||||
extract_sensitive_values_from_kubeconfig(kubeconfig_content)
|
|
||||||
)
|
|
||||||
|
|
||||||
if self.params.get("ca_cert"):
|
if self.params.get("ca_cert"):
|
||||||
ca_cert = self.params.get("ca_cert")
|
ca_cert = self.params.get("ca_cert")
|
||||||
if LooseVersion(self.get_helm_version()) < LooseVersion("3.5.0"):
|
if LooseVersion(self.get_helm_version()) < LooseVersion("3.5.0"):
|
||||||
@@ -168,13 +160,11 @@ class AnsibleHelmModule(object):
|
|||||||
self.helm_env = self._prepare_helm_environment()
|
self.helm_env = self._prepare_helm_environment()
|
||||||
return self.helm_env
|
return self.helm_env
|
||||||
|
|
||||||
def run_helm_command(self, command, fails_on_error=True, data=None):
|
def run_helm_command(self, command, fails_on_error=True):
|
||||||
if not HAS_YAML:
|
if not HAS_YAML:
|
||||||
self.fail_json(msg=missing_required_lib("PyYAML"), exception=YAML_IMP_ERR)
|
self.fail_json(msg=missing_required_lib("PyYAML"), exception=YAML_IMP_ERR)
|
||||||
|
|
||||||
rc, out, err = self.run_command(
|
rc, out, err = self.run_command(command, environ_update=self.env_update)
|
||||||
command, environ_update=self.env_update, data=data
|
|
||||||
)
|
|
||||||
if fails_on_error and rc != 0:
|
if fails_on_error and rc != 0:
|
||||||
self.fail_json(
|
self.fail_json(
|
||||||
msg="Failure when executing Helm command. Exited {0}.\nstdout: {1}\nstderr: {2}".format(
|
msg="Failure when executing Helm command. Exited {0}.\nstdout: {1}\nstderr: {2}".format(
|
||||||
@@ -194,32 +184,14 @@ class AnsibleHelmModule(object):
|
|||||||
def get_helm_version(self):
|
def get_helm_version(self):
|
||||||
command = self.get_helm_binary() + " version"
|
command = self.get_helm_binary() + " version"
|
||||||
rc, out, err = self.run_command(command)
|
rc, out, err = self.run_command(command)
|
||||||
m = re.match(r'version.BuildInfo{Version:"v(.*?)",', out)
|
m = re.match(r'version.BuildInfo{Version:"v([0-9\.]*)",', out)
|
||||||
if m:
|
if m:
|
||||||
return m.group(1)
|
return m.group(1)
|
||||||
m = re.match(r'Client: &version.Version{SemVer:"v(.*?)", ', out)
|
m = re.match(r'Client: &version.Version{SemVer:"v([0-9\.]*)", ', out)
|
||||||
if m:
|
if m:
|
||||||
return m.group(1)
|
return m.group(1)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def validate_helm_version(self):
|
|
||||||
"""
|
|
||||||
Validate that Helm version is >=3.0.0 and <4.0.0.
|
|
||||||
Helm 4 is not yet supported.
|
|
||||||
"""
|
|
||||||
helm_version = self.get_helm_version()
|
|
||||||
if helm_version is None:
|
|
||||||
self.fail_json(msg="Unable to determine Helm version")
|
|
||||||
|
|
||||||
if (LooseVersion(helm_version) < LooseVersion("3.0.0")) or (
|
|
||||||
LooseVersion(helm_version) >= LooseVersion("4.0.0")
|
|
||||||
):
|
|
||||||
self.fail_json(
|
|
||||||
msg="Helm version must be >=3.0.0,<4.0.0, current version is {0}".format(
|
|
||||||
helm_version
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_values(self, release_name, get_all=False):
|
def get_values(self, release_name, get_all=False):
|
||||||
"""
|
"""
|
||||||
Get Values from deployed release
|
Get Values from deployed release
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import hashlib
|
|||||||
import os
|
import os
|
||||||
from typing import Any, Dict, List, Optional
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
|
from ansible.module_utils.six import iteritems, string_types
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
|
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
|
||||||
AUTH_ARG_MAP,
|
AUTH_ARG_MAP,
|
||||||
AUTH_ARG_SPEC,
|
AUTH_ARG_SPEC,
|
||||||
@@ -114,7 +115,7 @@ def _load_config(auth: Dict) -> None:
|
|||||||
"persist_config": auth.get("persist_config"),
|
"persist_config": auth.get("persist_config"),
|
||||||
}
|
}
|
||||||
if kubeconfig:
|
if kubeconfig:
|
||||||
if isinstance(kubeconfig, str):
|
if isinstance(kubeconfig, string_types):
|
||||||
kubernetes.config.load_kube_config(config_file=kubeconfig, **optional_arg)
|
kubernetes.config.load_kube_config(config_file=kubeconfig, **optional_arg)
|
||||||
elif isinstance(kubeconfig, dict):
|
elif isinstance(kubeconfig, dict):
|
||||||
kubernetes.config.load_kube_config_from_dict(
|
kubernetes.config.load_kube_config_from_dict(
|
||||||
@@ -162,7 +163,7 @@ def _create_configuration(auth: Dict):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
configuration = kubernetes.client.Configuration()
|
configuration = kubernetes.client.Configuration()
|
||||||
|
|
||||||
for key, value in auth.items():
|
for key, value in iteritems(auth):
|
||||||
if key in AUTH_ARG_MAP.keys() and value is not None:
|
if key in AUTH_ARG_MAP.keys() and value is not None:
|
||||||
if key == "api_key":
|
if key == "api_key":
|
||||||
setattr(
|
setattr(
|
||||||
|
|||||||
@@ -3,9 +3,6 @@ from typing import Optional
|
|||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||||
from ansible.module_utils.common.text.converters import to_text
|
from ansible.module_utils.common.text.converters import to_text
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
|
|
||||||
extract_sensitive_values_from_kubeconfig,
|
|
||||||
)
|
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
|
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
|
||||||
LooseVersion,
|
LooseVersion,
|
||||||
)
|
)
|
||||||
@@ -36,15 +33,6 @@ class AnsibleK8SModule:
|
|||||||
|
|
||||||
self._module = self.settings["module_class"](**kwargs)
|
self._module = self.settings["module_class"](**kwargs)
|
||||||
|
|
||||||
# Apply kubeconfig redaction for logging purposes
|
|
||||||
if hasattr(self._module, "params") and hasattr(self._module, "no_log_values"):
|
|
||||||
kubeconfig = self._module.params.get("kubeconfig")
|
|
||||||
if kubeconfig and isinstance(kubeconfig, dict):
|
|
||||||
# Add sensitive values to no_log_values to prevent them from appearing in logs
|
|
||||||
self._module.no_log_values.update(
|
|
||||||
extract_sensitive_values_from_kubeconfig(kubeconfig)
|
|
||||||
)
|
|
||||||
|
|
||||||
if self.settings["check_k8s"]:
|
if self.settings["check_k8s"]:
|
||||||
self.requires("kubernetes")
|
self.requires("kubernetes")
|
||||||
self.has_at_least("kubernetes", "24.2.0", warn=True)
|
self.has_at_least("kubernetes", "24.2.0", warn=True)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
import os
|
import os
|
||||||
from typing import Dict, Iterable, List, Optional, Union, cast
|
from typing import Dict, Iterable, List, Optional, Union, cast
|
||||||
|
|
||||||
|
from ansible.module_utils.six import string_types
|
||||||
from ansible.module_utils.urls import Request
|
from ansible.module_utils.urls import Request
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -77,11 +78,11 @@ def create_definitions(params: Dict) -> List[ResourceDefinition]:
|
|||||||
def from_yaml(definition: Union[str, List, Dict]) -> Iterable[Dict]:
|
def from_yaml(definition: Union[str, List, Dict]) -> Iterable[Dict]:
|
||||||
"""Load resource definitions from a yaml definition."""
|
"""Load resource definitions from a yaml definition."""
|
||||||
definitions: List[Dict] = []
|
definitions: List[Dict] = []
|
||||||
if isinstance(definition, str):
|
if isinstance(definition, string_types):
|
||||||
definitions += yaml.safe_load_all(definition)
|
definitions += yaml.safe_load_all(definition)
|
||||||
elif isinstance(definition, list):
|
elif isinstance(definition, list):
|
||||||
for item in definition:
|
for item in definition:
|
||||||
if isinstance(item, str):
|
if isinstance(item, string_types):
|
||||||
definitions += yaml.safe_load_all(item)
|
definitions += yaml.safe_load_all(item)
|
||||||
else:
|
else:
|
||||||
definitions.append(item)
|
definitions.append(item)
|
||||||
|
|||||||
@@ -139,7 +139,6 @@ def perform_action(svc, definition: Dict, params: Dict) -> Dict:
|
|||||||
|
|
||||||
result = {"changed": False, "result": {}}
|
result = {"changed": False, "result": {}}
|
||||||
instance = {}
|
instance = {}
|
||||||
warnings = []
|
|
||||||
|
|
||||||
resource = svc.find_resource(kind, api_version, fail=True)
|
resource = svc.find_resource(kind, api_version, fail=True)
|
||||||
definition["kind"] = resource.kind
|
definition["kind"] = resource.kind
|
||||||
@@ -173,7 +172,7 @@ def perform_action(svc, definition: Dict, params: Dict) -> Dict:
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
if params.get("apply"):
|
if params.get("apply"):
|
||||||
instance, warnings = svc.apply(resource, definition, existing)
|
instance = svc.apply(resource, definition, existing)
|
||||||
result["method"] = "apply"
|
result["method"] = "apply"
|
||||||
elif not existing:
|
elif not existing:
|
||||||
if state == "patched":
|
if state == "patched":
|
||||||
@@ -184,19 +183,16 @@ def perform_action(svc, definition: Dict, params: Dict) -> Dict:
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
return result
|
return result
|
||||||
instance, warnings = svc.create(resource, definition)
|
instance = svc.create(resource, definition)
|
||||||
result["method"] = "create"
|
result["method"] = "create"
|
||||||
result["changed"] = True
|
result["changed"] = True
|
||||||
elif params.get("force", False):
|
elif params.get("force", False):
|
||||||
instance, warnings = svc.replace(resource, definition, existing)
|
instance = svc.replace(resource, definition, existing)
|
||||||
result["method"] = "replace"
|
result["method"] = "replace"
|
||||||
else:
|
else:
|
||||||
instance, warnings = svc.update(resource, definition, existing)
|
instance = svc.update(resource, definition, existing)
|
||||||
result["method"] = "update"
|
result["method"] = "update"
|
||||||
|
|
||||||
if warnings:
|
|
||||||
result["warnings"] = warnings
|
|
||||||
|
|
||||||
# If needed, wait and/or create diff
|
# If needed, wait and/or create diff
|
||||||
success = True
|
success = True
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,7 @@
|
|||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
from json import loads
|
from typing import Any, Dict, List, Optional, Tuple
|
||||||
from re import compile
|
|
||||||
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
||||||
|
|
||||||
from ansible.module_utils.common.dict_transformations import dict_merge
|
from ansible.module_utils.common.dict_transformations import dict_merge
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.hashes import (
|
from ansible_collections.kubernetes.core.plugins.module_utils.hashes import (
|
||||||
@@ -144,12 +142,18 @@ class K8sService:
|
|||||||
name: str,
|
name: str,
|
||||||
namespace: str,
|
namespace: str,
|
||||||
merge_type: str = None,
|
merge_type: str = None,
|
||||||
) -> Tuple[Dict, List[str]]:
|
) -> Dict:
|
||||||
|
if merge_type == "json":
|
||||||
|
self.module.deprecate(
|
||||||
|
msg="json as a merge_type value is deprecated. Please use the k8s_json_patch module instead.",
|
||||||
|
version="4.0.0",
|
||||||
|
collection_name="kubernetes.core",
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
params = dict(name=name, namespace=namespace, serialize=False)
|
params = dict(name=name, namespace=namespace)
|
||||||
if merge_type:
|
if merge_type:
|
||||||
params["content_type"] = "application/{0}-patch+json".format(merge_type)
|
params["content_type"] = "application/{0}-patch+json".format(merge_type)
|
||||||
return decode_response(self.client.patch(resource, definition, **params))
|
return self.client.patch(resource, definition, **params).to_dict()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
reason = e.body if hasattr(e, "body") else e
|
reason = e.body if hasattr(e, "body") else e
|
||||||
msg = "Failed to patch object: {0}".format(reason)
|
msg = "Failed to patch object: {0}".format(reason)
|
||||||
@@ -326,124 +330,123 @@ class K8sService:
|
|||||||
result["resources"].append(hide_fields(res, hidden_fields))
|
result["resources"].append(hide_fields(res, hidden_fields))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def create(self, resource: Resource, definition: Dict) -> Tuple[Dict, List[str]]:
|
def create(self, resource: Resource, definition: Dict) -> Dict:
|
||||||
namespace = definition["metadata"].get("namespace")
|
namespace = definition["metadata"].get("namespace")
|
||||||
name = definition["metadata"].get("name")
|
name = definition["metadata"].get("name")
|
||||||
|
|
||||||
if self._client_side_dry_run:
|
if self._client_side_dry_run:
|
||||||
return _encode_stringdata(definition), []
|
k8s_obj = _encode_stringdata(definition)
|
||||||
|
else:
|
||||||
try:
|
try:
|
||||||
return decode_response(
|
k8s_obj = self.client.create(
|
||||||
self.client.create(
|
resource, definition, namespace=namespace
|
||||||
resource, definition, namespace=namespace, serialize=False
|
).to_dict()
|
||||||
|
except ConflictError:
|
||||||
|
# Some resources, like ProjectRequests, can't be created multiple times,
|
||||||
|
# because the resources that they create don't match their kind
|
||||||
|
# In this case we'll mark it as unchanged and warn the user
|
||||||
|
self.module.warn(
|
||||||
|
"{0} was not found, but creating it returned a 409 Conflict error. This can happen \
|
||||||
|
if the resource you are creating does not directly create a resource of the same kind.".format(
|
||||||
|
name
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
return dict()
|
||||||
except ConflictError:
|
except Exception as e:
|
||||||
# Some resources, like ProjectRequests, can't be created multiple times,
|
reason = e.body if hasattr(e, "body") else e
|
||||||
# because the resources that they create don't match their kind
|
msg = "Failed to create object: {0}".format(reason)
|
||||||
# In this case we'll mark it as unchanged and warn the user
|
raise CoreException(msg) from e
|
||||||
self.module.warn(
|
return k8s_obj
|
||||||
"{0} was not found, but creating it returned a 409 Conflict error. This can happen \
|
|
||||||
if the resource you are creating does not directly create a resource of the same kind.".format(
|
|
||||||
name
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return dict(), []
|
|
||||||
except Exception as e:
|
|
||||||
reason = e.body if hasattr(e, "body") else e
|
|
||||||
msg = "Failed to create object: {0}".format(reason)
|
|
||||||
raise CoreException(msg) from e
|
|
||||||
|
|
||||||
def apply(
|
def apply(
|
||||||
self,
|
self,
|
||||||
resource: Resource,
|
resource: Resource,
|
||||||
definition: Dict,
|
definition: Dict,
|
||||||
existing: Optional[ResourceInstance] = None,
|
existing: Optional[ResourceInstance] = None,
|
||||||
) -> Tuple[Dict, List[str]]:
|
) -> Dict:
|
||||||
namespace = definition["metadata"].get("namespace")
|
namespace = definition["metadata"].get("namespace")
|
||||||
|
|
||||||
server_side_apply = self.module.params.get("server_side_apply")
|
server_side_apply = self.module.params.get("server_side_apply")
|
||||||
if server_side_apply:
|
if server_side_apply:
|
||||||
requires("kubernetes", "19.15.0", reason="to use server side apply")
|
requires("kubernetes", "19.15.0", reason="to use server side apply")
|
||||||
|
|
||||||
if self._client_side_dry_run:
|
if self._client_side_dry_run:
|
||||||
ignored, patch = apply_object(resource, _encode_stringdata(definition))
|
ignored, patch = apply_object(resource, _encode_stringdata(definition))
|
||||||
if existing:
|
if existing:
|
||||||
return dict_merge(existing.to_dict(), patch), []
|
k8s_obj = dict_merge(existing.to_dict(), patch)
|
||||||
else:
|
else:
|
||||||
return patch, []
|
k8s_obj = patch
|
||||||
|
else:
|
||||||
try:
|
try:
|
||||||
params = {}
|
params = {}
|
||||||
if server_side_apply:
|
if server_side_apply:
|
||||||
params["server_side"] = True
|
params["server_side"] = True
|
||||||
params.update(server_side_apply)
|
params.update(server_side_apply)
|
||||||
return decode_response(
|
k8s_obj = self.client.apply(
|
||||||
self.client.apply(
|
resource, definition, namespace=namespace, **params
|
||||||
resource, definition, namespace=namespace, serialize=False, **params
|
).to_dict()
|
||||||
)
|
except Exception as e:
|
||||||
)
|
reason = e.body if hasattr(e, "body") else e
|
||||||
except Exception as e:
|
msg = "Failed to apply object: {0}".format(reason)
|
||||||
reason = e.body if hasattr(e, "body") else e
|
raise CoreException(msg) from e
|
||||||
msg = "Failed to apply object: {0}".format(reason)
|
return k8s_obj
|
||||||
raise CoreException(msg) from e
|
|
||||||
|
|
||||||
def replace(
|
def replace(
|
||||||
self,
|
self,
|
||||||
resource: Resource,
|
resource: Resource,
|
||||||
definition: Dict,
|
definition: Dict,
|
||||||
existing: ResourceInstance,
|
existing: ResourceInstance,
|
||||||
) -> Tuple[Dict, List[str]]:
|
) -> Dict:
|
||||||
append_hash = self.module.params.get("append_hash", False)
|
append_hash = self.module.params.get("append_hash", False)
|
||||||
name = definition["metadata"].get("name")
|
name = definition["metadata"].get("name")
|
||||||
namespace = definition["metadata"].get("namespace")
|
namespace = definition["metadata"].get("namespace")
|
||||||
|
|
||||||
if self._client_side_dry_run:
|
if self._client_side_dry_run:
|
||||||
return _encode_stringdata(definition), []
|
k8s_obj = _encode_stringdata(definition)
|
||||||
|
else:
|
||||||
try:
|
try:
|
||||||
return decode_response(
|
k8s_obj = self.client.replace(
|
||||||
self.client.replace(
|
|
||||||
resource,
|
resource,
|
||||||
definition,
|
definition,
|
||||||
name=name,
|
name=name,
|
||||||
namespace=namespace,
|
namespace=namespace,
|
||||||
append_hash=append_hash,
|
append_hash=append_hash,
|
||||||
serialize=False,
|
).to_dict()
|
||||||
)
|
except Exception as e:
|
||||||
)
|
reason = e.body if hasattr(e, "body") else e
|
||||||
except Exception as e:
|
msg = "Failed to replace object: {0}".format(reason)
|
||||||
reason = e.body if hasattr(e, "body") else e
|
raise CoreException(msg) from e
|
||||||
msg = "Failed to replace object: {0}".format(reason)
|
return k8s_obj
|
||||||
raise CoreException(msg) from e
|
|
||||||
|
|
||||||
def update(
|
def update(
|
||||||
self, resource: Resource, definition: Dict, existing: ResourceInstance
|
self, resource: Resource, definition: Dict, existing: ResourceInstance
|
||||||
) -> Tuple[Dict, List[str]]:
|
) -> Dict:
|
||||||
name = definition["metadata"].get("name")
|
name = definition["metadata"].get("name")
|
||||||
namespace = definition["metadata"].get("namespace")
|
namespace = definition["metadata"].get("namespace")
|
||||||
|
|
||||||
if self._client_side_dry_run:
|
if self._client_side_dry_run:
|
||||||
return dict_merge(existing.to_dict(), _encode_stringdata(definition)), []
|
k8s_obj = dict_merge(existing.to_dict(), _encode_stringdata(definition))
|
||||||
|
else:
|
||||||
exception = None
|
exception = None
|
||||||
for merge_type in self.module.params.get("merge_type") or [
|
for merge_type in self.module.params.get("merge_type") or [
|
||||||
"strategic-merge",
|
"strategic-merge",
|
||||||
"merge",
|
"merge",
|
||||||
]:
|
]:
|
||||||
try:
|
try:
|
||||||
return self.patch_resource(
|
k8s_obj = self.patch_resource(
|
||||||
resource,
|
resource,
|
||||||
definition,
|
definition,
|
||||||
name,
|
name,
|
||||||
namespace,
|
namespace,
|
||||||
merge_type=merge_type,
|
merge_type=merge_type,
|
||||||
)
|
)
|
||||||
except CoreException as e:
|
exception = None
|
||||||
exception = e
|
except CoreException as e:
|
||||||
continue
|
exception = e
|
||||||
raise exception
|
continue
|
||||||
|
break
|
||||||
|
if exception:
|
||||||
|
raise exception
|
||||||
|
return k8s_obj
|
||||||
|
|
||||||
def delete(
|
def delete(
|
||||||
self,
|
self,
|
||||||
@@ -473,7 +476,7 @@ class K8sService:
|
|||||||
if label_selectors:
|
if label_selectors:
|
||||||
params["label_selector"] = ",".join(label_selectors)
|
params["label_selector"] = ",".join(label_selectors)
|
||||||
|
|
||||||
if delete_options and not self.module.check_mode:
|
if delete_options:
|
||||||
body = {
|
body = {
|
||||||
"apiVersion": "v1",
|
"apiVersion": "v1",
|
||||||
"kind": "DeleteOptions",
|
"kind": "DeleteOptions",
|
||||||
@@ -498,214 +501,45 @@ def diff_objects(
|
|||||||
if not diff:
|
if not diff:
|
||||||
return True, result
|
return True, result
|
||||||
|
|
||||||
result["before"] = hide_fields(diff[0], hidden_fields)
|
result["before"] = diff[0]
|
||||||
result["after"] = hide_fields(diff[1], hidden_fields)
|
result["after"] = diff[1]
|
||||||
|
|
||||||
if list(result["after"].keys()) == ["metadata"] and list(
|
if list(result["after"].keys()) != ["metadata"] or list(
|
||||||
result["before"].keys()
|
result["before"].keys()
|
||||||
) == ["metadata"]:
|
) != ["metadata"]:
|
||||||
# If only metadata.generation and metadata.resourceVersion changed, ignore it
|
return False, result
|
||||||
ignored_keys = set(["generation", "resourceVersion"])
|
|
||||||
|
|
||||||
if set(result["after"]["metadata"].keys()).issubset(ignored_keys) and set(
|
# If only metadata.generation and metadata.resourceVersion changed, ignore it
|
||||||
result["before"]["metadata"].keys()
|
ignored_keys = set(["generation", "resourceVersion"])
|
||||||
).issubset(ignored_keys):
|
|
||||||
return True, result
|
|
||||||
|
|
||||||
return False, result
|
if not set(result["after"]["metadata"].keys()).issubset(ignored_keys):
|
||||||
|
return False, result
|
||||||
|
if not set(result["before"]["metadata"].keys()).issubset(ignored_keys):
|
||||||
|
return False, result
|
||||||
|
|
||||||
|
result["before"] = hide_fields(result["before"], hidden_fields)
|
||||||
|
result["after"] = hide_fields(result["after"], hidden_fields)
|
||||||
|
|
||||||
|
return True, result
|
||||||
|
|
||||||
|
|
||||||
def hide_field_tree(hidden_field: str) -> List[str]:
|
def hide_fields(definition: dict, hidden_fields: Optional[list]) -> dict:
|
||||||
result = []
|
|
||||||
key, rest = hide_field_split2(hidden_field)
|
|
||||||
result.append(key)
|
|
||||||
while rest:
|
|
||||||
key, rest = hide_field_split2(rest)
|
|
||||||
result.append(key)
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def build_hidden_field_tree(hidden_fields: List[str]) -> Dict[str, Any]:
|
|
||||||
"""Group hidden field targeting the same json key
|
|
||||||
Example:
|
|
||||||
Input: ['env[3]', 'env[0]']
|
|
||||||
Output: {'env': [0, 3]}
|
|
||||||
"""
|
|
||||||
output = {}
|
|
||||||
for hidden_field in hidden_fields:
|
|
||||||
current = output
|
|
||||||
tree = hide_field_tree(hidden_field)
|
|
||||||
for idx, key in enumerate(tree):
|
|
||||||
if current.get(key, "") is None:
|
|
||||||
break
|
|
||||||
if idx == (len(tree) - 1):
|
|
||||||
current[key] = None
|
|
||||||
elif key not in current:
|
|
||||||
current[key] = {}
|
|
||||||
current = current[key]
|
|
||||||
return output
|
|
||||||
|
|
||||||
|
|
||||||
# hide_field should be able to cope with simple or more complicated
|
|
||||||
# field definitions
|
|
||||||
# e.g. status or metadata.managedFields or
|
|
||||||
# spec.template.spec.containers[0].env[3].value or
|
|
||||||
# metadata.annotations[kubectl.kubernetes.io/last-applied-configuration]
|
|
||||||
def hide_field(
|
|
||||||
definition: Union[Dict[str, Any], List[Any]], hidden_field: Dict[str, Any]
|
|
||||||
) -> Dict[str, Any]:
|
|
||||||
def dict_contains_key(obj: Dict[str, Any], key: str) -> bool:
|
|
||||||
return key in obj
|
|
||||||
|
|
||||||
def list_contains_key(obj: List[Any], key: str) -> bool:
|
|
||||||
return int(key) < len(obj)
|
|
||||||
|
|
||||||
hidden_keys = list(hidden_field.keys())
|
|
||||||
field_contains_key = dict_contains_key
|
|
||||||
field_get_key = str
|
|
||||||
if isinstance(definition, list):
|
|
||||||
# Sort with reverse=true so that when we delete an item from the list, the order is not changed
|
|
||||||
hidden_keys = sorted(
|
|
||||||
[k for k in hidden_field.keys() if k.isdecimal()], reverse=True
|
|
||||||
)
|
|
||||||
field_contains_key = list_contains_key
|
|
||||||
field_get_key = int
|
|
||||||
|
|
||||||
for key in hidden_keys:
|
|
||||||
if field_contains_key(definition, key):
|
|
||||||
value = hidden_field.get(key)
|
|
||||||
convert_key = field_get_key(key)
|
|
||||||
if value is None:
|
|
||||||
del definition[convert_key]
|
|
||||||
else:
|
|
||||||
definition[convert_key] = hide_field(definition[convert_key], value)
|
|
||||||
if (
|
|
||||||
definition[convert_key] == dict()
|
|
||||||
or definition[convert_key] == list()
|
|
||||||
):
|
|
||||||
del definition[convert_key]
|
|
||||||
|
|
||||||
return definition
|
|
||||||
|
|
||||||
|
|
||||||
def hide_fields(
|
|
||||||
definition: Dict[str, Any], hidden_fields: Optional[List[str]]
|
|
||||||
) -> Dict[str, Any]:
|
|
||||||
if not hidden_fields:
|
if not hidden_fields:
|
||||||
return definition
|
return definition
|
||||||
result = copy.deepcopy(definition)
|
result = copy.deepcopy(definition)
|
||||||
hidden_field_tree = build_hidden_field_tree(hidden_fields)
|
for hidden_field in hidden_fields:
|
||||||
return hide_field(result, hidden_field_tree)
|
result = hide_field(result, hidden_field)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def decode_response(resp) -> Tuple[Dict, List[str]]:
|
# hide_field is not hugely sophisticated and designed to cope
|
||||||
"""
|
# with e.g. status or metadata.managedFields rather than e.g.
|
||||||
This function decodes unserialized responses from the Kubernetes python
|
# spec.template.spec.containers[0].env[3].value
|
||||||
client and decodes the RFC2616 14.46 warnings found in the response
|
def hide_field(definition: dict, hidden_field: str) -> dict:
|
||||||
headers.
|
|
||||||
"""
|
|
||||||
obj = ResourceInstance(None, loads(resp.data.decode("utf8"))).to_dict()
|
|
||||||
warnings = []
|
|
||||||
if (
|
|
||||||
resp.headers is not None
|
|
||||||
and "warning" in resp.headers
|
|
||||||
and resp.headers["warning"] is not None
|
|
||||||
):
|
|
||||||
warnings = resp.headers["warning"].split(", ")
|
|
||||||
return obj, decode_warnings(warnings)
|
|
||||||
|
|
||||||
|
|
||||||
def decode_warnings(warnings: str) -> List[str]:
|
|
||||||
"""
|
|
||||||
This function decodes RFC2616 14.46 warnings in a simplified way, where
|
|
||||||
only the warn-texts are returned in a list.
|
|
||||||
"""
|
|
||||||
p = compile('\\d{3} .+ (".+")')
|
|
||||||
|
|
||||||
decoded = []
|
|
||||||
for warning in warnings:
|
|
||||||
m = p.match(warning)
|
|
||||||
if m:
|
|
||||||
try:
|
|
||||||
parsed, unused = parse_quoted_string(m.group(1))
|
|
||||||
decoded.append(parsed)
|
|
||||||
except ValueError:
|
|
||||||
continue
|
|
||||||
|
|
||||||
return decoded
|
|
||||||
|
|
||||||
|
|
||||||
def parse_quoted_string(quoted_string: str) -> Tuple[str, str]:
|
|
||||||
"""
|
|
||||||
This function was adapted from:
|
|
||||||
https://github.com/kubernetes/apimachinery/blob/bb8822152cabfb4f34dbc26270f874ce53db50de/pkg/util/net/http.go#L609
|
|
||||||
"""
|
|
||||||
if len(quoted_string) == 0:
|
|
||||||
raise ValueError("invalid quoted string: 0-length")
|
|
||||||
|
|
||||||
if quoted_string[0] != '"':
|
|
||||||
raise ValueError("invalid quoted string: missing initial quote")
|
|
||||||
|
|
||||||
quoted_string = quoted_string[1:]
|
|
||||||
remainder = ""
|
|
||||||
escaping = False
|
|
||||||
closed_quote = False
|
|
||||||
result = []
|
|
||||||
|
|
||||||
for i, b in enumerate(quoted_string):
|
|
||||||
if b == '"':
|
|
||||||
if escaping:
|
|
||||||
result.append(b)
|
|
||||||
escaping = False
|
|
||||||
else:
|
|
||||||
closed_quote = True
|
|
||||||
remainder_start = i + 1
|
|
||||||
remainder = quoted_string[remainder_start:].strip()
|
|
||||||
break
|
|
||||||
elif b == "\\":
|
|
||||||
if escaping:
|
|
||||||
result.append(b)
|
|
||||||
escaping = False
|
|
||||||
else:
|
|
||||||
escaping = True
|
|
||||||
else:
|
|
||||||
result.append(b)
|
|
||||||
escaping = False
|
|
||||||
|
|
||||||
if not closed_quote:
|
|
||||||
raise ValueError("invalid quoted string: missing closing quote")
|
|
||||||
|
|
||||||
return "".join(result), remainder
|
|
||||||
|
|
||||||
|
|
||||||
# hide_field_split2 returns the first key in hidden_field and the rest of the hidden_field
|
|
||||||
# We expect the first key to either be in brackets, to be terminated by the start of a left
|
|
||||||
# bracket, or to be terminated by a dot.
|
|
||||||
|
|
||||||
# examples would be:
|
|
||||||
# field.another.next -> (field, another.next)
|
|
||||||
# field[key].value -> (field, [key].value)
|
|
||||||
# [key].value -> (key, value)
|
|
||||||
# [one][two] -> (one, [two])
|
|
||||||
|
|
||||||
|
|
||||||
def hide_field_split2(hidden_field: str) -> Tuple[str, str]:
|
|
||||||
lbracket = hidden_field.find("[")
|
|
||||||
rbracket = hidden_field.find("]")
|
|
||||||
dot = hidden_field.find(".")
|
|
||||||
|
|
||||||
if lbracket == 0:
|
|
||||||
# skip past right bracket and any following dot
|
|
||||||
rest = hidden_field[rbracket + 1 :] # noqa: E203
|
|
||||||
if rest and rest[0] == ".":
|
|
||||||
rest = rest[1:]
|
|
||||||
return (hidden_field[lbracket + 1 : rbracket], rest) # noqa: E203
|
|
||||||
|
|
||||||
if lbracket != -1 and (dot == -1 or lbracket < dot):
|
|
||||||
return (hidden_field[:lbracket], hidden_field[lbracket:])
|
|
||||||
|
|
||||||
split = hidden_field.split(".", 1)
|
split = hidden_field.split(".", 1)
|
||||||
if len(split) == 1:
|
if split[0] in definition:
|
||||||
return split[0], ""
|
if len(split) == 2:
|
||||||
return split
|
definition[split[0]] = hide_field(definition[split[0]], split[1])
|
||||||
|
else:
|
||||||
|
del definition[split[0]]
|
||||||
|
return definition
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ def daemonset_ready(daemonset: ResourceInstance) -> bool:
|
|||||||
return bool(
|
return bool(
|
||||||
daemonset.status
|
daemonset.status
|
||||||
and daemonset.status.desiredNumberScheduled is not None
|
and daemonset.status.desiredNumberScheduled is not None
|
||||||
and (daemonset.status.updatedNumberScheduled or 0)
|
and daemonset.status.updatedNumberScheduled
|
||||||
== daemonset.status.desiredNumberScheduled
|
== daemonset.status.desiredNumberScheduled
|
||||||
and daemonset.status.numberReady == daemonset.status.desiredNumberScheduled
|
and daemonset.status.numberReady == daemonset.status.desiredNumberScheduled
|
||||||
and daemonset.status.observedGeneration == daemonset.metadata.generation
|
and daemonset.status.observedGeneration == daemonset.metadata.generation
|
||||||
@@ -117,34 +117,11 @@ def exists(resource: Optional[ResourceInstance]) -> bool:
|
|||||||
return bool(resource) and not empty_list(resource)
|
return bool(resource) and not empty_list(resource)
|
||||||
|
|
||||||
|
|
||||||
def cluster_operator_ready(resource: ResourceInstance) -> bool:
|
|
||||||
"""
|
|
||||||
Predicate to check if a single ClusterOperator is healthy.
|
|
||||||
Returns True if:
|
|
||||||
- "Available" is True
|
|
||||||
- "Degraded" is False
|
|
||||||
- "Progressing" is False
|
|
||||||
"""
|
|
||||||
if not resource:
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Extract conditions from the resource's status
|
|
||||||
conditions = resource.get("status", {}).get("conditions", [])
|
|
||||||
|
|
||||||
status = {x.get("type", ""): x.get("status") for x in conditions}
|
|
||||||
return (
|
|
||||||
(status.get("Degraded") == "False")
|
|
||||||
and (status.get("Progressing") == "False")
|
|
||||||
and (status.get("Available") == "True")
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
RESOURCE_PREDICATES = {
|
RESOURCE_PREDICATES = {
|
||||||
"DaemonSet": daemonset_ready,
|
"DaemonSet": daemonset_ready,
|
||||||
"Deployment": deployment_ready,
|
"Deployment": deployment_ready,
|
||||||
"Pod": pod_ready,
|
"Pod": pod_ready,
|
||||||
"StatefulSet": statefulset_ready,
|
"StatefulSet": statefulset_ready,
|
||||||
"ClusterOperator": cluster_operator_ready,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -137,24 +137,14 @@ options:
|
|||||||
- If I(reset_values) is set to C(True), this is ignored.
|
- If I(reset_values) is set to C(True), this is ignored.
|
||||||
type: bool
|
type: bool
|
||||||
required: false
|
required: false
|
||||||
version_added: 3.0.0
|
version_added: 2.5.0
|
||||||
reset_values:
|
reset_values:
|
||||||
description:
|
description:
|
||||||
- When upgrading package, reset the values to the ones built into the chart.
|
- When upgrading package, reset the values to the ones built into the chart.
|
||||||
type: bool
|
type: bool
|
||||||
required: false
|
required: false
|
||||||
default: True
|
default: True
|
||||||
version_added: 3.0.0
|
version_added: 2.5.0
|
||||||
reset_then_reuse_values:
|
|
||||||
description:
|
|
||||||
- When upgrading package, reset the values to the ones built into the chart, apply the last release's values and merge in any overrides from
|
|
||||||
parameters O(release_values), O(values_files) or O(set_values).
|
|
||||||
- If O(reset_values) or O(reuse_values) is set to V(True), this is ignored.
|
|
||||||
- This feature requires helm diff >= 3.9.12.
|
|
||||||
type: bool
|
|
||||||
required: false
|
|
||||||
default: False
|
|
||||||
version_added: 6.0.0
|
|
||||||
|
|
||||||
#Helm options
|
#Helm options
|
||||||
disable_hook:
|
disable_hook:
|
||||||
@@ -228,15 +218,6 @@ options:
|
|||||||
- mutually exclusive with with C(replace).
|
- mutually exclusive with with C(replace).
|
||||||
type: int
|
type: int
|
||||||
version_added: 2.2.0
|
version_added: 2.2.0
|
||||||
insecure_skip_tls_verify:
|
|
||||||
description:
|
|
||||||
- Skip tls certificate checks for the chart download.
|
|
||||||
- Do not confuse with the C(validate_certs) option.
|
|
||||||
- This option is only available for helm >= 3.16.0.
|
|
||||||
type: bool
|
|
||||||
default: False
|
|
||||||
aliases: [ skip_tls_certs_check ]
|
|
||||||
version_added: 5.3.0
|
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- kubernetes.core.helm_common_options
|
- kubernetes.core.helm_common_options
|
||||||
"""
|
"""
|
||||||
@@ -392,18 +373,9 @@ status:
|
|||||||
returned: always
|
returned: always
|
||||||
description: The Date of last update
|
description: The Date of last update
|
||||||
values:
|
values:
|
||||||
type: dict
|
type: str
|
||||||
returned: always
|
returned: always
|
||||||
description:
|
description: Dict of Values used to deploy
|
||||||
- Dict of Values used to deploy.
|
|
||||||
- This return value has been deprecated and will be removed in a release after
|
|
||||||
2027-01-08. Use RV(status.release_values) instead.
|
|
||||||
release_values:
|
|
||||||
type: dict
|
|
||||||
returned: always
|
|
||||||
description:
|
|
||||||
- Dict of Values used to deploy.
|
|
||||||
version_added: 6.3.0
|
|
||||||
stdout:
|
stdout:
|
||||||
type: str
|
type: str
|
||||||
description: Full `helm` command stdout, in case you want to display it or examine the event log
|
description: Full `helm` command stdout, in case you want to display it or examine the event log
|
||||||
@@ -483,8 +455,7 @@ def get_release_status(module, release_name, all_status=False):
|
|||||||
if release is None: # not install
|
if release is None: # not install
|
||||||
return None
|
return None
|
||||||
|
|
||||||
release["release_values"] = module.get_values(release_name)
|
release["values"] = module.get_values(release_name)
|
||||||
release["values"] = release["release_values"]
|
|
||||||
|
|
||||||
return release
|
return release
|
||||||
|
|
||||||
@@ -505,15 +476,12 @@ def run_dep_update(module, chart_ref):
|
|||||||
rc, out, err = module.run_helm_command(dep_update)
|
rc, out, err = module.run_helm_command(dep_update)
|
||||||
|
|
||||||
|
|
||||||
def fetch_chart_info(module, command, chart_ref, insecure_skip_tls_verify=False):
|
def fetch_chart_info(module, command, chart_ref):
|
||||||
"""
|
"""
|
||||||
Get chart info
|
Get chart info
|
||||||
"""
|
"""
|
||||||
inspect_command = command + f" show chart '{chart_ref}'"
|
inspect_command = command + f" show chart '{chart_ref}'"
|
||||||
|
|
||||||
if insecure_skip_tls_verify:
|
|
||||||
inspect_command += " --insecure-skip-tls-verify"
|
|
||||||
|
|
||||||
rc, out, err = module.run_helm_command(inspect_command)
|
rc, out, err = module.run_helm_command(inspect_command)
|
||||||
|
|
||||||
return yaml.safe_load(out)
|
return yaml.safe_load(out)
|
||||||
@@ -541,8 +509,6 @@ def deploy(
|
|||||||
set_value_args=None,
|
set_value_args=None,
|
||||||
reuse_values=None,
|
reuse_values=None,
|
||||||
reset_values=True,
|
reset_values=True,
|
||||||
reset_then_reuse_values=False,
|
|
||||||
insecure_skip_tls_verify=False,
|
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Install/upgrade/rollback release chart
|
Install/upgrade/rollback release chart
|
||||||
@@ -560,17 +526,6 @@ def deploy(
|
|||||||
if reuse_values is not None:
|
if reuse_values is not None:
|
||||||
deploy_command += " --reuse-values=" + str(reuse_values)
|
deploy_command += " --reuse-values=" + str(reuse_values)
|
||||||
|
|
||||||
if reset_then_reuse_values:
|
|
||||||
helm_version = module.get_helm_version()
|
|
||||||
if LooseVersion(helm_version) < LooseVersion("3.14.0"):
|
|
||||||
module.fail_json(
|
|
||||||
msg="reset_then_reuse_values requires helm >= 3.14.0, current version is {0}".format(
|
|
||||||
helm_version
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
deploy_command += " --reset-then-reuse-values"
|
|
||||||
|
|
||||||
if wait:
|
if wait:
|
||||||
deploy_command += " --wait"
|
deploy_command += " --wait"
|
||||||
if wait_timeout is not None:
|
if wait_timeout is not None:
|
||||||
@@ -594,17 +549,6 @@ def deploy(
|
|||||||
if create_namespace:
|
if create_namespace:
|
||||||
deploy_command += " --create-namespace"
|
deploy_command += " --create-namespace"
|
||||||
|
|
||||||
if insecure_skip_tls_verify:
|
|
||||||
helm_version = module.get_helm_version()
|
|
||||||
if LooseVersion(helm_version) < LooseVersion("3.16.0"):
|
|
||||||
module.fail_json(
|
|
||||||
msg="insecure_skip_tls_verify requires helm >= 3.16.0, current version is {0}".format(
|
|
||||||
helm_version
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
deploy_command += " --insecure-skip-tls-verify"
|
|
||||||
|
|
||||||
if values_files:
|
if values_files:
|
||||||
for value_file in values_files:
|
for value_file in values_files:
|
||||||
deploy_command += " --values=" + value_file
|
deploy_command += " --values=" + value_file
|
||||||
@@ -698,8 +642,6 @@ def helmdiff_check(
|
|||||||
set_value_args=None,
|
set_value_args=None,
|
||||||
reuse_values=None,
|
reuse_values=None,
|
||||||
reset_values=True,
|
reset_values=True,
|
||||||
reset_then_reuse_values=False,
|
|
||||||
insecure_skip_tls_verify=False,
|
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Use helm diff to determine if a release would change by upgrading a chart.
|
Use helm diff to determine if a release would change by upgrading a chart.
|
||||||
@@ -734,27 +676,6 @@ def helmdiff_check(
|
|||||||
if reuse_values:
|
if reuse_values:
|
||||||
cmd += " --reuse-values"
|
cmd += " --reuse-values"
|
||||||
|
|
||||||
if reset_then_reuse_values:
|
|
||||||
helm_diff_version = get_plugin_version("diff")
|
|
||||||
helm_version = module.get_helm_version()
|
|
||||||
fail_msg = ""
|
|
||||||
if LooseVersion(helm_diff_version) < LooseVersion("3.9.12"):
|
|
||||||
fail_msg = "reset_then_reuse_values requires helm diff >= 3.9.12, current version is {0}\n".format(
|
|
||||||
helm_diff_version
|
|
||||||
)
|
|
||||||
if LooseVersion(helm_version) < LooseVersion("3.14.0"):
|
|
||||||
fail_msg += "reset_then_reuse_values requires helm >= 3.14.0, current version is {0}\n".format(
|
|
||||||
helm_version
|
|
||||||
)
|
|
||||||
|
|
||||||
if fail_msg:
|
|
||||||
module.fail_json(msg=fail_msg)
|
|
||||||
else:
|
|
||||||
cmd += " --reset-then-reuse-values"
|
|
||||||
|
|
||||||
if insecure_skip_tls_verify:
|
|
||||||
cmd += " --insecure-skip-tls-verify"
|
|
||||||
|
|
||||||
rc, out, err = module.run_helm_command(cmd)
|
rc, out, err = module.run_helm_command(cmd)
|
||||||
return (len(out.strip()) > 0, out.strip())
|
return (len(out.strip()) > 0, out.strip())
|
||||||
|
|
||||||
@@ -814,10 +735,6 @@ def argument_spec():
|
|||||||
set_values=dict(type="list", elements="dict"),
|
set_values=dict(type="list", elements="dict"),
|
||||||
reuse_values=dict(type="bool"),
|
reuse_values=dict(type="bool"),
|
||||||
reset_values=dict(type="bool", default=True),
|
reset_values=dict(type="bool", default=True),
|
||||||
reset_then_reuse_values=dict(type="bool", default=False),
|
|
||||||
insecure_skip_tls_verify=dict(
|
|
||||||
type="bool", default=False, aliases=["skip_tls_certs_check"]
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return arg_spec
|
return arg_spec
|
||||||
@@ -842,9 +759,6 @@ 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,<4.0.0
|
|
||||||
module.validate_helm_version()
|
|
||||||
|
|
||||||
changed = False
|
changed = False
|
||||||
|
|
||||||
chart_ref = module.params.get("chart_ref")
|
chart_ref = module.params.get("chart_ref")
|
||||||
@@ -873,8 +787,6 @@ def main():
|
|||||||
set_values = module.params.get("set_values")
|
set_values = module.params.get("set_values")
|
||||||
reuse_values = module.params.get("reuse_values")
|
reuse_values = module.params.get("reuse_values")
|
||||||
reset_values = module.params.get("reset_values")
|
reset_values = module.params.get("reset_values")
|
||||||
reset_then_reuse_values = module.params.get("reset_then_reuse_values")
|
|
||||||
insecure_skip_tls_verify = module.params.get("insecure_skip_tls_verify")
|
|
||||||
|
|
||||||
if update_repo_cache:
|
if update_repo_cache:
|
||||||
run_repo_update(module)
|
run_repo_update(module)
|
||||||
@@ -912,9 +824,7 @@ def main():
|
|||||||
helm_cmd += " --repo=" + chart_repo_url
|
helm_cmd += " --repo=" + chart_repo_url
|
||||||
|
|
||||||
# Fetch chart info to have real version and real name for chart_ref from archive, folder or url
|
# Fetch chart info to have real version and real name for chart_ref from archive, folder or url
|
||||||
chart_info = fetch_chart_info(
|
chart_info = fetch_chart_info(module, helm_cmd, chart_ref)
|
||||||
module, helm_cmd, chart_ref, insecure_skip_tls_verify
|
|
||||||
)
|
|
||||||
|
|
||||||
if dependency_update:
|
if dependency_update:
|
||||||
if chart_info.get("dependencies"):
|
if chart_info.get("dependencies"):
|
||||||
@@ -973,8 +883,6 @@ def main():
|
|||||||
set_value_args=set_value_args,
|
set_value_args=set_value_args,
|
||||||
reuse_values=reuse_values,
|
reuse_values=reuse_values,
|
||||||
reset_values=reset_values,
|
reset_values=reset_values,
|
||||||
reset_then_reuse_values=reset_then_reuse_values,
|
|
||||||
insecure_skip_tls_verify=insecure_skip_tls_verify,
|
|
||||||
)
|
)
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
@@ -1000,8 +908,6 @@ def main():
|
|||||||
set_value_args,
|
set_value_args,
|
||||||
reuse_values=reuse_values,
|
reuse_values=reuse_values,
|
||||||
reset_values=reset_values,
|
reset_values=reset_values,
|
||||||
reset_then_reuse_values=reset_then_reuse_values,
|
|
||||||
insecure_skip_tls_verify=insecure_skip_tls_verify,
|
|
||||||
)
|
)
|
||||||
if would_change and module._diff:
|
if would_change and module._diff:
|
||||||
opt_result["diff"] = {"prepared": prepared}
|
opt_result["diff"] = {"prepared": prepared}
|
||||||
@@ -1037,21 +943,14 @@ def main():
|
|||||||
set_value_args=set_value_args,
|
set_value_args=set_value_args,
|
||||||
reuse_values=reuse_values,
|
reuse_values=reuse_values,
|
||||||
reset_values=reset_values,
|
reset_values=reset_values,
|
||||||
reset_then_reuse_values=reset_then_reuse_values,
|
|
||||||
insecure_skip_tls_verify=insecure_skip_tls_verify,
|
|
||||||
)
|
)
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
if module.check_mode:
|
if module.check_mode:
|
||||||
check_status = {
|
check_status = {"values": {"current": {}, "declared": {}}}
|
||||||
"values": {"current": {}, "declared": {}},
|
|
||||||
"release_values": {"current": {}, "declared": {}},
|
|
||||||
}
|
|
||||||
if release_status:
|
if release_status:
|
||||||
check_status["values"]["current"] = release_status["release_values"]
|
check_status["values"]["current"] = release_status["values"]
|
||||||
check_status["values"]["declared"] = release_status
|
check_status["values"]["declared"] = release_status
|
||||||
check_status["release_values"]["current"] = release_status["release_values"]
|
|
||||||
check_status["release_values"]["declared"] = release_status
|
|
||||||
|
|
||||||
module.exit_json(
|
module.exit_json(
|
||||||
changed=changed,
|
changed=changed,
|
||||||
|
|||||||
@@ -115,18 +115,9 @@ status:
|
|||||||
returned: always
|
returned: always
|
||||||
description: The Date of last update
|
description: The Date of last update
|
||||||
values:
|
values:
|
||||||
type: dict
|
type: str
|
||||||
returned: always
|
returned: always
|
||||||
description:
|
description: Dict of Values used to deploy
|
||||||
- Dict of Values used to deploy
|
|
||||||
- This return value has been deprecated and will be removed in a release after
|
|
||||||
2027-01-08. Use RV(status.release_values) instead.
|
|
||||||
release_values:
|
|
||||||
type: dict
|
|
||||||
returned: always
|
|
||||||
description:
|
|
||||||
- Dict of Values used to deploy.
|
|
||||||
version_added: 6.3.0
|
|
||||||
hooks:
|
hooks:
|
||||||
type: list
|
type: list
|
||||||
elements: dict
|
elements: dict
|
||||||
@@ -211,8 +202,7 @@ def get_release_status(module, release_name, release_state, get_all_values=False
|
|||||||
if release is None: # not install
|
if release is None: # not install
|
||||||
return None
|
return None
|
||||||
|
|
||||||
release["release_values"] = module.get_values(release_name, get_all_values)
|
release["values"] = module.get_values(release_name, get_all_values)
|
||||||
release["values"] = release["release_values"]
|
|
||||||
release["manifest"] = module.get_manifest(release_name)
|
release["manifest"] = module.get_manifest(release_name)
|
||||||
release["notes"] = module.get_notes(release_name)
|
release["notes"] = module.get_notes(release_name)
|
||||||
release["hooks"] = module.get_hooks(release_name)
|
release["hooks"] = module.get_hooks(release_name)
|
||||||
@@ -245,9 +235,6 @@ 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,<4.0.0
|
|
||||||
module.validate_helm_version()
|
|
||||||
|
|
||||||
release_name = module.params.get("release_name")
|
release_name = module.params.get("release_name")
|
||||||
release_state = module.params.get("release_state")
|
release_state = module.params.get("release_state")
|
||||||
get_all_values = module.params.get("get_all_values")
|
get_all_values = module.params.get("get_all_values")
|
||||||
|
|||||||
@@ -161,9 +161,6 @@ def main():
|
|||||||
mutually_exclusive=mutually_exclusive(),
|
mutually_exclusive=mutually_exclusive(),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Validate Helm version >=3.0.0,<4.0.0
|
|
||||||
module.validate_helm_version()
|
|
||||||
|
|
||||||
state = module.params.get("state")
|
state = module.params.get("state")
|
||||||
|
|
||||||
helm_cmd_common = module.get_helm_binary() + " plugin"
|
helm_cmd_common = module.get_helm_binary() + " plugin"
|
||||||
|
|||||||
@@ -98,9 +98,6 @@ def main():
|
|||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Validate Helm version >=3.0.0,<4.0.0
|
|
||||||
module.validate_helm_version()
|
|
||||||
|
|
||||||
plugin_name = module.params.get("plugin_name")
|
plugin_name = module.params.get("plugin_name")
|
||||||
|
|
||||||
plugin_list = []
|
plugin_list = []
|
||||||
|
|||||||
@@ -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, <4.0.0 (https://github.com/helm/helm/releases)"
|
- "helm >= 3.0 (https://github.com/helm/helm/releases)"
|
||||||
|
|
||||||
options:
|
options:
|
||||||
chart_ref:
|
chart_ref:
|
||||||
@@ -75,10 +75,9 @@ options:
|
|||||||
skip_tls_certs_check:
|
skip_tls_certs_check:
|
||||||
description:
|
description:
|
||||||
- Whether or not to check tls certificate for the chart download.
|
- Whether or not to check tls certificate for the chart download.
|
||||||
- Requires helm >= 3.3.0. Alias C(insecure_skip_tls_verify) added in 5.3.0.
|
- Requires helm >= 3.3.0.
|
||||||
type: bool
|
type: bool
|
||||||
default: False
|
default: False
|
||||||
aliases: [ insecure_skip_tls_verify ]
|
|
||||||
chart_devel:
|
chart_devel:
|
||||||
description:
|
description:
|
||||||
- Use development versions, too. Equivalent to version '>0.0.0-0'.
|
- Use development versions, too. Equivalent to version '>0.0.0-0'.
|
||||||
@@ -89,14 +88,6 @@ options:
|
|||||||
- if set to true, will untar the chart after downloading it.
|
- if set to true, will untar the chart after downloading it.
|
||||||
type: bool
|
type: bool
|
||||||
default: False
|
default: False
|
||||||
force:
|
|
||||||
description:
|
|
||||||
- Force download of the chart even if it already exists in the destination directory.
|
|
||||||
- By default, the module will skip downloading if the chart with the same version already exists for idempotency.
|
|
||||||
- When used with O(untar_chart=true), will remove any existing chart directory before extracting.
|
|
||||||
type: bool
|
|
||||||
default: False
|
|
||||||
version_added: 6.3.0
|
|
||||||
destination:
|
destination:
|
||||||
description:
|
description:
|
||||||
- location to write the chart.
|
- location to write the chart.
|
||||||
@@ -153,23 +144,6 @@ EXAMPLES = r"""
|
|||||||
destination: /path/to/chart
|
destination: /path/to/chart
|
||||||
username: myuser
|
username: myuser
|
||||||
password: mypassword123
|
password: mypassword123
|
||||||
|
|
||||||
- name: Download Chart (force re-download even if exists)
|
|
||||||
kubernetes.core.helm_pull:
|
|
||||||
chart_ref: redis
|
|
||||||
repo_url: https://charts.bitnami.com/bitnami
|
|
||||||
chart_version: '17.0.0'
|
|
||||||
destination: /path/to/chart
|
|
||||||
force: yes
|
|
||||||
|
|
||||||
- name: Download and untar chart (force re-extraction even if directory exists)
|
|
||||||
kubernetes.core.helm_pull:
|
|
||||||
chart_ref: redis
|
|
||||||
repo_url: https://charts.bitnami.com/bitnami
|
|
||||||
chart_version: '17.0.0'
|
|
||||||
destination: /path/to/chart
|
|
||||||
untar_chart: yes
|
|
||||||
force: yes
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
RETURN = r"""
|
RETURN = r"""
|
||||||
@@ -188,11 +162,6 @@ command:
|
|||||||
description: Full `helm pull` command built by this module, in case you want to re-run the command outside the module or debug a problem.
|
description: Full `helm pull` command built by this module, in case you want to re-run the command outside the module or debug a problem.
|
||||||
returned: always
|
returned: always
|
||||||
sample: helm pull --repo test ...
|
sample: helm pull --repo test ...
|
||||||
msg:
|
|
||||||
type: str
|
|
||||||
description: A message indicating the result of the operation.
|
|
||||||
returned: when chart already exists
|
|
||||||
sample: Chart redis version 17.0.0 already exists in destination directory
|
|
||||||
rc:
|
rc:
|
||||||
type: int
|
type: int
|
||||||
description: Helm pull command return code
|
description: Helm pull command return code
|
||||||
@@ -200,18 +169,6 @@ rc:
|
|||||||
sample: 1
|
sample: 1
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
import tarfile
|
|
||||||
import uuid
|
|
||||||
|
|
||||||
try:
|
|
||||||
import yaml
|
|
||||||
|
|
||||||
HAS_YAML = True
|
|
||||||
except ImportError:
|
|
||||||
HAS_YAML = False
|
|
||||||
|
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.helm import (
|
from ansible_collections.kubernetes.core.plugins.module_utils.helm import (
|
||||||
AnsibleHelmModule,
|
AnsibleHelmModule,
|
||||||
)
|
)
|
||||||
@@ -220,115 +177,6 @@ from ansible_collections.kubernetes.core.plugins.module_utils.version import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def extract_chart_name(chart_ref):
|
|
||||||
"""
|
|
||||||
Extract chart name from chart reference.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
chart_ref (str): Chart reference (name, URL, or OCI reference)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: Extracted chart name
|
|
||||||
"""
|
|
||||||
chart_name = chart_ref.split("/")[-1]
|
|
||||||
# Remove any query parameters or fragments from URL-based refs
|
|
||||||
if "?" in chart_name:
|
|
||||||
chart_name = chart_name.split("?")[0]
|
|
||||||
if "#" in chart_name:
|
|
||||||
chart_name = chart_name.split("#")[0]
|
|
||||||
# Remove .tgz extension if present
|
|
||||||
if chart_name.endswith(".tgz"):
|
|
||||||
chart_name = chart_name[:-4]
|
|
||||||
return chart_name
|
|
||||||
|
|
||||||
|
|
||||||
def chart_exists(destination, chart_ref, chart_version, untar_chart):
|
|
||||||
"""
|
|
||||||
Check if the chart already exists in the destination directory.
|
|
||||||
|
|
||||||
For untarred charts: check if directory exists with Chart.yaml matching version
|
|
||||||
For tarred charts: check if .tgz file exists and contains matching version
|
|
||||||
|
|
||||||
Args:
|
|
||||||
destination (str): Destination directory path
|
|
||||||
chart_ref (str): Chart reference (name or URL)
|
|
||||||
chart_version (str): Chart version to check for
|
|
||||||
untar_chart (bool): Whether to check for untarred or tarred chart
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True if chart with matching version exists, False otherwise
|
|
||||||
"""
|
|
||||||
# YAML is required for version checking
|
|
||||||
if not HAS_YAML:
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Without version, we can't reliably check
|
|
||||||
if not chart_version:
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Extract chart name from chart_ref using shared helper
|
|
||||||
chart_name = extract_chart_name(chart_ref)
|
|
||||||
|
|
||||||
if untar_chart:
|
|
||||||
# Check for extracted directory
|
|
||||||
chart_dir = os.path.join(destination, chart_name)
|
|
||||||
chart_yaml_path = os.path.join(chart_dir, "Chart.yaml")
|
|
||||||
|
|
||||||
if os.path.isdir(chart_dir) and os.path.isfile(chart_yaml_path):
|
|
||||||
try:
|
|
||||||
with open(chart_yaml_path, "r", encoding="utf-8") as chart_file:
|
|
||||||
chart_metadata = yaml.safe_load(chart_file)
|
|
||||||
# Ensure chart_metadata is a dict and has a version that matches
|
|
||||||
if (
|
|
||||||
chart_metadata
|
|
||||||
and isinstance(chart_metadata, dict)
|
|
||||||
and chart_metadata.get("version") == chart_version
|
|
||||||
and chart_metadata.get("name") == chart_name
|
|
||||||
):
|
|
||||||
return True
|
|
||||||
except (yaml.YAMLError, IOError, OSError, TypeError):
|
|
||||||
# If we can't read or parse the file, treat as non-existent
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
# Check for .tgz file
|
|
||||||
chart_file = os.path.join(destination, f"{chart_name}-{chart_version}.tgz")
|
|
||||||
|
|
||||||
if os.path.isfile(chart_file):
|
|
||||||
try:
|
|
||||||
# Verify it's a valid tarball with matching version
|
|
||||||
with tarfile.open(chart_file, "r:gz") as tar:
|
|
||||||
# Try to extract Chart.yaml to verify version
|
|
||||||
# Look for Chart.yaml at the expected path: <chart-name>/Chart.yaml
|
|
||||||
expected_chart_yaml = f"{chart_name}/Chart.yaml"
|
|
||||||
try:
|
|
||||||
member = tar.getmember(expected_chart_yaml)
|
|
||||||
chart_yaml_file = tar.extractfile(member)
|
|
||||||
if chart_yaml_file:
|
|
||||||
try:
|
|
||||||
chart_metadata = yaml.safe_load(chart_yaml_file)
|
|
||||||
# Ensure chart_metadata is a dict and has a version that matches
|
|
||||||
if (
|
|
||||||
chart_metadata
|
|
||||||
and isinstance(chart_metadata, dict)
|
|
||||||
and chart_metadata.get("version") == chart_version
|
|
||||||
and chart_metadata.get("name") == chart_name
|
|
||||||
):
|
|
||||||
return True
|
|
||||||
except (yaml.YAMLError, TypeError):
|
|
||||||
# If we can't parse the YAML, treat as non-existent
|
|
||||||
pass
|
|
||||||
finally:
|
|
||||||
chart_yaml_file.close()
|
|
||||||
except KeyError:
|
|
||||||
# Chart.yaml not found at expected path
|
|
||||||
pass
|
|
||||||
except (tarfile.TarError, yaml.YAMLError, IOError, OSError, TypeError):
|
|
||||||
# If we can't read or parse the tarball, treat as non-existent
|
|
||||||
pass
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
argspec = dict(
|
argspec = dict(
|
||||||
chart_ref=dict(type="str", required=True),
|
chart_ref=dict(type="str", required=True),
|
||||||
@@ -341,13 +189,10 @@ def main():
|
|||||||
repo_password=dict(
|
repo_password=dict(
|
||||||
type="str", no_log=True, aliases=["password", "chart_repo_password"]
|
type="str", no_log=True, aliases=["password", "chart_repo_password"]
|
||||||
),
|
),
|
||||||
pass_credentials=dict(type="bool", default=False, no_log=False),
|
pass_credentials=dict(type="bool", default=False),
|
||||||
skip_tls_certs_check=dict(
|
skip_tls_certs_check=dict(type="bool", default=False),
|
||||||
type="bool", default=False, aliases=["insecure_skip_tls_verify"]
|
|
||||||
),
|
|
||||||
chart_devel=dict(type="bool"),
|
chart_devel=dict(type="bool"),
|
||||||
untar_chart=dict(type="bool", default=False),
|
untar_chart=dict(type="bool", default=False),
|
||||||
force=dict(type="bool", default=False),
|
|
||||||
destination=dict(type="path", required=True),
|
destination=dict(type="path", required=True),
|
||||||
chart_ca_cert=dict(type="path"),
|
chart_ca_cert=dict(type="path"),
|
||||||
chart_ssl_cert_file=dict(type="path"),
|
chart_ssl_cert_file=dict(type="path"),
|
||||||
@@ -364,10 +209,13 @@ def main():
|
|||||||
mutually_exclusive=[("chart_version", "chart_devel")],
|
mutually_exclusive=[("chart_version", "chart_devel")],
|
||||||
)
|
)
|
||||||
|
|
||||||
# Validate Helm version >=3.0.0,<4.0.0
|
|
||||||
module.validate_helm_version()
|
|
||||||
|
|
||||||
helm_version = module.get_helm_version()
|
helm_version = module.get_helm_version()
|
||||||
|
if LooseVersion(helm_version) < LooseVersion("3.0.0"):
|
||||||
|
module.fail_json(
|
||||||
|
msg="This module requires helm >= 3.0.0, current version is {0}".format(
|
||||||
|
helm_version
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
helm_pull_opt_versionning = dict(
|
helm_pull_opt_versionning = dict(
|
||||||
skip_tls_certs_check="3.3.0",
|
skip_tls_certs_check="3.3.0",
|
||||||
@@ -425,72 +273,8 @@ def main():
|
|||||||
module.params.get("chart_ref"),
|
module.params.get("chart_ref"),
|
||||||
" ".join(helm_pull_opts),
|
" ".join(helm_pull_opts),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check if chart already exists (idempotency)
|
|
||||||
if module.params.get("chart_version") and not module.params.get("force"):
|
|
||||||
chart_exists_locally = chart_exists(
|
|
||||||
module.params.get("destination"),
|
|
||||||
module.params.get("chart_ref"),
|
|
||||||
module.params.get("chart_version"),
|
|
||||||
module.params.get("untar_chart"),
|
|
||||||
)
|
|
||||||
|
|
||||||
if chart_exists_locally:
|
|
||||||
module.exit_json(
|
|
||||||
failed=False,
|
|
||||||
changed=False,
|
|
||||||
msg="Chart {0} version {1} already exists in destination directory".format(
|
|
||||||
module.params.get("chart_ref"), module.params.get("chart_version")
|
|
||||||
),
|
|
||||||
command="",
|
|
||||||
stdout="",
|
|
||||||
stderr="",
|
|
||||||
rc=0,
|
|
||||||
)
|
|
||||||
|
|
||||||
# When both untar_chart and force are enabled, we need to remove the existing chart directory
|
|
||||||
# BEFORE running helm pull to prevent helm's "directory already exists" error.
|
|
||||||
# We do this by:
|
|
||||||
# 1. Renaming the existing directory to a temporary name (if it exists)
|
|
||||||
# 2. Running helm pull
|
|
||||||
# 3. On success: remove the temporary directory
|
|
||||||
# 4. On failure: restore the temporary directory and report the error
|
|
||||||
chart_dir_renamed = False
|
|
||||||
chart_dir = None
|
|
||||||
chart_dir_backup = None
|
|
||||||
|
|
||||||
if module.params.get("untar_chart") and module.params.get("force"):
|
|
||||||
chart_name = extract_chart_name(module.params.get("chart_ref"))
|
|
||||||
chart_dir = os.path.join(module.params.get("destination"), chart_name)
|
|
||||||
|
|
||||||
# Check if directory exists and contains a Chart.yaml (to be safe)
|
|
||||||
if os.path.isdir(chart_dir):
|
|
||||||
chart_yaml_path = os.path.join(chart_dir, "Chart.yaml")
|
|
||||||
# Only rename if it looks like a Helm chart directory (have Chart.yaml)
|
|
||||||
if os.path.isfile(chart_yaml_path):
|
|
||||||
if not module.check_mode:
|
|
||||||
# Rename to temporary backup name using uuid for uniqueness
|
|
||||||
backup_suffix = uuid.uuid4().hex[:8]
|
|
||||||
chart_dir_backup = os.path.join(
|
|
||||||
module.params.get("destination"),
|
|
||||||
f".{chart_name}_backup_{backup_suffix}",
|
|
||||||
)
|
|
||||||
os.rename(chart_dir, chart_dir_backup)
|
|
||||||
chart_dir_renamed = True
|
|
||||||
|
|
||||||
if not module.check_mode:
|
if not module.check_mode:
|
||||||
rc, out, err = module.run_helm_command(helm_cmd_common, fails_on_error=False)
|
rc, out, err = module.run_helm_command(helm_cmd_common, fails_on_error=False)
|
||||||
|
|
||||||
# Handle cleanup/restore based on helm command result
|
|
||||||
if chart_dir_renamed:
|
|
||||||
if rc == 0:
|
|
||||||
# Success: remove the backup directory
|
|
||||||
if os.path.isdir(chart_dir_backup):
|
|
||||||
shutil.rmtree(chart_dir_backup)
|
|
||||||
else:
|
|
||||||
# Failure: restore the backup directory
|
|
||||||
if os.path.isdir(chart_dir_backup) and not os.path.exists(chart_dir):
|
|
||||||
os.rename(chart_dir_backup, chart_dir)
|
|
||||||
else:
|
else:
|
||||||
rc, out, err = (0, "", "")
|
rc, out, err = (0, "", "")
|
||||||
|
|
||||||
|
|||||||
@@ -1,252 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Copyright: © Ericsson AB 2024
|
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
||||||
from __future__ import absolute_import, division, print_function
|
|
||||||
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
|
|
||||||
DOCUMENTATION = r"""
|
|
||||||
---
|
|
||||||
module: helm_registry_auth
|
|
||||||
|
|
||||||
short_description: Helm registry authentication module
|
|
||||||
|
|
||||||
version_added: 5.1.0
|
|
||||||
|
|
||||||
author:
|
|
||||||
- Yuriy Novostavskiy (@yurnov)
|
|
||||||
|
|
||||||
requirements:
|
|
||||||
- "helm (https://github.com/helm/helm/releases) >= 3.8.0, <4.0.0"
|
|
||||||
|
|
||||||
description:
|
|
||||||
- Helm registry authentication module allows you to login C(helm registry login) and logout C(helm registry logout) from a Helm registry.
|
|
||||||
|
|
||||||
options:
|
|
||||||
state:
|
|
||||||
description:
|
|
||||||
- Desired state of the registry.
|
|
||||||
- If set to V(present) attempt to log in to the remote registry server using the URL specified in O(host).
|
|
||||||
- If set to V(absent) attempt to log out from the remote registry server using the URL specified in O(host).
|
|
||||||
- As helm >= 3.18.0 reports successful logout even if the user is not logged in, this module will report a change regardless of the current state.
|
|
||||||
required: false
|
|
||||||
default: present
|
|
||||||
choices: ['present', 'absent']
|
|
||||||
type: str
|
|
||||||
host:
|
|
||||||
description:
|
|
||||||
- Provide a URL for accessing the registry.
|
|
||||||
required: true
|
|
||||||
aliases: [ registry_url ]
|
|
||||||
type: str
|
|
||||||
insecure:
|
|
||||||
description:
|
|
||||||
- Allow connections to SSL sites without certs.
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
type: bool
|
|
||||||
username:
|
|
||||||
description:
|
|
||||||
- Username for the registry.
|
|
||||||
required: false
|
|
||||||
type: str
|
|
||||||
aliases: [ repo_username ]
|
|
||||||
password:
|
|
||||||
description:
|
|
||||||
- Password for the registry.
|
|
||||||
required: false
|
|
||||||
type: str
|
|
||||||
aliases: [ repo_password ]
|
|
||||||
key_file:
|
|
||||||
description:
|
|
||||||
- Path to the client key SSL file for identify registry client using this key file.
|
|
||||||
required: false
|
|
||||||
type: path
|
|
||||||
cert_file:
|
|
||||||
description:
|
|
||||||
- Path to the client certificate SSL file for identify registry client using this certificate file.
|
|
||||||
required: false
|
|
||||||
type: path
|
|
||||||
ca_file:
|
|
||||||
description:
|
|
||||||
- Path to the CA certificate SSL file for verify registry server certificate.
|
|
||||||
required: false
|
|
||||||
type: path
|
|
||||||
binary_path:
|
|
||||||
description:
|
|
||||||
- The path of a helm binary to use.
|
|
||||||
required: false
|
|
||||||
type: path
|
|
||||||
"""
|
|
||||||
|
|
||||||
EXAMPLES = r"""
|
|
||||||
- name: Login to remote registry
|
|
||||||
kubernetes.core.helm_registry_auth:
|
|
||||||
username: admin
|
|
||||||
password: "sample_password"
|
|
||||||
host: localhost:5000
|
|
||||||
|
|
||||||
- name: Logout from remote registry
|
|
||||||
kubernetes.core.helm_registry_auth:
|
|
||||||
state: absent
|
|
||||||
host: localhost:5000
|
|
||||||
"""
|
|
||||||
|
|
||||||
RETURN = r"""
|
|
||||||
stdout:
|
|
||||||
type: str
|
|
||||||
description: Full C(helm) command stdout, in case you want to display it or examine the event log
|
|
||||||
returned: always
|
|
||||||
stout_lines:
|
|
||||||
type: list
|
|
||||||
description: Full C(helm) command stdout, in case you want to display it or examine the event log
|
|
||||||
returned: always
|
|
||||||
stderr:
|
|
||||||
type: str
|
|
||||||
description: >-
|
|
||||||
Full C(helm) command stderr, in case you want to display it or examine the event log.
|
|
||||||
Please be note that helm binnary may print messages to stderr even if the command is successful.
|
|
||||||
returned: always
|
|
||||||
sample: 'Login Succeeded\n'
|
|
||||||
stderr_lines:
|
|
||||||
type: list
|
|
||||||
description: Full C(helm) command stderr, in case you want to display it or examine the event log
|
|
||||||
returned: always
|
|
||||||
command:
|
|
||||||
type: str
|
|
||||||
description: Full C(helm) command executed
|
|
||||||
returned: always
|
|
||||||
sample: '/usr/local/bin/helm registry login oci-registry.domain.example --username=admin --password-stdin --insecure'
|
|
||||||
failed:
|
|
||||||
type: bool
|
|
||||||
description: Indicate if the C(helm) command failed
|
|
||||||
returned: always
|
|
||||||
sample: false
|
|
||||||
"""
|
|
||||||
|
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.helm import (
|
|
||||||
AnsibleHelmModule,
|
|
||||||
)
|
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
|
|
||||||
LooseVersion,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def arg_spec():
|
|
||||||
return dict(
|
|
||||||
binary_path=dict(type="path", required=False),
|
|
||||||
host=dict(type="str", aliases=["registry_url"], required=True),
|
|
||||||
state=dict(default="present", choices=["present", "absent"], required=False),
|
|
||||||
insecure=dict(type="bool", default=False, required=False),
|
|
||||||
username=dict(type="str", aliases=["repo_username"], required=False),
|
|
||||||
password=dict(
|
|
||||||
type="str", aliases=["repo_password"], no_log=True, required=False
|
|
||||||
),
|
|
||||||
key_file=dict(type="path", required=False),
|
|
||||||
cert_file=dict(type="path", required=False),
|
|
||||||
ca_file=dict(type="path", required=False),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def login(
|
|
||||||
command,
|
|
||||||
host,
|
|
||||||
insecure,
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
key_file,
|
|
||||||
cert_file,
|
|
||||||
ca_file,
|
|
||||||
):
|
|
||||||
login_command = command + " registry login " + host
|
|
||||||
|
|
||||||
if username is not None and password is not None:
|
|
||||||
login_command += " --username=" + username + " --password-stdin"
|
|
||||||
|
|
||||||
if insecure:
|
|
||||||
login_command += " --insecure"
|
|
||||||
|
|
||||||
if key_file is not None:
|
|
||||||
login_command += " --key-file=" + key_file
|
|
||||||
|
|
||||||
if cert_file is not None:
|
|
||||||
login_command += " --cert-file=" + cert_file
|
|
||||||
|
|
||||||
if ca_file is not None:
|
|
||||||
login_command += " --ca-file=" + ca_file
|
|
||||||
|
|
||||||
return login_command
|
|
||||||
|
|
||||||
|
|
||||||
def logout(command, host):
|
|
||||||
return command + " registry logout " + host
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
global module
|
|
||||||
|
|
||||||
module = AnsibleHelmModule(
|
|
||||||
argument_spec=arg_spec(),
|
|
||||||
required_together=[["username", "password"]],
|
|
||||||
supports_check_mode=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Validate Helm version >=3.0.0,<4.0.0
|
|
||||||
module.validate_helm_version()
|
|
||||||
|
|
||||||
changed = False
|
|
||||||
|
|
||||||
host = module.params.get("host")
|
|
||||||
state = module.params.get("state")
|
|
||||||
insecure = module.params.get("insecure")
|
|
||||||
username = module.params.get("username")
|
|
||||||
password = module.params.get("password")
|
|
||||||
key_file = module.params.get("key_file")
|
|
||||||
cert_file = module.params.get("cert_file")
|
|
||||||
ca_file = module.params.get("ca_file")
|
|
||||||
|
|
||||||
helm_cmd = module.get_helm_binary()
|
|
||||||
|
|
||||||
if state == "absent":
|
|
||||||
helm_cmd = logout(helm_cmd, host)
|
|
||||||
changed = True
|
|
||||||
elif state == "present":
|
|
||||||
helm_cmd = login(
|
|
||||||
helm_cmd, host, insecure, username, password, key_file, cert_file, ca_file
|
|
||||||
)
|
|
||||||
changed = True
|
|
||||||
|
|
||||||
if module.check_mode:
|
|
||||||
module.exit_json(changed=changed, command=helm_cmd)
|
|
||||||
|
|
||||||
rc, out, err = module.run_helm_command(
|
|
||||||
helm_cmd, data=password, fails_on_error=False
|
|
||||||
)
|
|
||||||
|
|
||||||
if rc != 0:
|
|
||||||
if state == "absent" and "Error: not logged in" in err:
|
|
||||||
changed = False
|
|
||||||
else:
|
|
||||||
module.fail_json(
|
|
||||||
msg="Failure when executing Helm command. Exited {0}.\nstdout: {1}\nstderr: {2}".format(
|
|
||||||
rc, out, err
|
|
||||||
),
|
|
||||||
stderr=err,
|
|
||||||
command=helm_cmd,
|
|
||||||
)
|
|
||||||
|
|
||||||
helm_version = module.get_helm_version()
|
|
||||||
if LooseVersion(helm_version) >= LooseVersion("3.18.0") and state == "absent":
|
|
||||||
# https://github.com/ansible-collections/kubernetes.core/issues/944
|
|
||||||
module.warn(
|
|
||||||
"The helm_registry_auth is not idempotent with helm >= 3.18.0, always report a change."
|
|
||||||
)
|
|
||||||
|
|
||||||
module.exit_json(changed=changed, stdout=out, stderr=err, command=helm_cmd)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
@@ -119,13 +119,6 @@ options:
|
|||||||
aliases: [ force ]
|
aliases: [ force ]
|
||||||
default: False
|
default: False
|
||||||
version_added: 2.4.0
|
version_added: 2.4.0
|
||||||
insecure_skip_tls_verify:
|
|
||||||
description:
|
|
||||||
- Skip tls certificate checks for the repository url.
|
|
||||||
type: bool
|
|
||||||
default: False
|
|
||||||
aliases: [ skip_tls_certs_check ]
|
|
||||||
version_added: "5.3.0"
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
EXAMPLES = r"""
|
EXAMPLES = r"""
|
||||||
@@ -233,7 +226,6 @@ def install_repository(
|
|||||||
repository_password,
|
repository_password,
|
||||||
pass_credentials,
|
pass_credentials,
|
||||||
force_update,
|
force_update,
|
||||||
insecure_skip_tls_verify,
|
|
||||||
):
|
):
|
||||||
install_command = command + " repo add " + repository_name + " " + repository_url
|
install_command = command + " repo add " + repository_name + " " + repository_url
|
||||||
|
|
||||||
@@ -247,9 +239,6 @@ def install_repository(
|
|||||||
if force_update:
|
if force_update:
|
||||||
install_command += " --force-update"
|
install_command += " --force-update"
|
||||||
|
|
||||||
if insecure_skip_tls_verify:
|
|
||||||
install_command += " --insecure-skip-tls-verify"
|
|
||||||
|
|
||||||
return install_command
|
return install_command
|
||||||
|
|
||||||
|
|
||||||
@@ -273,9 +262,6 @@ def argument_spec():
|
|||||||
),
|
),
|
||||||
pass_credentials=dict(type="bool", default=False, no_log=True),
|
pass_credentials=dict(type="bool", default=False, no_log=True),
|
||||||
force_update=dict(type="bool", default=False, aliases=["force"]),
|
force_update=dict(type="bool", default=False, aliases=["force"]),
|
||||||
insecure_skip_tls_verify=dict(
|
|
||||||
type="bool", default=False, aliases=["skip_tls_certs_check"]
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return arg_spec
|
return arg_spec
|
||||||
@@ -295,9 +281,6 @@ 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,<4.0.0
|
|
||||||
module.validate_helm_version()
|
|
||||||
|
|
||||||
changed = False
|
changed = False
|
||||||
|
|
||||||
repo_name = module.params.get("repo_name")
|
repo_name = module.params.get("repo_name")
|
||||||
@@ -307,7 +290,6 @@ def main():
|
|||||||
repo_state = module.params.get("repo_state")
|
repo_state = module.params.get("repo_state")
|
||||||
pass_credentials = module.params.get("pass_credentials")
|
pass_credentials = module.params.get("pass_credentials")
|
||||||
force_update = module.params.get("force_update")
|
force_update = module.params.get("force_update")
|
||||||
insecure_skip_tls_verify = module.params.get("insecure_skip_tls_verify")
|
|
||||||
|
|
||||||
helm_cmd = module.get_helm_binary()
|
helm_cmd = module.get_helm_binary()
|
||||||
|
|
||||||
@@ -326,7 +308,6 @@ def main():
|
|||||||
repo_password,
|
repo_password,
|
||||||
pass_credentials,
|
pass_credentials,
|
||||||
force_update,
|
force_update,
|
||||||
insecure_skip_tls_verify,
|
|
||||||
)
|
)
|
||||||
changed = True
|
changed = True
|
||||||
elif repository_status["url"] != repo_url:
|
elif repository_status["url"] != repo_url:
|
||||||
|
|||||||
@@ -72,13 +72,6 @@ options:
|
|||||||
- If the directory already exists, it will be overwritten.
|
- If the directory already exists, it will be overwritten.
|
||||||
required: false
|
required: false
|
||||||
type: path
|
type: path
|
||||||
insecure_registry:
|
|
||||||
description:
|
|
||||||
- Skip TLS certificate checks for the chart download
|
|
||||||
required: false
|
|
||||||
type: bool
|
|
||||||
default: false
|
|
||||||
version_added: 5.1.0
|
|
||||||
release_name:
|
release_name:
|
||||||
description:
|
description:
|
||||||
- Release name to use in rendered templates.
|
- Release name to use in rendered templates.
|
||||||
@@ -228,7 +221,6 @@ def template(
|
|||||||
dependency_update=None,
|
dependency_update=None,
|
||||||
disable_hook=None,
|
disable_hook=None,
|
||||||
output_dir=None,
|
output_dir=None,
|
||||||
insecure_registry=None,
|
|
||||||
show_only=None,
|
show_only=None,
|
||||||
release_name=None,
|
release_name=None,
|
||||||
release_namespace=None,
|
release_namespace=None,
|
||||||
@@ -259,9 +251,6 @@ def template(
|
|||||||
if output_dir:
|
if output_dir:
|
||||||
cmd += " --output-dir=" + output_dir
|
cmd += " --output-dir=" + output_dir
|
||||||
|
|
||||||
if insecure_registry:
|
|
||||||
cmd += " --insecure-skip-tls-verify"
|
|
||||||
|
|
||||||
if show_only:
|
if show_only:
|
||||||
for template in show_only:
|
for template in show_only:
|
||||||
cmd += " -s " + template
|
cmd += " -s " + template
|
||||||
@@ -300,7 +289,6 @@ def main():
|
|||||||
include_crds=dict(type="bool", default=False),
|
include_crds=dict(type="bool", default=False),
|
||||||
release_name=dict(type="str", aliases=["name"]),
|
release_name=dict(type="str", aliases=["name"]),
|
||||||
output_dir=dict(type="path"),
|
output_dir=dict(type="path"),
|
||||||
insecure_registry=dict(type="bool", default=False),
|
|
||||||
release_namespace=dict(type="str"),
|
release_namespace=dict(type="str"),
|
||||||
release_values=dict(type="dict", default={}, aliases=["values"]),
|
release_values=dict(type="dict", default={}, aliases=["values"]),
|
||||||
show_only=dict(type="list", default=[], elements="str"),
|
show_only=dict(type="list", default=[], elements="str"),
|
||||||
@@ -320,7 +308,6 @@ def main():
|
|||||||
include_crds = module.params.get("include_crds")
|
include_crds = module.params.get("include_crds")
|
||||||
release_name = module.params.get("release_name")
|
release_name = module.params.get("release_name")
|
||||||
output_dir = module.params.get("output_dir")
|
output_dir = module.params.get("output_dir")
|
||||||
insecure_registry = module.params.get("insecure_registry")
|
|
||||||
show_only = module.params.get("show_only")
|
show_only = module.params.get("show_only")
|
||||||
release_namespace = module.params.get("release_namespace")
|
release_namespace = module.params.get("release_namespace")
|
||||||
release_values = module.params.get("release_values")
|
release_values = module.params.get("release_values")
|
||||||
@@ -331,9 +318,6 @@ 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,<4.0.0
|
|
||||||
module.validate_helm_version()
|
|
||||||
|
|
||||||
helm_cmd = module.get_helm_binary()
|
helm_cmd = module.get_helm_binary()
|
||||||
|
|
||||||
if update_repo_cache:
|
if update_repo_cache:
|
||||||
@@ -353,7 +337,6 @@ def main():
|
|||||||
disable_hook=disable_hook,
|
disable_hook=disable_hook,
|
||||||
release_name=release_name,
|
release_name=release_name,
|
||||||
output_dir=output_dir,
|
output_dir=output_dir,
|
||||||
insecure_registry=insecure_registry,
|
|
||||||
release_namespace=release_namespace,
|
release_namespace=release_namespace,
|
||||||
release_values=release_values,
|
release_values=release_values,
|
||||||
show_only=show_only,
|
show_only=show_only,
|
||||||
|
|||||||
@@ -57,14 +57,15 @@ options:
|
|||||||
- Whether to override the default patch merge approach with a specific type. By default, the strategic
|
- Whether to override the default patch merge approach with a specific type. By default, the strategic
|
||||||
merge will typically be used.
|
merge will typically be used.
|
||||||
- For example, Custom Resource Definitions typically aren't updatable by the usual strategic merge. You may
|
- For example, Custom Resource Definitions typically aren't updatable by the usual strategic merge. You may
|
||||||
want to use C(merge) if you see "strategic merge patch format is not supported".
|
want to use C(merge) if you see "strategic merge patch format is not supported"
|
||||||
- See U(https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/#use-a-json-merge-patch-to-update-a-deployment)
|
- See U(https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/#use-a-json-merge-patch-to-update-a-deployment)
|
||||||
- If more than one C(merge_type) is given, the merge_types will be tried in order. This defaults to
|
- If more than one C(merge_type) is given, the merge_types will be tried in order. This defaults to
|
||||||
C(['strategic-merge', 'merge']), which is ideal for using the same parameters on resource kinds that
|
C(['strategic-merge', 'merge']), which is ideal for using the same parameters on resource kinds that
|
||||||
combine Custom Resources and built-in resources.
|
combine Custom Resources and built-in resources.
|
||||||
- Mutually exclusive with C(apply).
|
- mutually exclusive with C(apply)
|
||||||
- I(merge_type=json) has been removed in version 4.0.0. Please use M(kubernetes.core.k8s_json_patch) instead.
|
- I(merge_type=json) is deprecated and will be removed in version 4.0.0. Please use M(kubernetes.core.k8s_json_patch) instead.
|
||||||
choices:
|
choices:
|
||||||
|
- json
|
||||||
- merge
|
- merge
|
||||||
- strategic-merge
|
- strategic-merge
|
||||||
type: list
|
type: list
|
||||||
@@ -100,7 +101,7 @@ options:
|
|||||||
- C(apply) compares the desired resource definition with the previously supplied resource definition,
|
- C(apply) compares the desired resource definition with the previously supplied resource definition,
|
||||||
ignoring properties that are automatically generated
|
ignoring properties that are automatically generated
|
||||||
- C(apply) works better with Services than 'force=yes'
|
- C(apply) works better with Services than 'force=yes'
|
||||||
- Mutually exclusive with C(merge_type).
|
- mutually exclusive with C(merge_type)
|
||||||
default: False
|
default: False
|
||||||
type: bool
|
type: bool
|
||||||
template:
|
template:
|
||||||
@@ -181,18 +182,17 @@ options:
|
|||||||
- This parameter can be used with C(label_selectors) to restrict the resources to be deleted.
|
- This parameter can be used with C(label_selectors) to restrict the resources to be deleted.
|
||||||
type: bool
|
type: bool
|
||||||
default: false
|
default: false
|
||||||
version_added: 3.0.0
|
version_added: 2.5.0
|
||||||
aliases:
|
aliases:
|
||||||
- all
|
- all
|
||||||
hidden_fields:
|
hidden_fields:
|
||||||
description:
|
description:
|
||||||
- Hide fields matching this option in the result
|
- Hide fields matching this option in the result
|
||||||
- An example might be C(hidden_fields=[metadata.managedFields])
|
- An example might be C(hidden_fields=[metadata.managedFields])
|
||||||
or V(hidden_fields=[spec.containers[0].env[3].value])
|
- Only field definitions that don't reference list items are supported (so V(spec.containers[0]) would not work)
|
||||||
or V(hidden_fields=[metadata.annotations[kubectl.kubernetes.io/last-applied-configuration]])
|
|
||||||
type: list
|
type: list
|
||||||
elements: str
|
elements: str
|
||||||
version_added: 3.0.0
|
version_added: 2.5.0
|
||||||
|
|
||||||
requirements:
|
requirements:
|
||||||
- "python >= 3.9"
|
- "python >= 3.9"
|
||||||
@@ -383,24 +383,28 @@ result:
|
|||||||
contains:
|
contains:
|
||||||
api_version:
|
api_version:
|
||||||
description: The versioned schema of this representation of an object.
|
description: The versioned schema of this representation of an object.
|
||||||
returned: when O(resource_definition) or O(src) contains a single object.
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
kind:
|
kind:
|
||||||
description: Represents the REST resource this object represents.
|
description: Represents the REST resource this object represents.
|
||||||
returned: when O(resource_definition) or O(src) contains a single object.
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
metadata:
|
metadata:
|
||||||
description: Standard object metadata. Includes name, namespace, annotations, labels, etc.
|
description: Standard object metadata. Includes name, namespace, annotations, labels, etc.
|
||||||
returned: when O(resource_definition) or O(src) contains a single object.
|
returned: success
|
||||||
type: complex
|
type: complex
|
||||||
spec:
|
spec:
|
||||||
description: Specific attributes of the object. Will vary based on the I(api_version) and I(kind).
|
description: Specific attributes of the object. Will vary based on the I(api_version) and I(kind).
|
||||||
returned: when O(resource_definition) or O(src) contains a single object.
|
returned: success
|
||||||
type: complex
|
type: complex
|
||||||
status:
|
status:
|
||||||
description: Current status details for the object.
|
description: Current status details for the object.
|
||||||
returned: when O(resource_definition) or O(src) contains a single object.
|
returned: success
|
||||||
type: complex
|
type: complex
|
||||||
|
items:
|
||||||
|
description: Returned only when multiple yaml documents are passed to src or resource_definition
|
||||||
|
returned: when resource_definition or src contains list of objects
|
||||||
|
type: list
|
||||||
duration:
|
duration:
|
||||||
description: elapsed time of task in seconds
|
description: elapsed time of task in seconds
|
||||||
returned: when C(wait) is true
|
returned: when C(wait) is true
|
||||||
@@ -410,46 +414,6 @@ result:
|
|||||||
description: error while trying to create/delete the object.
|
description: error while trying to create/delete the object.
|
||||||
returned: error
|
returned: error
|
||||||
type: complex
|
type: complex
|
||||||
results:
|
|
||||||
description: An array of created, patched, or otherwise present objects.
|
|
||||||
returned: when O(resource_definition) or O(src) contains a list of objects.
|
|
||||||
type: complex
|
|
||||||
contains:
|
|
||||||
api_version:
|
|
||||||
description: The versioned schema of this representation of an object.
|
|
||||||
returned: when O(resource_definition) or O(src) contains a single object.
|
|
||||||
type: str
|
|
||||||
kind:
|
|
||||||
description: Represents the REST resource this object represents.
|
|
||||||
returned: when O(resource_definition) or O(src) contains a single object.
|
|
||||||
type: str
|
|
||||||
metadata:
|
|
||||||
description: Standard object metadata. Includes name, namespace, annotations, labels, etc.
|
|
||||||
returned: when O(resource_definition) or O(src) contains a single object.
|
|
||||||
type: complex
|
|
||||||
spec:
|
|
||||||
description: Specific attributes of the object. Will vary based on the I(api_version) and I(kind).
|
|
||||||
returned: when O(resource_definition) or O(src) contains a single object.
|
|
||||||
type: complex
|
|
||||||
status:
|
|
||||||
description: Current status details for the object.
|
|
||||||
returned: when O(resource_definition) or O(src) contains a single object.
|
|
||||||
type: complex
|
|
||||||
duration:
|
|
||||||
description: elapsed time of task in seconds
|
|
||||||
returned: when C(wait) is true
|
|
||||||
type: int
|
|
||||||
sample: 48
|
|
||||||
error:
|
|
||||||
description: error while trying to create/delete the object.
|
|
||||||
returned: error
|
|
||||||
type: complex
|
|
||||||
method:
|
|
||||||
description:
|
|
||||||
- The method used to deploy the resource.
|
|
||||||
returned: success
|
|
||||||
type: str
|
|
||||||
sample: create
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
@@ -496,7 +460,7 @@ def argspec():
|
|||||||
argument_spec.update(copy.deepcopy(AUTH_ARG_SPEC))
|
argument_spec.update(copy.deepcopy(AUTH_ARG_SPEC))
|
||||||
argument_spec.update(copy.deepcopy(WAIT_ARG_SPEC))
|
argument_spec.update(copy.deepcopy(WAIT_ARG_SPEC))
|
||||||
argument_spec["merge_type"] = dict(
|
argument_spec["merge_type"] = dict(
|
||||||
type="list", elements="str", choices=["merge", "strategic-merge"]
|
type="list", elements="str", choices=["json", "merge", "strategic-merge"]
|
||||||
)
|
)
|
||||||
argument_spec["validate"] = dict(type="dict", default=None, options=validate_spec())
|
argument_spec["validate"] = dict(type="dict", default=None, options=validate_spec())
|
||||||
argument_spec["append_hash"] = dict(type="bool", default=False)
|
argument_spec["append_hash"] = dict(type="bool", default=False)
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ options:
|
|||||||
|
|
||||||
notes:
|
notes:
|
||||||
- the tar binary is required on the container when copying from local filesystem to pod.
|
- the tar binary is required on the container when copying from local filesystem to pod.
|
||||||
- the (init) container has to be started before you copy files or directories to it.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
EXAMPLES = r"""
|
EXAMPLES = r"""
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ options:
|
|||||||
- This option has effect only when C(state) is set to I(drain).
|
- This option has effect only when C(state) is set to I(drain).
|
||||||
type: list
|
type: list
|
||||||
elements: str
|
elements: str
|
||||||
version_added: 3.0.0
|
version_added: 2.5.0
|
||||||
aliases:
|
aliases:
|
||||||
- label_selectors
|
- label_selectors
|
||||||
delete_options:
|
delete_options:
|
||||||
@@ -106,8 +106,7 @@ EXAMPLES = r"""
|
|||||||
kubernetes.core.k8s_drain:
|
kubernetes.core.k8s_drain:
|
||||||
state: drain
|
state: drain
|
||||||
name: foo
|
name: foo
|
||||||
delete_options:
|
force: yes
|
||||||
force: yes
|
|
||||||
|
|
||||||
- name: Drain node "foo", but abort if there are pods not managed by a ReplicationController, Job, or DaemonSet, and use a grace period of 15 minutes.
|
- name: Drain node "foo", but abort if there are pods not managed by a ReplicationController, Job, or DaemonSet, and use a grace period of 15 minutes.
|
||||||
kubernetes.core.k8s_drain:
|
kubernetes.core.k8s_drain:
|
||||||
@@ -144,7 +143,6 @@ result:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import json
|
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@@ -189,17 +187,6 @@ except ImportError:
|
|||||||
HAS_EVICTION_API = False
|
HAS_EVICTION_API = False
|
||||||
|
|
||||||
|
|
||||||
def format_dynamic_api_exc(exc):
|
|
||||||
if exc.body:
|
|
||||||
if exc.headers and exc.headers.get("Content-Type") == "application/json":
|
|
||||||
message = json.loads(exc.body).get("message")
|
|
||||||
if message:
|
|
||||||
return message
|
|
||||||
return exc.body
|
|
||||||
else:
|
|
||||||
return "%s Reason: %s" % (exc.status, exc.reason)
|
|
||||||
|
|
||||||
|
|
||||||
def filter_pods(pods, force, ignore_daemonset, delete_emptydir_data):
|
def filter_pods(pods, force, ignore_daemonset, delete_emptydir_data):
|
||||||
k8s_kind_mirror = "kubernetes.io/config.mirror"
|
k8s_kind_mirror = "kubernetes.io/config.mirror"
|
||||||
daemonSet, unmanaged, mirror, localStorage, to_delete = [], [], [], [], []
|
daemonSet, unmanaged, mirror, localStorage, to_delete = [], [], [], [], []
|
||||||
@@ -304,19 +291,16 @@ class K8sDrainAnsible(object):
|
|||||||
return (datetime.now() - start).seconds
|
return (datetime.now() - start).seconds
|
||||||
|
|
||||||
response = None
|
response = None
|
||||||
pod = None
|
pod = pods.pop()
|
||||||
while (_elapsed_time() < wait_timeout or wait_timeout == 0) and pods:
|
while (_elapsed_time() < wait_timeout or wait_timeout == 0) and pods:
|
||||||
if not pod:
|
if not pod:
|
||||||
pod = pods[-1]
|
pod = pods.pop()
|
||||||
try:
|
try:
|
||||||
response = self._api_instance.read_namespaced_pod(
|
response = self._api_instance.read_namespaced_pod(
|
||||||
namespace=pod[0], name=pod[1]
|
namespace=pod[0], name=pod[1]
|
||||||
)
|
)
|
||||||
if not response or response.spec.node_name != self._module.params.get(
|
if not response:
|
||||||
"name"
|
|
||||||
):
|
|
||||||
pod = None
|
pod = None
|
||||||
del pods[-1]
|
|
||||||
time.sleep(wait_sleep)
|
time.sleep(wait_sleep)
|
||||||
except ApiException as exc:
|
except ApiException as exc:
|
||||||
if exc.reason != "Not Found":
|
if exc.reason != "Not Found":
|
||||||
@@ -324,7 +308,6 @@ class K8sDrainAnsible(object):
|
|||||||
msg="Exception raised: {0}".format(exc.reason)
|
msg="Exception raised: {0}".format(exc.reason)
|
||||||
)
|
)
|
||||||
pod = None
|
pod = None
|
||||||
del pods[-1]
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._module.fail_json(msg="Exception raised: {0}".format(to_native(e)))
|
self._module.fail_json(msg="Exception raised: {0}".format(to_native(e)))
|
||||||
if not pods:
|
if not pods:
|
||||||
@@ -351,7 +334,7 @@ class K8sDrainAnsible(object):
|
|||||||
if exc.reason != "Not Found":
|
if exc.reason != "Not Found":
|
||||||
self._module.fail_json(
|
self._module.fail_json(
|
||||||
msg="Failed to delete pod {0}/{1} due to: {2}".format(
|
msg="Failed to delete pod {0}/{1} due to: {2}".format(
|
||||||
namespace, name, to_native(format_dynamic_api_exc(exc))
|
namespace, name, exc.reason
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
@@ -441,8 +424,7 @@ class K8sDrainAnsible(object):
|
|||||||
warnings.append(warn)
|
warnings.append(warn)
|
||||||
result.append("{0} Pod(s) deleted from node.".format(number_pod))
|
result.append("{0} Pod(s) deleted from node.".format(number_pod))
|
||||||
if warnings:
|
if warnings:
|
||||||
for warning in warnings:
|
return dict(result=" ".join(result), warnings=warnings)
|
||||||
self._module.warn(warning)
|
|
||||||
return dict(result=" ".join(result))
|
return dict(result=" ".join(result))
|
||||||
|
|
||||||
def patch_node(self, unschedulable):
|
def patch_node(self, unschedulable):
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ from ansible.module_utils._text import to_native
|
|||||||
from ansible_collections.kubernetes.core.plugins.module_utils.ansiblemodule import (
|
from ansible_collections.kubernetes.core.plugins.module_utils.ansiblemodule import (
|
||||||
AnsibleModule,
|
AnsibleModule,
|
||||||
)
|
)
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
|
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
|
||||||
AUTH_ARG_SPEC,
|
AUTH_ARG_SPEC,
|
||||||
)
|
)
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
||||||
@@ -219,6 +219,12 @@ def execute_module(module, client):
|
|||||||
else:
|
else:
|
||||||
rc = int(err["details"]["causes"][0]["message"])
|
rc = int(err["details"]["causes"][0]["message"])
|
||||||
|
|
||||||
|
module.deprecate(
|
||||||
|
"The 'return_code' return key is being renamed to 'rc'. "
|
||||||
|
"Both keys are being returned for now to allow users to migrate their automation.",
|
||||||
|
version="4.0.0",
|
||||||
|
collection_name="kubernetes.core",
|
||||||
|
)
|
||||||
module.exit_json(
|
module.exit_json(
|
||||||
# Some command might change environment, but ultimately failing at end
|
# Some command might change environment, but ultimately failing at end
|
||||||
changed=True,
|
changed=True,
|
||||||
|
|||||||
@@ -48,11 +48,10 @@ options:
|
|||||||
description:
|
description:
|
||||||
- Hide fields matching any of the field definitions in the result
|
- Hide fields matching any of the field definitions in the result
|
||||||
- An example might be C(hidden_fields=[metadata.managedFields])
|
- An example might be C(hidden_fields=[metadata.managedFields])
|
||||||
or V(hidden_fields=[spec.containers[0].env[3].value])
|
- Only field definitions that don't reference list items are supported (so V(spec.containers[0]) would not work)
|
||||||
or V(hidden_fields=[metadata.annotations[kubectl.kubernetes.io/last-applied-configuration]])
|
|
||||||
type: list
|
type: list
|
||||||
elements: str
|
elements: str
|
||||||
version_added: 3.0.0
|
version_added: 2.5.0
|
||||||
|
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- kubernetes.core.k8s_auth_options
|
- kubernetes.core.k8s_auth_options
|
||||||
@@ -120,21 +119,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"""
|
||||||
|
|||||||
@@ -168,9 +168,7 @@ def perform_action(svc, resource):
|
|||||||
module.params["kind"],
|
module.params["kind"],
|
||||||
resource["metadata"]["name"],
|
resource["metadata"]["name"],
|
||||||
)
|
)
|
||||||
if warn:
|
result = {"changed": False, "warnings": [warn]}
|
||||||
module.warn(warn)
|
|
||||||
result = {"changed": False}
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
if module.params["kind"] == "Deployment":
|
if module.params["kind"] == "Deployment":
|
||||||
|
|||||||
@@ -243,12 +243,10 @@ def execute_module(client, module):
|
|||||||
module.fail_json(msg=error, **return_attributes)
|
module.fail_json(msg=error, **return_attributes)
|
||||||
|
|
||||||
def _continue_or_exit(warn):
|
def _continue_or_exit(warn):
|
||||||
if warn:
|
|
||||||
module.warn(warn)
|
|
||||||
if multiple_scale:
|
if multiple_scale:
|
||||||
return_attributes["results"].append({"changed": False})
|
return_attributes["results"].append({"warning": warn, "changed": False})
|
||||||
else:
|
else:
|
||||||
module.exit_json(**return_attributes)
|
module.exit_json(warning=warn, **return_attributes)
|
||||||
|
|
||||||
for existing in existing_items:
|
for existing in existing_items:
|
||||||
if kind.lower() == "job":
|
if kind.lower() == "job":
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ helm_default_archive_name: "helm-{{ helm_version }}-{{ ansible_system | lower }}
|
|||||||
helm_binary: "/tmp/helm/{{ ansible_system | lower }}-amd64/helm"
|
helm_binary: "/tmp/helm/{{ ansible_system | lower }}-amd64/helm"
|
||||||
|
|
||||||
chart_test: "ingress-nginx"
|
chart_test: "ingress-nginx"
|
||||||
chart_test_oci: "oci://registry-1.docker.io/bitnamicharts/redis"
|
|
||||||
chart_test_local_path: "nginx-ingress"
|
chart_test_local_path: "nginx-ingress"
|
||||||
chart_test_version: 4.2.4
|
chart_test_version: 4.2.4
|
||||||
chart_test_version_local_path: 1.32.0
|
chart_test_version_local_path: 1.32.0
|
||||||
@@ -27,5 +26,3 @@ test_namespace:
|
|||||||
- "helm-from-url"
|
- "helm-from-url"
|
||||||
- "helm-reuse-values"
|
- "helm-reuse-values"
|
||||||
- "helm-chart-with-space-into-name"
|
- "helm-chart-with-space-into-name"
|
||||||
- "helm-reset-then-reuse-values"
|
|
||||||
- "helm-insecure"
|
|
||||||
|
|||||||
@@ -4,7 +4,4 @@
|
|||||||
loop_control:
|
loop_control:
|
||||||
loop_var: helm_version
|
loop_var: helm_version
|
||||||
with_items:
|
with_items:
|
||||||
- "v3.15.4"
|
- "v3.7.0"
|
||||||
- "v3.16.0"
|
|
||||||
- "v3.17.0"
|
|
||||||
- "v4.0.0"
|
|
||||||
|
|||||||
@@ -13,47 +13,33 @@
|
|||||||
include_role:
|
include_role:
|
||||||
name: install_helm
|
name: install_helm
|
||||||
|
|
||||||
- name: Main helm tests with Helm v3
|
- name: "Ensure we honor the environment variables"
|
||||||
when: helm_version != "v4.0.0"
|
include_tasks: test_read_envvars.yml
|
||||||
block:
|
|
||||||
|
|
||||||
- name: "Ensure we honor the environment variables"
|
- name: Deploy charts
|
||||||
include_tasks: test_read_envvars.yml
|
include_tasks: "tests_chart/{{ test_chart_type }}.yml"
|
||||||
when: helm_version != "v4.0.0"
|
loop_control:
|
||||||
|
loop_var: test_chart_type
|
||||||
|
with_items:
|
||||||
|
- from_local_path
|
||||||
|
- from_repository
|
||||||
|
- from_url
|
||||||
|
|
||||||
- name: Deploy charts
|
- name: test helm upgrade with reuse_values
|
||||||
include_tasks: "tests_chart/{{ test_chart_type }}.yml"
|
include_tasks: test_helm_reuse_values.yml
|
||||||
loop_control:
|
|
||||||
loop_var: test_chart_type
|
|
||||||
with_items:
|
|
||||||
- from_local_path
|
|
||||||
- from_repository
|
|
||||||
- from_url
|
|
||||||
|
|
||||||
- name: test helm upgrade with reuse_values
|
- name: test helm dependency update
|
||||||
include_tasks: test_helm_reuse_values.yml
|
include_tasks: test_up_dep.yml
|
||||||
|
|
||||||
- name: test helm upgrade with reset_then_reuse_values
|
- name: Test helm uninstall
|
||||||
include_tasks: test_helm_reset_then_reuse_values.yml
|
include_tasks: test_helm_uninstall.yml
|
||||||
|
|
||||||
- name: test helm dependency update
|
- name: Test helm install with chart name containing space
|
||||||
include_tasks: test_up_dep.yml
|
include_tasks: test_helm_with_space_into_chart_name.yml
|
||||||
|
|
||||||
- name: Test helm uninstall
|
# https://github.com/ansible-collections/community.kubernetes/issues/296
|
||||||
include_tasks: test_helm_uninstall.yml
|
- name: Test Skip CRDS feature in helm chart install
|
||||||
|
include_tasks: test_crds.yml
|
||||||
- name: Test helm install with chart name containing space
|
|
||||||
include_tasks: test_helm_with_space_into_chart_name.yml
|
|
||||||
|
|
||||||
# https://github.com/ansible-collections/community.kubernetes/issues/296
|
|
||||||
- name: Test Skip CRDS feature in helm chart install
|
|
||||||
include_tasks: test_crds.yml
|
|
||||||
|
|
||||||
- name: Test insecure registry flag feature
|
|
||||||
include_tasks: test_helm_insecure.yml
|
|
||||||
|
|
||||||
- name: Test helm version
|
|
||||||
include_tasks: test_helm_version.yml
|
|
||||||
|
|
||||||
- name: Clean helm install
|
- name: Clean helm install
|
||||||
file:
|
file:
|
||||||
|
|||||||
@@ -3,89 +3,78 @@
|
|||||||
vars:
|
vars:
|
||||||
test_chart: "test-crds"
|
test_chart: "test-crds"
|
||||||
helm_namespace: "{{ test_namespace[0] }}"
|
helm_namespace: "{{ test_namespace[0] }}"
|
||||||
helm_binary: helm
|
|
||||||
block:
|
block:
|
||||||
- name: Create namespace
|
- name: Create namespace
|
||||||
k8s:
|
k8s:
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
name: "{{ helm_namespace }}"
|
name: "{{ helm_namespace }}"
|
||||||
|
|
||||||
- name: Check if CRD resource is already present
|
- name: Copy test chart
|
||||||
k8s_info:
|
copy:
|
||||||
namespace: default
|
src: "{{ test_chart }}"
|
||||||
kind: Foo
|
dest: "/tmp/helm_test_crds/"
|
||||||
api_version: ansible.com/v1
|
|
||||||
|
- name: Install chart while skipping CRDs
|
||||||
|
helm:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
chart_ref: "/tmp/helm_test_crds/{{ test_chart }}"
|
||||||
|
namespace: "{{ helm_namespace }}"
|
||||||
|
name: test-crds
|
||||||
|
skip_crds: true
|
||||||
|
register: install
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- install is changed
|
||||||
|
- install.status.name == "test-crds"
|
||||||
|
|
||||||
|
- name: Fail to create custom resource
|
||||||
|
k8s:
|
||||||
|
definition:
|
||||||
|
apiVersion: ansible.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
|
namespace: "{{ helm_namespace }}"
|
||||||
|
name: test-foo
|
||||||
|
foobar: footest
|
||||||
ignore_errors: true
|
ignore_errors: true
|
||||||
register: crd_check
|
register: result
|
||||||
|
|
||||||
- when: crd_check is failed
|
- assert:
|
||||||
block:
|
that:
|
||||||
- name: Copy test chart
|
- result is failed
|
||||||
copy:
|
- "result.msg.startswith('Failed to find exact match for ansible.com/v1.Foo')"
|
||||||
src: "{{ test_chart }}"
|
|
||||||
dest: "/tmp/helm_test_crds/"
|
|
||||||
|
|
||||||
- name: Install chart while skipping CRDs
|
# Helm won't install CRDs into an existing release, so we need to delete this, first
|
||||||
helm:
|
- name: Uninstall chart
|
||||||
binary_path: "{{ helm_binary }}"
|
helm:
|
||||||
chart_ref: "/tmp/helm_test_crds/{{ test_chart }}"
|
binary_path: "{{ helm_binary }}"
|
||||||
|
namespace: "{{ helm_namespace }}"
|
||||||
|
name: test-crds
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Install chart with CRDs
|
||||||
|
helm:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
chart_ref: "/tmp/helm_test_crds/{{ test_chart }}"
|
||||||
|
namespace: "{{ helm_namespace }}"
|
||||||
|
name: test-crds
|
||||||
|
|
||||||
|
- name: Create custom resource
|
||||||
|
k8s:
|
||||||
|
definition:
|
||||||
|
apiVersion: ansible.com/v1
|
||||||
|
kind: Foo
|
||||||
|
metadata:
|
||||||
namespace: "{{ helm_namespace }}"
|
namespace: "{{ helm_namespace }}"
|
||||||
name: test-crds
|
name: test-foo
|
||||||
skip_crds: true
|
foobar: footest
|
||||||
register: install
|
register: result
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- install is changed
|
- result is changed
|
||||||
- install.status.name == "test-crds"
|
- result.result.foobar == "footest"
|
||||||
|
|
||||||
- name: Fail to create custom resource
|
|
||||||
k8s:
|
|
||||||
definition:
|
|
||||||
apiVersion: ansible.com/v1
|
|
||||||
kind: Foo
|
|
||||||
metadata:
|
|
||||||
namespace: "{{ helm_namespace }}"
|
|
||||||
name: test-foo
|
|
||||||
foobar: footest
|
|
||||||
ignore_errors: true
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- result is failed
|
|
||||||
- "result.msg.startswith('Failed to find exact match for ansible.com/v1.Foo')"
|
|
||||||
|
|
||||||
# Helm won't install CRDs into an existing release, so we need to delete this, first
|
|
||||||
- name: Uninstall chart
|
|
||||||
helm:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
namespace: "{{ helm_namespace }}"
|
|
||||||
name: test-crds
|
|
||||||
state: absent
|
|
||||||
|
|
||||||
- name: Install chart with CRDs
|
|
||||||
helm:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
chart_ref: "/tmp/helm_test_crds/{{ test_chart }}"
|
|
||||||
namespace: "{{ helm_namespace }}"
|
|
||||||
name: test-crds
|
|
||||||
|
|
||||||
- name: Create custom resource
|
|
||||||
k8s:
|
|
||||||
definition:
|
|
||||||
apiVersion: ansible.com/v1
|
|
||||||
kind: Foo
|
|
||||||
metadata:
|
|
||||||
namespace: "{{ helm_namespace }}"
|
|
||||||
name: test-foo
|
|
||||||
foobar: footest
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- result is changed
|
|
||||||
- result.result.foobar == "footest"
|
|
||||||
|
|
||||||
always:
|
always:
|
||||||
- name: Remove chart
|
- name: Remove chart
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Test helm insecure
|
|
||||||
vars:
|
|
||||||
helm_namespace: "{{ test_namespace[12] }}"
|
|
||||||
block:
|
|
||||||
|
|
||||||
- name: Initial chart installation (no flag set)
|
|
||||||
helm:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
chart_ref: "{{ chart_test_oci }}"
|
|
||||||
release_name: test-secure
|
|
||||||
release_namespace: "{{ helm_namespace }}"
|
|
||||||
create_namespace: true
|
|
||||||
register: install
|
|
||||||
|
|
||||||
- name: Validate that insecure flag is not set
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- install is changed
|
|
||||||
- '"--insecure-skip-tls-verify" not in install.command'
|
|
||||||
|
|
||||||
- name: Initial chart installation (insecure flag set)
|
|
||||||
helm:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
chart_ref: "{{ chart_test_oci }}"
|
|
||||||
release_name: test-insecure
|
|
||||||
release_namespace: "{{ helm_namespace }}"
|
|
||||||
insecure_skip_tls_verify: true
|
|
||||||
register: install
|
|
||||||
ignore_errors: true
|
|
||||||
|
|
||||||
- name: Validate that insecure flag IS set if helm version is >= 3.16.0
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- install is changed
|
|
||||||
- '"--insecure-skip-tls-verify" in install.command'
|
|
||||||
when: '"v3.16.0" <= helm_version'
|
|
||||||
|
|
||||||
- name: Validate that feature fails for helm < 3.16.0
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- install is failed
|
|
||||||
- '"insecure_skip_tls_verify requires helm >= 3.16.0" in install.msg'
|
|
||||||
when: 'helm_version < "v3.16.0"'
|
|
||||||
|
|
||||||
always:
|
|
||||||
- name: Remove helm namespace
|
|
||||||
k8s:
|
|
||||||
api_version: v1
|
|
||||||
kind: Namespace
|
|
||||||
name: "{{ helm_namespace }}"
|
|
||||||
state: absent
|
|
||||||
@@ -13,11 +13,3 @@
|
|||||||
that:
|
that:
|
||||||
- helm_missing_binary is failed
|
- helm_missing_binary is failed
|
||||||
- "'No such file or directory' in helm_missing_binary.msg"
|
- "'No such file or directory' in helm_missing_binary.msg"
|
||||||
when: ansible_version.full is version('2.20', '<')
|
|
||||||
|
|
||||||
- name: Assert that helm is not installed (ansible 2.20+)
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- helm_missing_binary is failed
|
|
||||||
- "'Error executing command' in helm_missing_binary.msg"
|
|
||||||
when: ansible_version.full is version('2.20', '>=')
|
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Test helm reset_then_reuse_values
|
|
||||||
vars:
|
|
||||||
helm_namespace: "{{ test_namespace[11] }}"
|
|
||||||
chart_release_values:
|
|
||||||
replica:
|
|
||||||
replicaCount: 3
|
|
||||||
master:
|
|
||||||
count: 1
|
|
||||||
kind: Deployment
|
|
||||||
chart_reset_then_reuse_values:
|
|
||||||
replica:
|
|
||||||
replicaCount: 1
|
|
||||||
master:
|
|
||||||
count: 3
|
|
||||||
block:
|
|
||||||
- name: Initial chart installation
|
|
||||||
helm:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
chart_ref: oci://registry-1.docker.io/bitnamicharts/redis
|
|
||||||
release_name: test-redis
|
|
||||||
release_namespace: "{{ helm_namespace }}"
|
|
||||||
create_namespace: true
|
|
||||||
release_values: "{{ chart_release_values }}"
|
|
||||||
register: install
|
|
||||||
|
|
||||||
- name: Get value set as string
|
|
||||||
helm_info:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
release_name: test-redis
|
|
||||||
release_namespace: "{{ helm_namespace }}"
|
|
||||||
register: release_value
|
|
||||||
|
|
||||||
- name: Validate that chart values are as expected
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- install is changed
|
|
||||||
- '"--reset-then-reuse-values" not in install.command'
|
|
||||||
- release_value["status"]["release_values"] == chart_release_values
|
|
||||||
|
|
||||||
- name: Upgrade chart using reset_then_reuse_values=true
|
|
||||||
helm:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
chart_ref: oci://registry-1.docker.io/bitnamicharts/redis
|
|
||||||
release_name: test-redis
|
|
||||||
release_namespace: "{{ helm_namespace }}"
|
|
||||||
reuse_values: false
|
|
||||||
reset_values: false
|
|
||||||
reset_then_reuse_values: true
|
|
||||||
release_values: "{{ chart_reset_then_reuse_values }}"
|
|
||||||
register: upgrade
|
|
||||||
|
|
||||||
- name: Get value set as string
|
|
||||||
helm_info:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
release_name: test-redis
|
|
||||||
release_namespace: "{{ helm_namespace }}"
|
|
||||||
register: release_value
|
|
||||||
|
|
||||||
- name: Validate that chart values are as expected
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- upgrade is changed
|
|
||||||
- '"--reset-then-reuse-values" in upgrade.command'
|
|
||||||
- '"--reuse-values " not in upgrade.command'
|
|
||||||
- '"--reset-values" not in upgrade.command'
|
|
||||||
- release_value["status"]["release_values"] == chart_release_values | combine(chart_reset_then_reuse_values, recursive=true)
|
|
||||||
|
|
||||||
always:
|
|
||||||
- name: Remove helm namespace
|
|
||||||
k8s:
|
|
||||||
api_version: v1
|
|
||||||
kind: Namespace
|
|
||||||
name: "{{ helm_namespace }}"
|
|
||||||
state: absent
|
|
||||||
@@ -17,7 +17,8 @@
|
|||||||
- name: Initial chart installation
|
- name: Initial chart installation
|
||||||
helm:
|
helm:
|
||||||
binary_path: "{{ helm_binary }}"
|
binary_path: "{{ helm_binary }}"
|
||||||
chart_ref: oci://registry-1.docker.io/bitnamicharts/redis
|
chart_ref: redis
|
||||||
|
chart_repo_url: https://charts.bitnami.com/bitnami
|
||||||
release_name: test-redis
|
release_name: test-redis
|
||||||
release_namespace: "{{ helm_namespace }}"
|
release_namespace: "{{ helm_namespace }}"
|
||||||
create_namespace: true
|
create_namespace: true
|
||||||
@@ -36,12 +37,13 @@
|
|||||||
that:
|
that:
|
||||||
- install is changed
|
- install is changed
|
||||||
- '"--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"]["values"] == chart_release_values
|
||||||
|
|
||||||
- name: Upgrade chart using reuse_values=true
|
- name: Upgrade chart using reuse_values=true
|
||||||
helm:
|
helm:
|
||||||
binary_path: "{{ helm_binary }}"
|
binary_path: "{{ helm_binary }}"
|
||||||
chart_ref: oci://registry-1.docker.io/bitnamicharts/redis
|
chart_ref: redis
|
||||||
|
chart_repo_url: https://charts.bitnami.com/bitnami
|
||||||
release_name: test-redis
|
release_name: test-redis
|
||||||
release_namespace: "{{ helm_namespace }}"
|
release_namespace: "{{ helm_namespace }}"
|
||||||
reuse_values: true
|
reuse_values: true
|
||||||
@@ -62,7 +64,7 @@
|
|||||||
- upgrade is changed
|
- upgrade is changed
|
||||||
- '"--reuse-values=True" in upgrade.command'
|
- '"--reuse-values=True" in upgrade.command'
|
||||||
- '"--reset-values" not in upgrade.command'
|
- '"--reset-values" not in upgrade.command'
|
||||||
- release_value["status"]["release_values"] == chart_release_values | combine(chart_reuse_values, recursive=true)
|
- release_value["status"]["values"] == chart_release_values | combine(chart_reuse_values, recursive=true)
|
||||||
|
|
||||||
always:
|
always:
|
||||||
- name: Remove helm namespace
|
- name: Remove helm namespace
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Test helm reuse_values
|
|
||||||
vars:
|
|
||||||
helm_namespace: "{{ test_namespace[12] }}"
|
|
||||||
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
|
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
that:
|
that:
|
||||||
- install_check_mode is changed
|
- install_check_mode is changed
|
||||||
- install_check_mode.status is defined
|
- install_check_mode.status is defined
|
||||||
- install_check_mode.status.release_values is defined
|
- install_check_mode.status.values is defined
|
||||||
|
|
||||||
- name: "Install {{ chart_test }} from {{ source }}"
|
- name: "Install {{ chart_test }} from {{ source }}"
|
||||||
helm:
|
helm:
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
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'
|
||||||
|
|
||||||
- name: Check helm_info content
|
- name: Check helm_info content
|
||||||
@@ -95,7 +95,7 @@
|
|||||||
- name: "Assert that {{ chart_test }} 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 }}"
|
||||||
- content_info.status.status | lower == 'deployed'
|
- content_info.status.status | lower == 'deployed'
|
||||||
- release_state_content_info.status.status | lower == 'deployed'
|
- release_state_content_info.status.status | lower == 'deployed'
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- install is not changed
|
- install is not 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'
|
||||||
|
|
||||||
- name: "Add vars to {{ chart_test }} from {{ source }}"
|
- name: "Add vars to {{ chart_test }} from {{ source }}"
|
||||||
@@ -130,8 +130,8 @@
|
|||||||
that:
|
that:
|
||||||
- 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'].revisionHistoryLimit == 0"
|
- "install.status['values'].revisionHistoryLimit == 0"
|
||||||
|
|
||||||
- name: Check idempotency after adding vars
|
- name: Check idempotency after adding vars
|
||||||
helm:
|
helm:
|
||||||
@@ -148,8 +148,8 @@
|
|||||||
that:
|
that:
|
||||||
- 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'].revisionHistoryLimit == 0"
|
- "install.status['values'].revisionHistoryLimit == 0"
|
||||||
|
|
||||||
- name: "Remove Vars to {{ chart_test }} from {{ source }}"
|
- name: "Remove Vars to {{ chart_test }} from {{ source }}"
|
||||||
helm:
|
helm:
|
||||||
@@ -165,8 +165,8 @@
|
|||||||
that:
|
that:
|
||||||
- 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'] == {}
|
- install.status['values'] == {}
|
||||||
|
|
||||||
- name: Check idempotency after removing vars
|
- name: Check idempotency after removing vars
|
||||||
helm:
|
helm:
|
||||||
@@ -182,8 +182,8 @@
|
|||||||
that:
|
that:
|
||||||
- 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'] == {}
|
- install.status['values'] == {}
|
||||||
|
|
||||||
- name: "Upgrade {{ chart_test }} from {{ source }}"
|
- name: "Upgrade {{ chart_test }} from {{ source }}"
|
||||||
helm:
|
helm:
|
||||||
@@ -199,7 +199,7 @@
|
|||||||
that:
|
that:
|
||||||
- install is changed
|
- install is changed
|
||||||
- install.status.status | lower == 'deployed'
|
- install.status.status | lower == 'deployed'
|
||||||
- install.status.chart == chart_test+"-"+chart_test_version_upgrade
|
- install.status.chart == "{{ chart_test }}-{{ chart_test_version_upgrade }}"
|
||||||
|
|
||||||
- name: Check idempotency after upgrade
|
- name: Check idempotency after upgrade
|
||||||
helm:
|
helm:
|
||||||
@@ -215,7 +215,7 @@
|
|||||||
that:
|
that:
|
||||||
- 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_upgrade
|
- install.status.chart == "{{ chart_test }}-{{ chart_test_version_upgrade }}"
|
||||||
|
|
||||||
- name: "Remove {{ chart_test }} from {{ source }}"
|
- name: "Remove {{ chart_test }} from {{ source }}"
|
||||||
helm:
|
helm:
|
||||||
@@ -316,8 +316,8 @@
|
|||||||
that:
|
that:
|
||||||
- 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'].revisionHistoryLimit == 0"
|
- "install.status['values'].revisionHistoryLimit == 0"
|
||||||
|
|
||||||
- name: "Install {{ chart_test }} from {{ source }} with values_files (again)"
|
- name: "Install {{ chart_test }} from {{ source }} with values_files (again)"
|
||||||
helm:
|
helm:
|
||||||
@@ -357,7 +357,7 @@
|
|||||||
- result is changed
|
- result is changed
|
||||||
- result is not failed
|
- result is not failed
|
||||||
- result.rc == 0
|
- result.rc == 0
|
||||||
- result.command is match(helm_binary+" template "+chart_source)
|
- result.command is match("{{ helm_binary }} template {{ chart_source }}")
|
||||||
|
|
||||||
- name: Check templates created
|
- name: Check templates created
|
||||||
stat:
|
stat:
|
||||||
@@ -374,8 +374,8 @@
|
|||||||
chart_ref: "{{ chart_source }}"
|
chart_ref: "{{ chart_source }}"
|
||||||
chart_version: "{{ chart_source_version | default(omit) }}"
|
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"
|
||||||
show_only:
|
show_only:
|
||||||
- "templates/configmap.yaml"
|
- "templates/configmap.yaml"
|
||||||
release_values:
|
release_values:
|
||||||
@@ -388,7 +388,7 @@
|
|||||||
- result is changed
|
- result is changed
|
||||||
- result is not failed
|
- result is not failed
|
||||||
- result.rc == 0
|
- result.rc == 0
|
||||||
- result.command is match(helm_binary+" template myrelease "+chart_source)
|
- result.command is match("{{ helm_binary }} template MyRelease {{ chart_source }}")
|
||||||
- result.stdout is search("ThisValue")
|
- result.stdout is search("ThisValue")
|
||||||
when: chart_source is search("test-chart")
|
when: chart_source is search("test-chart")
|
||||||
# limit assertion of test result to controlled (local) chart_source
|
# limit assertion of test result to controlled (local) chart_source
|
||||||
@@ -402,7 +402,7 @@
|
|||||||
namespace: "{{ helm_namespace }}"
|
namespace: "{{ helm_namespace }}"
|
||||||
create_namespace: true
|
create_namespace: true
|
||||||
context: does-not-exist
|
context: does-not-exist
|
||||||
ignore_errors: true
|
ignore_errors: yes
|
||||||
register: result
|
register: result
|
||||||
|
|
||||||
- name: Assert that release fails with non-existent context
|
- name: Assert that release fails with non-existent context
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
apiVersion: v2
|
|
||||||
name: test-chart-deployment-time
|
|
||||||
description: A chart with a config map containing the deployment time in data
|
|
||||||
type: application
|
|
||||||
version: 0.1.0
|
|
||||||
appVersion: "default"
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: {{ default "ansible-configmap" .Values.myConfigmapName }}
|
|
||||||
data:
|
|
||||||
myValue: {{ default "test" .Values.myValue }}
|
|
||||||
deploymentTime: {{ now }}
|
|
||||||
@@ -2,4 +2,3 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
- remove_namespace
|
- remove_namespace
|
||||||
- install_helm
|
- install_helm
|
||||||
- setup_helm_registry
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
- name: Test helm diff functionality
|
- name: Test helm diff functionality
|
||||||
vars:
|
vars:
|
||||||
test_chart_ref: "/tmp/test-chart"
|
test_chart_ref: "/tmp/test-chart"
|
||||||
|
redis_chart_version: '17.0.5'
|
||||||
|
|
||||||
block:
|
block:
|
||||||
|
|
||||||
@@ -10,7 +11,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.9.13
|
plugin_version: 3.4.0
|
||||||
|
|
||||||
- name: Copy test chart
|
- name: Copy test chart
|
||||||
copy:
|
copy:
|
||||||
@@ -23,7 +24,7 @@
|
|||||||
name: test-chart
|
name: test-chart
|
||||||
namespace: "{{ helm_namespace }}"
|
namespace: "{{ helm_namespace }}"
|
||||||
chart_ref: "{{ test_chart_ref }}"
|
chart_ref: "{{ test_chart_ref }}"
|
||||||
create_namespace: true
|
create_namespace: yes
|
||||||
register: install
|
register: install
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
@@ -48,8 +49,8 @@
|
|||||||
name: test-chart
|
name: test-chart
|
||||||
namespace: "{{ helm_namespace }}"
|
namespace: "{{ helm_namespace }}"
|
||||||
chart_ref: "{{ test_chart_ref }}"
|
chart_ref: "{{ test_chart_ref }}"
|
||||||
check_mode: true
|
check_mode: yes
|
||||||
diff: true
|
diff: yes
|
||||||
register: diff_result
|
register: diff_result
|
||||||
|
|
||||||
- name: Check if helm diff check is correct
|
- name: Check if helm diff check is correct
|
||||||
@@ -78,7 +79,7 @@
|
|||||||
namespace: "{{ helm_namespace }}"
|
namespace: "{{ helm_namespace }}"
|
||||||
chart_ref: "{{ test_chart_ref }}"
|
chart_ref: "{{ test_chart_ref }}"
|
||||||
check_mode: yes
|
check_mode: yes
|
||||||
diff: true
|
diff: yes
|
||||||
register: diff_result
|
register: diff_result
|
||||||
|
|
||||||
- name: Check if no diff in check mode when no change
|
- name: Check if no diff in check mode when no change
|
||||||
@@ -100,7 +101,7 @@
|
|||||||
|
|
||||||
- name: Modify values
|
- name: Modify values
|
||||||
blockinfile:
|
blockinfile:
|
||||||
create: true
|
create: yes
|
||||||
path: "{{ test_chart_ref }}/values.yml"
|
path: "{{ test_chart_ref }}/values.yml"
|
||||||
block: |
|
block: |
|
||||||
---
|
---
|
||||||
@@ -205,76 +206,52 @@
|
|||||||
- install is not changed
|
- install is not changed
|
||||||
|
|
||||||
# Test helm diff with chart_repo_url
|
# Test helm diff with chart_repo_url
|
||||||
|
- name: Define Redis chart values
|
||||||
|
set_fact:
|
||||||
|
redis_chart_values:
|
||||||
|
commonLabels:
|
||||||
|
phase: testing
|
||||||
|
company: RedHat
|
||||||
|
image:
|
||||||
|
tag: 6.2.6-debian-10-r135
|
||||||
|
architecture: standalone
|
||||||
|
|
||||||
|
- name: Install Redis chart
|
||||||
|
helm:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
chart_repo_url: https://charts.bitnami.com/bitnami
|
||||||
|
chart_ref: redis
|
||||||
|
namespace: "{{ helm_namespace }}"
|
||||||
|
name: redis-chart
|
||||||
|
chart_version: "{{ redis_chart_version }}"
|
||||||
|
release_values: "{{ redis_chart_values }}"
|
||||||
|
|
||||||
|
- name: Upgrade Redis chart
|
||||||
|
helm:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
chart_repo_url: https://charts.bitnami.com/bitnami
|
||||||
|
chart_ref: redis
|
||||||
|
namespace: "{{ helm_namespace }}"
|
||||||
|
name: redis-chart
|
||||||
|
chart_version: "{{ redis_chart_version }}"
|
||||||
|
release_values: "{{ redis_chart_values }}"
|
||||||
|
check_mode: yes
|
||||||
|
register: redis_upgrade
|
||||||
|
|
||||||
|
- name: Assert that module raised a warning
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- not redis_upgrade.changed
|
||||||
|
- redis_upgrade.warnings is defined
|
||||||
|
- redis_upgrade.warnings | length == 1
|
||||||
|
- redis_upgrade.warnings[0] == "The default idempotency check can fail to report changes in certain cases. Install helm diff >= 3.4.1 for better results."
|
||||||
|
|
||||||
- name: Uninstall helm diff
|
- name: Uninstall helm diff
|
||||||
helm_plugin:
|
helm_plugin:
|
||||||
binary_path: "{{ helm_binary }}"
|
binary_path: "{{ helm_binary }}"
|
||||||
state: absent
|
state: absent
|
||||||
plugin_name: diff
|
plugin_name: diff
|
||||||
ignore_errors: true
|
ignore_errors: yes
|
||||||
|
|
||||||
- name: Define chart variables
|
|
||||||
set_fact:
|
|
||||||
test_chart_values:
|
|
||||||
myValue: 'Some ConfigMap data value'
|
|
||||||
myConfigmapName: 'ansible-config-from-url'
|
|
||||||
test_chart_version: 0.1.0
|
|
||||||
test_chart_ref_url: "oci://localhost:6035/testing/test-chart-deployment-time"
|
|
||||||
|
|
||||||
- name: Deploy chart to remote registry
|
|
||||||
block:
|
|
||||||
- name: Create local directory to copy chart in
|
|
||||||
ansible.builtin.tempfile:
|
|
||||||
suffix: .chart
|
|
||||||
state: directory
|
|
||||||
register: _tmpd
|
|
||||||
|
|
||||||
- name: Copy local registry
|
|
||||||
ansible.builtin.copy:
|
|
||||||
dest: "{{ _tmpd.path }}"
|
|
||||||
src: '{{ role_path }}/files/test-chart-deployment-time'
|
|
||||||
|
|
||||||
- name: Push chart to helm registry
|
|
||||||
ansible.builtin.include_role:
|
|
||||||
name: push_to_helm_registry
|
|
||||||
vars:
|
|
||||||
chart_local_path: '{{ _tmpd.path }}/test-chart-deployment-time'
|
|
||||||
chart_repo_path: 'testing'
|
|
||||||
always:
|
|
||||||
- name: Delete temporary directory
|
|
||||||
ansible.builtin.file:
|
|
||||||
state: absent
|
|
||||||
path: '{{ _tmpd.path }}'
|
|
||||||
|
|
||||||
- name: Log into Helm registry
|
|
||||||
ansible.builtin.command: "{{ helm_binary }} registry login -u testuser -p 'pass123!' localhost:6035"
|
|
||||||
|
|
||||||
- name: Install chart from remote URL
|
|
||||||
helm:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
chart_ref: "{{ test_chart_ref_url }}"
|
|
||||||
chart_version: 0.1.0
|
|
||||||
namespace: "{{ helm_namespace }}"
|
|
||||||
name: another-chart
|
|
||||||
release_values: "{{ test_chart_values }}"
|
|
||||||
|
|
||||||
- name: Upgrade chart
|
|
||||||
helm:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
chart_ref: "{{ test_chart_ref_url }}"
|
|
||||||
chart_version: 0.1.0
|
|
||||||
namespace: "{{ helm_namespace }}"
|
|
||||||
name: another-chart
|
|
||||||
release_values: "{{ test_chart_values }}"
|
|
||||||
check_mode: true
|
|
||||||
register: _upgrade
|
|
||||||
|
|
||||||
- name: Assert that module raised a warning
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- not _upgrade.changed
|
|
||||||
- _upgrade.warnings is defined
|
|
||||||
- _upgrade.warnings | length == 1
|
|
||||||
- _upgrade.warnings[0] == "The default idempotency check can fail to report changes in certain cases. Install helm diff >= 3.4.1 for better results."
|
|
||||||
|
|
||||||
- name: Install helm diff (version=3.4.1)
|
- name: Install helm diff (version=3.4.1)
|
||||||
helm_plugin:
|
helm_plugin:
|
||||||
@@ -283,36 +260,37 @@
|
|||||||
plugin_path: https://github.com/databus23/helm-diff
|
plugin_path: https://github.com/databus23/helm-diff
|
||||||
plugin_version: 3.4.1
|
plugin_version: 3.4.1
|
||||||
|
|
||||||
- name: Upgrade chart once again
|
- name: Upgrade Redis chart once again
|
||||||
helm:
|
helm:
|
||||||
binary_path: "{{ helm_binary }}"
|
binary_path: "{{ helm_binary }}"
|
||||||
chart_ref: "{{ test_chart_ref_url }}"
|
chart_repo_url: https://charts.bitnami.com/bitnami
|
||||||
chart_version: 0.1.0
|
chart_ref: redis
|
||||||
namespace: "{{ helm_namespace }}"
|
namespace: "{{ helm_namespace }}"
|
||||||
name: another-chart
|
name: redis-chart
|
||||||
release_values: "{{ test_chart_values }}"
|
chart_version: "{{ redis_chart_version }}"
|
||||||
check_mode: true
|
release_values: "{{ redis_chart_values }}"
|
||||||
register: _upgrade_2
|
check_mode: yes
|
||||||
|
register: redis_upgrade_2
|
||||||
|
|
||||||
- name: Assert that module raised a warning
|
- name: Assert that module raised a warning
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- _upgrade_2.changed
|
- redis_upgrade_2.changed
|
||||||
- _upgrade_2.warnings is not defined
|
- redis_upgrade_2.warnings is not defined
|
||||||
|
|
||||||
always:
|
always:
|
||||||
- name: Remove chart directory
|
- name: Remove chart directory
|
||||||
file:
|
file:
|
||||||
path: "{{ test_chart_ref }}"
|
path: "{{ test_chart_ref }}"
|
||||||
state: absent
|
state: absent
|
||||||
ignore_errors: true
|
ignore_errors: yes
|
||||||
|
|
||||||
- name: Uninstall helm diff
|
- name: Uninstall helm diff
|
||||||
helm_plugin:
|
helm_plugin:
|
||||||
binary_path: "{{ helm_binary }}"
|
binary_path: "{{ helm_binary }}"
|
||||||
state: absent
|
state: absent
|
||||||
plugin_name: diff
|
plugin_name: diff
|
||||||
ignore_errors: true
|
ignore_errors: yes
|
||||||
|
|
||||||
- name: Remove helm namespace
|
- name: Remove helm namespace
|
||||||
k8s:
|
k8s:
|
||||||
@@ -321,8 +299,6 @@
|
|||||||
name: "{{ helm_namespace }}"
|
name: "{{ helm_namespace }}"
|
||||||
state: absent
|
state: absent
|
||||||
wait: true
|
wait: true
|
||||||
ignore_errors: true
|
ignore_errors: yes
|
||||||
|
|
||||||
- include_tasks: reuse_values.yml
|
- include_tasks: reuse_values.yml
|
||||||
|
|
||||||
- include_tasks: reset_then_reuse_values.yml
|
|
||||||
|
|||||||
@@ -1,189 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Create temporary directory for helm chart
|
|
||||||
tempfile:
|
|
||||||
suffix: .helm
|
|
||||||
state: directory
|
|
||||||
register: helm_dir
|
|
||||||
|
|
||||||
- name: Test helm diff functionality
|
|
||||||
vars:
|
|
||||||
test_chart_path: "{{ helm_dir.path }}/test-chart-reuse-values"
|
|
||||||
test_release_name: "myrelease"
|
|
||||||
|
|
||||||
block:
|
|
||||||
- name: Install helm diff
|
|
||||||
kubernetes.core.helm_plugin:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
state: present
|
|
||||||
plugin_path: https://github.com/databus23/helm-diff
|
|
||||||
plugin_version: 3.9.14
|
|
||||||
|
|
||||||
- name: Copy test chart
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: "test-chart-reuse-values"
|
|
||||||
dest: "{{ helm_dir.path }}"
|
|
||||||
|
|
||||||
- name: Delete existing namespace
|
|
||||||
kubernetes.core.k8s:
|
|
||||||
state: absent
|
|
||||||
wait: true
|
|
||||||
kind: Namespace
|
|
||||||
name: "{{ helm_namespace }}"
|
|
||||||
ignore_errors: true
|
|
||||||
|
|
||||||
- name: Create helm release
|
|
||||||
kubernetes.core.helm:
|
|
||||||
state: present
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
chart_ref: "{{ test_chart_path }}"
|
|
||||||
release_name: "{{ test_release_name }}"
|
|
||||||
release_namespace: "{{ helm_namespace }}"
|
|
||||||
create_namespace: true
|
|
||||||
release_values:
|
|
||||||
ansible_version: devel
|
|
||||||
phase: ci
|
|
||||||
wait: true
|
|
||||||
|
|
||||||
- name: Upgrade helm release (reset_values=false and reuse_values=false and reset_then_reuse_values=true)
|
|
||||||
kubernetes.core.helm:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
chart_ref: "{{ test_chart_path }}"
|
|
||||||
reset_values: false
|
|
||||||
reuse_values: false
|
|
||||||
reset_then_reuse_values: true
|
|
||||||
release_name: "{{ test_release_name }}"
|
|
||||||
release_namespace: "{{ helm_namespace }}"
|
|
||||||
values:
|
|
||||||
ansible_version: devel
|
|
||||||
register: helm_upgrade
|
|
||||||
|
|
||||||
- name: Ensure task did not reported change
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- helm_upgrade is not changed
|
|
||||||
|
|
||||||
- name: Upgrade helm release (reset_then_reuse_values=true with default value for reset_values and reuse_values=false)
|
|
||||||
kubernetes.core.helm:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
chart_ref: "{{ test_chart_path }}"
|
|
||||||
reuse_values: false
|
|
||||||
reset_then_reuse_values: true
|
|
||||||
release_name: "{{ test_release_name }}"
|
|
||||||
release_namespace: "{{ helm_namespace }}"
|
|
||||||
values:
|
|
||||||
ansible_version: devel
|
|
||||||
register: helm_upgrade
|
|
||||||
|
|
||||||
- name: Ensure task reported change
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- helm_upgrade is changed
|
|
||||||
|
|
||||||
# Delete helm and helm diff to install older version
|
|
||||||
- name: Uninstall helm diff
|
|
||||||
helm_plugin:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
state: absent
|
|
||||||
plugin_name: diff
|
|
||||||
ignore_errors: true
|
|
||||||
|
|
||||||
- name: Delete Helm folders
|
|
||||||
file:
|
|
||||||
path: /tmp/helm/
|
|
||||||
state: absent
|
|
||||||
|
|
||||||
- name: Init Helm folders
|
|
||||||
file:
|
|
||||||
path: /tmp/helm
|
|
||||||
state: directory
|
|
||||||
|
|
||||||
- name: Set Helm old version
|
|
||||||
set_fact:
|
|
||||||
helm_archive_name: "helm-v3.8.0-linux-amd64.tar.gz"
|
|
||||||
helm_diff_old_version: "3.8.0"
|
|
||||||
|
|
||||||
- name: Unarchive Helm binary
|
|
||||||
unarchive:
|
|
||||||
src: "https://get.helm.sh/{{ helm_archive_name | default(helm_default_archive_name) }}"
|
|
||||||
dest: /tmp/helm/
|
|
||||||
remote_src: yes
|
|
||||||
retries: 10
|
|
||||||
delay: 5
|
|
||||||
register: result
|
|
||||||
until: result is not failed
|
|
||||||
|
|
||||||
- name: Upgrade helm release (with reset_then_reuse_values=true)
|
|
||||||
kubernetes.core.helm:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
chart_ref: "{{ test_chart_path }}"
|
|
||||||
reuse_values: false
|
|
||||||
reset_then_reuse_values: true
|
|
||||||
release_name: "{{ test_release_name }}"
|
|
||||||
release_namespace: "{{ helm_namespace }}"
|
|
||||||
values:
|
|
||||||
ansible_version: test
|
|
||||||
register: helm_upgrade
|
|
||||||
ignore_errors: true
|
|
||||||
|
|
||||||
- name: Debug
|
|
||||||
debug:
|
|
||||||
var: helm_upgrade
|
|
||||||
|
|
||||||
- name: Ensure warning for Helm version
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- helm_upgrade is failed
|
|
||||||
- '"reset_then_reuse_values requires helm >= 3.14.0, current version is" in helm_upgrade.msg'
|
|
||||||
|
|
||||||
- name: Install helm diff
|
|
||||||
helm_plugin:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
state: present
|
|
||||||
plugin_path: https://github.com/databus23/helm-diff
|
|
||||||
plugin_version: "{{ helm_diff_old_version }}"
|
|
||||||
|
|
||||||
- name: Upgrade helm release (with reset_then_reuse_values=true)
|
|
||||||
kubernetes.core.helm:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
chart_ref: "{{ test_chart_path }}"
|
|
||||||
reuse_values: false
|
|
||||||
reset_then_reuse_values: true
|
|
||||||
release_name: "{{ test_release_name }}"
|
|
||||||
release_namespace: "{{ helm_namespace }}"
|
|
||||||
values:
|
|
||||||
ansible_version: devel
|
|
||||||
register: helm_upgrade
|
|
||||||
ignore_errors: true
|
|
||||||
|
|
||||||
- name: Debug
|
|
||||||
debug:
|
|
||||||
var: helm_upgrade
|
|
||||||
|
|
||||||
- name: Ensure warning for Helm Diff version
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- helm_upgrade is failed
|
|
||||||
- '"reset_then_reuse_values requires helm diff >= 3.9.12, current version is" in helm_upgrade.msg'
|
|
||||||
|
|
||||||
always:
|
|
||||||
- name: Remove temporary directory
|
|
||||||
file:
|
|
||||||
path: "{{ helm_dir.path }}"
|
|
||||||
state: absent
|
|
||||||
ignore_errors: true
|
|
||||||
|
|
||||||
- name: Uninstall helm diff
|
|
||||||
kubernetes.core.helm_plugin:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
state: absent
|
|
||||||
plugin_name: diff
|
|
||||||
ignore_errors: true
|
|
||||||
|
|
||||||
- name: Remove helm namespace
|
|
||||||
kubernetes.core.k8s:
|
|
||||||
api_version: v1
|
|
||||||
kind: Namespace
|
|
||||||
name: "{{ helm_namespace }}"
|
|
||||||
state: absent
|
|
||||||
wait: true
|
|
||||||
ignore_errors: true
|
|
||||||
@@ -90,5 +90,4 @@
|
|||||||
kind: Namespace
|
kind: Namespace
|
||||||
name: "{{ helm_namespace }}"
|
name: "{{ helm_namespace }}"
|
||||||
state: absent
|
state: absent
|
||||||
wait: true
|
|
||||||
ignore_errors: true
|
ignore_errors: true
|
||||||
|
|||||||
@@ -18,12 +18,7 @@
|
|||||||
- set_fact:
|
- set_fact:
|
||||||
saved_kubeconfig_path: "{{ _dir.path }}/config"
|
saved_kubeconfig_path: "{{ _dir.path }}/config"
|
||||||
|
|
||||||
- vars:
|
- block:
|
||||||
helm_repo_name: autoscaler
|
|
||||||
helm_repo_url: "https://kubernetes.github.io/autoscaler"
|
|
||||||
helm_release_name: "autoscaler"
|
|
||||||
helm_chart_name: "cluster-autoscaler"
|
|
||||||
block:
|
|
||||||
- name: Copy default kubeconfig
|
- name: Copy default kubeconfig
|
||||||
copy:
|
copy:
|
||||||
remote_src: true
|
remote_src: true
|
||||||
@@ -64,14 +59,14 @@
|
|||||||
- plugin_info.plugin_list != []
|
- plugin_info.plugin_list != []
|
||||||
|
|
||||||
# helm_repository, helm, helm_info
|
# helm_repository, helm, helm_info
|
||||||
- name: 'Add "{{ helm_repo_name }}" chart repository'
|
- name: Add test_bitnami chart repository
|
||||||
helm_repository:
|
helm_repository:
|
||||||
binary_path: "{{ helm_binary }}"
|
binary_path: "{{ helm_binary }}"
|
||||||
name: "{{ helm_repo_name }}"
|
name: test_bitnami
|
||||||
kubeconfig: "{{ test_kubeconfig | default(omit) }}"
|
kubeconfig: "{{ test_kubeconfig | default(omit) }}"
|
||||||
validate_certs: "{{ test_validate_certs | default(omit) }}"
|
validate_certs: "{{ test_validate_certs | default(omit) }}"
|
||||||
ca_cert: "{{ test_ca_cert | default(omit) }}"
|
ca_cert: "{{ test_ca_cert | default(omit) }}"
|
||||||
repo_url: "{{ helm_repo_url }}"
|
repo_url: https://charts.bitnami.com/bitnami
|
||||||
register: repository
|
register: repository
|
||||||
|
|
||||||
- name: Assert that repository was added
|
- name: Assert that repository was added
|
||||||
@@ -82,8 +77,8 @@
|
|||||||
- name: Install chart from repository added before
|
- name: Install chart from repository added before
|
||||||
helm:
|
helm:
|
||||||
binary_path: "{{ helm_binary }}"
|
binary_path: "{{ helm_binary }}"
|
||||||
name: "{{ helm_release_name }}"
|
name: rabbitmq
|
||||||
chart_ref: "{{ helm_repo_name }}/{{ helm_chart_name }}"
|
chart_ref: test_bitnami/rabbitmq
|
||||||
namespace: "{{ helm_namespace }}"
|
namespace: "{{ helm_namespace }}"
|
||||||
update_repo_cache: true
|
update_repo_cache: true
|
||||||
kubeconfig: "{{ test_kubeconfig | default(omit) }}"
|
kubeconfig: "{{ test_kubeconfig | default(omit) }}"
|
||||||
@@ -103,7 +98,7 @@
|
|||||||
kubeconfig: "{{ test_kubeconfig | default(omit) }}"
|
kubeconfig: "{{ test_kubeconfig | default(omit) }}"
|
||||||
validate_certs: "{{ test_validate_certs | default(omit) }}"
|
validate_certs: "{{ test_validate_certs | default(omit) }}"
|
||||||
ca_cert: "{{ test_ca_cert | default(omit) }}"
|
ca_cert: "{{ test_ca_cert | default(omit) }}"
|
||||||
name: "{{ helm_release_name }}"
|
name: "rabbitmq"
|
||||||
namespace: "{{ helm_namespace }}"
|
namespace: "{{ helm_namespace }}"
|
||||||
register: chart_info
|
register: chart_info
|
||||||
|
|
||||||
@@ -117,7 +112,7 @@
|
|||||||
- name: Remove chart
|
- name: Remove chart
|
||||||
helm:
|
helm:
|
||||||
binary_path: "{{ helm_binary }}"
|
binary_path: "{{ helm_binary }}"
|
||||||
name: "{{ helm_release_name }}"
|
name: rabbitmq
|
||||||
namespace: "{{ helm_namespace }}"
|
namespace: "{{ helm_namespace }}"
|
||||||
kubeconfig: "{{ test_kubeconfig | default(omit) }}"
|
kubeconfig: "{{ test_kubeconfig | default(omit) }}"
|
||||||
validate_certs: "{{ test_validate_certs | default(omit) }}"
|
validate_certs: "{{ test_validate_certs | default(omit) }}"
|
||||||
@@ -136,7 +131,7 @@
|
|||||||
kubeconfig: "{{ test_kubeconfig | default(omit) }}"
|
kubeconfig: "{{ test_kubeconfig | default(omit) }}"
|
||||||
validate_certs: "{{ test_validate_certs | default(omit) }}"
|
validate_certs: "{{ test_validate_certs | default(omit) }}"
|
||||||
ca_cert: "{{ test_ca_cert | default(omit) }}"
|
ca_cert: "{{ test_ca_cert | default(omit) }}"
|
||||||
name: "{{ helm_release_name }}"
|
name: "rabbitmq"
|
||||||
namespace: "{{ helm_namespace }}"
|
namespace: "{{ helm_namespace }}"
|
||||||
register: chart_info
|
register: chart_info
|
||||||
|
|
||||||
@@ -148,7 +143,7 @@
|
|||||||
- name: Remove chart repository
|
- name: Remove chart repository
|
||||||
helm_repository:
|
helm_repository:
|
||||||
binary_path: "{{ helm_binary }}"
|
binary_path: "{{ helm_binary }}"
|
||||||
name: "{{ helm_repo_name }}"
|
name: test_bitnami
|
||||||
kubeconfig: "{{ test_kubeconfig | default(omit) }}"
|
kubeconfig: "{{ test_kubeconfig | default(omit) }}"
|
||||||
validate_certs: "{{ test_validate_certs | default(omit) }}"
|
validate_certs: "{{ test_validate_certs | default(omit) }}"
|
||||||
ca_cert: "{{ test_ca_cert | default(omit) }}"
|
ca_cert: "{{ test_ca_cert | default(omit) }}"
|
||||||
@@ -197,6 +192,6 @@
|
|||||||
- name: Delete helm repository
|
- name: Delete helm repository
|
||||||
helm_repository:
|
helm_repository:
|
||||||
binary_path: "{{ helm_binary }}"
|
binary_path: "{{ helm_binary }}"
|
||||||
name: "{{ helm_repo_name }}"
|
name: test_bitnami
|
||||||
state: absent
|
state: absent
|
||||||
ignore_errors: true
|
ignore_errors: true
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- _result is failed
|
- _result is failed
|
||||||
- _result.msg == "Helm version must be >=3.0.0,<4.0.0, current version is 2.3.0"
|
- _result.msg == "This module requires helm >= 3.0.0, current version is 2.3.0"
|
||||||
|
|
||||||
vars:
|
vars:
|
||||||
helm_path: "{{ temp_dir }}/2.3.0/linux-amd64/helm"
|
helm_path: "{{ temp_dir }}/2.3.0/linux-amd64/helm"
|
||||||
@@ -180,7 +180,6 @@
|
|||||||
- '"--username ansible" in _result.command'
|
- '"--username ansible" in _result.command'
|
||||||
- '"--password ***" in _result.command'
|
- '"--password ***" in _result.command'
|
||||||
- '"--keyring pubring.gpg" in _result.command'
|
- '"--keyring pubring.gpg" in _result.command'
|
||||||
- '"Module did not set no_log for pass_credentials" not in _result.stderr'
|
|
||||||
|
|
||||||
- name: Download chart using chart_ref
|
- name: Download chart using chart_ref
|
||||||
helm_pull:
|
helm_pull:
|
||||||
@@ -204,8 +203,9 @@
|
|||||||
- name: Download chart using untar_chart
|
- name: Download chart using untar_chart
|
||||||
helm_pull:
|
helm_pull:
|
||||||
binary_path: "{{ helm_path }}"
|
binary_path: "{{ helm_path }}"
|
||||||
chart_ref: "oci://registry-1.docker.io/bitnamicharts/redis"
|
chart_ref: redis
|
||||||
destination: "{{ destination }}"
|
destination: "{{ destination }}"
|
||||||
|
repo_url: "https://charts.bitnami.com/bitnami"
|
||||||
untar_chart: true
|
untar_chart: true
|
||||||
register: _result
|
register: _result
|
||||||
|
|
||||||
@@ -221,101 +221,6 @@
|
|||||||
- _chart.stat.exists
|
- _chart.stat.exists
|
||||||
- _chart.stat.isdir
|
- _chart.stat.isdir
|
||||||
|
|
||||||
# Test idempotency with tarred chart
|
|
||||||
- name: Download chart with version (first time)
|
|
||||||
helm_pull:
|
|
||||||
binary_path: "{{ helm_path }}"
|
|
||||||
chart_ref: "oci://registry-1.docker.io/bitnamicharts/redis"
|
|
||||||
destination: "{{ destination }}"
|
|
||||||
chart_version: "24.1.0"
|
|
||||||
register: _result_first
|
|
||||||
|
|
||||||
- name: Download chart with version (second time - should be idempotent)
|
|
||||||
helm_pull:
|
|
||||||
binary_path: "{{ helm_path }}"
|
|
||||||
chart_ref: "oci://registry-1.docker.io/bitnamicharts/redis"
|
|
||||||
destination: "{{ destination }}"
|
|
||||||
chart_version: "24.1.0"
|
|
||||||
register: _result_second
|
|
||||||
|
|
||||||
- name: Validate idempotency for tarred chart
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- _result_first is changed
|
|
||||||
- _result_second is not changed
|
|
||||||
|
|
||||||
# Test force parameter with tarred chart
|
|
||||||
- name: Download chart with force=true (should always download)
|
|
||||||
helm_pull:
|
|
||||||
binary_path: "{{ helm_path }}"
|
|
||||||
chart_ref: "oci://registry-1.docker.io/bitnamicharts/redis"
|
|
||||||
destination: "{{ destination }}"
|
|
||||||
chart_version: "24.1.0"
|
|
||||||
force: true
|
|
||||||
register: _result_force
|
|
||||||
|
|
||||||
- name: Validate force parameter causes download
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- _result_force is changed
|
|
||||||
|
|
||||||
# Test idempotency with untarred chart in the separate folder
|
|
||||||
- name: Create separate directory for untar test under {{ temp_dir }}
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: "{{ destination }}/untar_test"
|
|
||||||
state: directory
|
|
||||||
mode: '0755'
|
|
||||||
|
|
||||||
- name: Download and untar chart (first time)
|
|
||||||
helm_pull:
|
|
||||||
binary_path: "{{ helm_path }}"
|
|
||||||
chart_ref: "oci://registry-1.docker.io/bitnamicharts/redis"
|
|
||||||
destination: "{{ destination }}/untar_test"
|
|
||||||
chart_version: "24.0.0"
|
|
||||||
untar_chart: true
|
|
||||||
register: _result_untar_first
|
|
||||||
|
|
||||||
- name: Download and untar chart (second time - should be idempotent)
|
|
||||||
helm_pull:
|
|
||||||
binary_path: "{{ helm_path }}"
|
|
||||||
chart_ref: "oci://registry-1.docker.io/bitnamicharts/redis"
|
|
||||||
destination: "{{ destination }}/untar_test"
|
|
||||||
chart_version: "24.0.0"
|
|
||||||
untar_chart: true
|
|
||||||
register: _result_untar_second
|
|
||||||
|
|
||||||
- name: Validate idempotency for untarred chart
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- _result_untar_first is changed
|
|
||||||
- _result_untar_second is not changed
|
|
||||||
|
|
||||||
- name: Download and untar chart with force=true (should remove existing directory and re-extract)
|
|
||||||
helm_pull:
|
|
||||||
binary_path: "{{ helm_path }}"
|
|
||||||
chart_ref: "oci://registry-1.docker.io/bitnamicharts/redis"
|
|
||||||
destination: "{{ destination }}/untar_test"
|
|
||||||
chart_version: "24.0.0"
|
|
||||||
untar_chart: true
|
|
||||||
force: true
|
|
||||||
register: _result_untar_force
|
|
||||||
|
|
||||||
- name: Validate first force extraction works
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- _result_untar_force is changed
|
|
||||||
|
|
||||||
- name: Verify chart directory still exists after force re-extraction
|
|
||||||
stat:
|
|
||||||
path: "{{ destination }}/untar_test/redis"
|
|
||||||
register: _chart_after_force
|
|
||||||
|
|
||||||
- name: Validate chart directory exists
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- _chart_after_force.stat.exists
|
|
||||||
- _chart_after_force.stat.isdir
|
|
||||||
|
|
||||||
vars:
|
vars:
|
||||||
helm_path: "{{ temp_dir }}/3.8.0/linux-amd64/helm"
|
helm_path: "{{ temp_dir }}/3.8.0/linux-amd64/helm"
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
time=16
|
|
||||||
helm_registry_auth
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
---
|
|
||||||
# Username and password for the registry
|
|
||||||
# ../files/registry.password contains username and hashed password
|
|
||||||
username: testuser
|
|
||||||
password: testpassword
|
|
||||||
wrong_password: 'WrongPassword'
|
|
||||||
registry_name: oci_registry
|
|
||||||
registry_port: 5000
|
|
||||||
test_chart: https://github.com/grafana/helm-charts/releases/download/k8s-monitoring-1.6.8/k8s-monitoring-1.6.8.tgz
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
testuser:$2y$05$PmdUjSCJYdRUZlsYy8QGWuJDiwuHtWXa28YrELlN5haeHkZ1seZZG
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
---
|
|
||||||
dependencies:
|
|
||||||
- install_helm
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Test helm_registry_auth module
|
|
||||||
hosts: localhost
|
|
||||||
connection: local
|
|
||||||
gather_facts: true
|
|
||||||
roles:
|
|
||||||
- helm_registry_auth
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -eux
|
|
||||||
export ANSIBLE_CALLBACKS_ENABLED=profile_tasks
|
|
||||||
export ANSIBLE_ROLES_PATH=../
|
|
||||||
ansible-playbook playbook.yaml "$@"
|
|
||||||
@@ -1,182 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Run module test
|
|
||||||
# using a shell and command module to run the test as test can be non-idempotent
|
|
||||||
# and it allow to not install any additional dependencies
|
|
||||||
block:
|
|
||||||
- name: Ensure that helm is installed
|
|
||||||
ansible.builtin.shell: helm version --client --short | grep v3
|
|
||||||
register: _helm_version
|
|
||||||
failed_when: _helm_version.rc != 0
|
|
||||||
|
|
||||||
- name: Ensure that Docker demon is running
|
|
||||||
ansible.builtin.command: "docker info"
|
|
||||||
register: _docker_info
|
|
||||||
failed_when: _docker_info.rc != 0
|
|
||||||
|
|
||||||
- name: Create a tmpfile htpasswd directory
|
|
||||||
ansible.builtin.tempfile:
|
|
||||||
state: directory
|
|
||||||
suffix: .httppasswd
|
|
||||||
register: _tmpfile
|
|
||||||
|
|
||||||
- name: Copy htpasswd to the tmpfile directory
|
|
||||||
ansible.builtin.copy:
|
|
||||||
src: registry.password
|
|
||||||
dest: "{{ _tmpfile.path }}/registry.password"
|
|
||||||
|
|
||||||
- name: Setup the registry
|
|
||||||
ansible.builtin.command: >-
|
|
||||||
docker run -d --rm
|
|
||||||
-p {{ registry_port }}:5000
|
|
||||||
--name "{{ registry_name }}"
|
|
||||||
-v "{{ _tmpfile.path }}:/auth"
|
|
||||||
-e "REGISTRY_AUTH=htpasswd"
|
|
||||||
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm"
|
|
||||||
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/registry.password
|
|
||||||
registry:2
|
|
||||||
register: _setup_registry
|
|
||||||
failed_when: _setup_registry.rc != 0
|
|
||||||
|
|
||||||
- name: Ensure that the registry is running and rechable
|
|
||||||
ansible.builtin.wait_for:
|
|
||||||
host: localhost
|
|
||||||
port: "{{ registry_port }}"
|
|
||||||
|
|
||||||
- name: Test the registry with correct credentials to ensure that the registry is running
|
|
||||||
ansible.builtin.shell: >-
|
|
||||||
echo {{ password | quote }} | helm registry login localhost:{{ registry_port }}
|
|
||||||
-u {{ username }} --password-stdin
|
|
||||||
register: _login_correct
|
|
||||||
failed_when: _login_correct.rc != 0
|
|
||||||
|
|
||||||
- name: Clean up credentials to run test on clean environment
|
|
||||||
ansible.builtin.shell: >-
|
|
||||||
helm registry logout localhost:{{ registry_port }}
|
|
||||||
register: _logout
|
|
||||||
failed_when: _logout.rc != 0
|
|
||||||
|
|
||||||
- name: Create directory for helm chart
|
|
||||||
ansible.builtin.tempfile:
|
|
||||||
state: directory
|
|
||||||
suffix: ".helm"
|
|
||||||
register: _destination
|
|
||||||
|
|
||||||
- name: Pull test helm chart
|
|
||||||
ansible.builtin.uri:
|
|
||||||
url: "{{ test_chart }}"
|
|
||||||
dest: "{{ _destination.path }}/k8s-monitoring-1.6.8.tgz"
|
|
||||||
return_content: no
|
|
||||||
status_code: 200
|
|
||||||
|
|
||||||
- name: Test module helm_registry_auth with correct credentials
|
|
||||||
helm_registry_auth:
|
|
||||||
username: "{{ username }}"
|
|
||||||
password: "{{ password }}"
|
|
||||||
host: localhost:{{ registry_port }}
|
|
||||||
state: present
|
|
||||||
register: _helm_registry_auth_correct
|
|
||||||
|
|
||||||
- name: Assert that the registry is logged in
|
|
||||||
# Helm binary prints the message to stderr, refence: https://github.com/helm/helm/issues/13464
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- "'Login Succeeded' in _helm_registry_auth_correct.stderr"
|
|
||||||
- "'{{ password }}' not in _helm_registry_auth_correct.command"
|
|
||||||
- "'{{ password }}' not in _helm_registry_auth_correct.stdout"
|
|
||||||
- "'{{ password }}' not in _helm_registry_auth_correct.stderr"
|
|
||||||
|
|
||||||
- name: Ensure that push to the registry is working
|
|
||||||
ansible.builtin.shell: >-
|
|
||||||
helm push "{{ _destination.path }}/k8s-monitoring-1.6.8.tgz" oci://localhost:{{ registry_port }}/test/
|
|
||||||
register: _save_chart
|
|
||||||
failed_when: _save_chart.rc != 0
|
|
||||||
|
|
||||||
- name: Assert that the chart is saved
|
|
||||||
# Helm binary prints the message to stderr, refence: https://github.com/helm/helm/issues/13464
|
|
||||||
assert:
|
|
||||||
that: "'Pushed: localhost:{{ registry_port }}/test/k8s-monitoring' in _save_chart.stderr"
|
|
||||||
|
|
||||||
|
|
||||||
- name: Test logout
|
|
||||||
helm_registry_auth:
|
|
||||||
host: localhost:{{ registry_port }}
|
|
||||||
state: absent
|
|
||||||
register: _helm_registry_auth_logout
|
|
||||||
|
|
||||||
- name: Assert logout
|
|
||||||
# Helm binary prints the message to stderr
|
|
||||||
assert:
|
|
||||||
that: "'Removing login credentials' in _helm_registry_auth_logout.stderr"
|
|
||||||
|
|
||||||
- name: Test 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
|
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
---
|
---
|
||||||
collections:
|
|
||||||
- kubernetes.core
|
|
||||||
dependencies:
|
dependencies:
|
||||||
- install_helm
|
- install_helm
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- repository is changed
|
- repository is changed
|
||||||
- '"--insecure-skip-tls-verify" not in repository.command'
|
|
||||||
|
|
||||||
- name: Check idempotency
|
- name: Check idempotency
|
||||||
helm_repository:
|
helm_repository:
|
||||||
@@ -79,23 +78,3 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- repository is not changed
|
- repository is not changed
|
||||||
|
|
||||||
- name: Add test_helm_repo chart repository as insecure
|
|
||||||
helm_repository:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
name: test_helm_repo
|
|
||||||
repo_url: "{{ chart_test_repo }}"
|
|
||||||
insecure_skip_tls_verify: true
|
|
||||||
register: repository
|
|
||||||
|
|
||||||
- name: Assert that repository added and flag set
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- repository is changed
|
|
||||||
- '"--insecure-skip-tls-verify" in repository.command'
|
|
||||||
|
|
||||||
- name: Clean test_helm_repo chart repository
|
|
||||||
helm_repository:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
name: test_helm_repo
|
|
||||||
state: absent
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
- name: Install helm using set_values parameters
|
- name: Install helm using set_values parameters
|
||||||
helm:
|
helm:
|
||||||
binary_path: "{{ helm_binary }}"
|
binary_path: "{{ helm_binary }}"
|
||||||
chart_ref: oci://registry-1.docker.io/bitnamicharts/mariadb
|
chart_ref: mariadb
|
||||||
|
chart_repo_url: https://charts.bitnami.com/bitnami
|
||||||
release_name: test-mariadb
|
release_name: test-mariadb
|
||||||
release_namespace: "{{ helm_namespace }}"
|
release_namespace: "{{ helm_namespace }}"
|
||||||
create_namespace: true
|
create_namespace: true
|
||||||
@@ -20,10 +21,10 @@
|
|||||||
- name: Assert that release was created with user-defined variables
|
- name: Assert that release was created with user-defined variables
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- '"phase" in user_values.status["release_values"]'
|
- '"phase" in user_values.status["values"]'
|
||||||
- '"versioned" in user_values.status["release_values"]'
|
- '"versioned" in user_values.status["values"]'
|
||||||
- user_values.status["release_values"]["phase"] == "integration"
|
- user_values.status["values"]["phase"] == "integration"
|
||||||
- user_values.status["release_values"]["versioned"] is false
|
- user_values.status["values"]["versioned"] is false
|
||||||
|
|
||||||
# install chart using set_values and release_values
|
# install chart using set_values and release_values
|
||||||
- name: Install helm binary (> 3.10.0) requires to use set-json
|
- name: Install helm binary (> 3.10.0) requires to use set-json
|
||||||
@@ -35,7 +36,8 @@
|
|||||||
- name: Install helm using set_values parameters
|
- name: Install helm using set_values parameters
|
||||||
helm:
|
helm:
|
||||||
binary_path: "{{ helm_binary }}"
|
binary_path: "{{ helm_binary }}"
|
||||||
chart_ref: oci://registry-1.docker.io/bitnamicharts/apache
|
chart_ref: apache
|
||||||
|
chart_repo_url: https://charts.bitnami.com/bitnami
|
||||||
release_name: test-apache
|
release_name: test-apache
|
||||||
release_namespace: "{{ helm_namespace }}"
|
release_namespace: "{{ helm_namespace }}"
|
||||||
create_namespace: true
|
create_namespace: true
|
||||||
@@ -55,10 +57,10 @@
|
|||||||
- name: Assert that release was created with user-defined variables
|
- name: Assert that release was created with user-defined variables
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- values.status["release_values"].replicaCount == 3
|
- values.status["values"].replicaCount == 3
|
||||||
- values.status["release_values"].master.image.registry == "docker.io"
|
- values.status["values"].master.image.registry == "docker.io"
|
||||||
- values.status["release_values"].master.image.repository == "bitnami/apache"
|
- values.status["values"].master.image.repository == "bitnami/apache"
|
||||||
- values.status["release_values"].master.image.tag == "2.4.54-debian-11-r74"
|
- values.status["values"].master.image.tag == "2.4.54-debian-11-r74"
|
||||||
|
|
||||||
# install chart using set_values and values_files
|
# install chart using set_values and values_files
|
||||||
- name: create temporary file to save values in
|
- name: create temporary file to save values in
|
||||||
@@ -77,7 +79,8 @@
|
|||||||
- name: Install helm using set_values parameters
|
- name: Install helm using set_values parameters
|
||||||
helm:
|
helm:
|
||||||
binary_path: "{{ helm_binary }}"
|
binary_path: "{{ helm_binary }}"
|
||||||
chart_ref: oci://registry-1.docker.io/bitnamicharts/minio
|
chart_ref: minio
|
||||||
|
chart_repo_url: https://charts.bitnami.com/bitnami
|
||||||
release_name: test-minio
|
release_name: test-minio
|
||||||
release_namespace: "{{ helm_namespace }}"
|
release_namespace: "{{ helm_namespace }}"
|
||||||
create_namespace: true
|
create_namespace: true
|
||||||
@@ -96,19 +99,11 @@
|
|||||||
- name: Assert that release was created with user-defined variables
|
- name: Assert that release was created with user-defined variables
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- values.status["release_values"].mode == "distributed"
|
- values.status["values"].mode == "distributed"
|
||||||
- values.status["release_values"].disableWebUI is true
|
- values.status["values"].disableWebUI is true
|
||||||
|
|
||||||
always:
|
always:
|
||||||
- name: Delete temporary file
|
- name: Delete temporary file
|
||||||
file:
|
file:
|
||||||
state: absent
|
state: absent
|
||||||
path: "{{ ymlfile.path }}"
|
path: "{{ ymlfile.path }}"
|
||||||
ignore_errors: true
|
|
||||||
|
|
||||||
- name: Delete namespace
|
|
||||||
k8s:
|
|
||||||
state: absent
|
|
||||||
kind: namespace
|
|
||||||
name: "{{ helm_namespace }}"
|
|
||||||
ignore_errors: true
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
---
|
---
|
||||||
helm_version: v3.16.4
|
helm_version: v3.7.0
|
||||||
helm_install_path: /tmp/helm
|
helm_install_path: /tmp/helm
|
||||||
helm_default_archive_name: "helm-{{ helm_version }}-{{ ansible_system | lower }}-amd64.tar.gz"
|
helm_default_archive_name: "helm-{{ helm_version }}-{{ ansible_system | lower }}-amd64.tar.gz"
|
||||||
|
|||||||
@@ -1,4 +1,42 @@
|
|||||||
---
|
---
|
||||||
|
k8s_pod_metadata:
|
||||||
|
labels:
|
||||||
|
app: "{{ k8s_pod_name }}"
|
||||||
|
|
||||||
|
k8s_pod_spec:
|
||||||
|
serviceAccount: "{{ k8s_pod_service_account }}"
|
||||||
|
containers:
|
||||||
|
- image: "{{ k8s_pod_image }}"
|
||||||
|
imagePullPolicy: Always
|
||||||
|
name: "{{ k8s_pod_name }}"
|
||||||
|
command: "{{ k8s_pod_command }}"
|
||||||
|
readinessProbe:
|
||||||
|
initialDelaySeconds: 15
|
||||||
|
exec:
|
||||||
|
command:
|
||||||
|
- /bin/true
|
||||||
|
resources: "{{ k8s_pod_resources }}"
|
||||||
|
ports: "{{ k8s_pod_ports }}"
|
||||||
|
env: "{{ k8s_pod_env }}"
|
||||||
|
|
||||||
|
|
||||||
|
k8s_pod_service_account: default
|
||||||
|
|
||||||
|
k8s_pod_resources:
|
||||||
|
limits:
|
||||||
|
cpu: "100m"
|
||||||
|
memory: "100Mi"
|
||||||
|
|
||||||
|
k8s_pod_command: []
|
||||||
|
|
||||||
|
k8s_pod_ports: []
|
||||||
|
|
||||||
|
k8s_pod_env: []
|
||||||
|
|
||||||
|
k8s_pod_template:
|
||||||
|
metadata: "{{ k8s_pod_metadata }}"
|
||||||
|
spec: "{{ k8s_pod_spec }}"
|
||||||
|
|
||||||
test_namespace: "apply"
|
test_namespace: "apply"
|
||||||
|
|
||||||
k8s_wait_timeout: 240
|
k8s_wait_timeout: 240
|
||||||
|
|||||||
@@ -26,8 +26,7 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- k8s_configmap is changed
|
- k8s_configmap is changed
|
||||||
- '"annotations" in k8s_configmap.result.metadata'
|
- k8s_configmap.result.metadata.annotations|default(False)
|
||||||
- k8s_configmap.result.metadata.annotations != {}
|
|
||||||
|
|
||||||
- name: Add same configmap again
|
- name: Add same configmap again
|
||||||
k8s:
|
k8s:
|
||||||
@@ -292,34 +291,36 @@
|
|||||||
|
|
||||||
- name: Add a deployment
|
- name: Add a deployment
|
||||||
k8s:
|
k8s:
|
||||||
namespace: "{{ test_namespace }}"
|
|
||||||
definition:
|
definition:
|
||||||
definition:
|
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: apply-deploy
|
name: apply-deploy
|
||||||
labels:
|
namespace: "{{ test_namespace }}"
|
||||||
app: apply-deploy
|
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: apply-deploy
|
app: "{{ k8s_pod_name }}"
|
||||||
template:
|
template: "{{ k8s_pod_template }}"
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: apply-deploy
|
|
||||||
spec:
|
|
||||||
serviceAccount: apply-deploy
|
|
||||||
containers:
|
|
||||||
- name: nginx
|
|
||||||
image: nginx:latest
|
|
||||||
ports:
|
|
||||||
- containerPort: 80
|
|
||||||
wait: yes
|
wait: yes
|
||||||
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
||||||
apply: yes
|
apply: yes
|
||||||
|
vars:
|
||||||
|
k8s_pod_name: apply-deploy
|
||||||
|
k8s_pod_image: gcr.io/kuar-demo/kuard-amd64:v0.10.0-green
|
||||||
|
k8s_pod_service_account: apply-deploy
|
||||||
|
k8s_pod_ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
name: http
|
||||||
|
protocol: TCP
|
||||||
|
k8s_pod_resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 100Mi
|
||||||
|
limits:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 100Mi
|
||||||
|
|
||||||
- name: Update the earlier deployment in check mode
|
- name: Update the earlier deployment in check mode
|
||||||
k8s:
|
k8s:
|
||||||
@@ -333,29 +334,33 @@
|
|||||||
replicas: 1
|
replicas: 1
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: apply-deploy
|
app: "{{ k8s_pod_name }}"
|
||||||
template:
|
template: "{{ k8s_pod_template }}"
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: apply-deploy
|
|
||||||
spec:
|
|
||||||
serviceAccount: apply-deploy
|
|
||||||
containers:
|
|
||||||
- name: nginx-2
|
|
||||||
image: nginx:latest
|
|
||||||
ports:
|
|
||||||
- containerPort: 80
|
|
||||||
wait: yes
|
wait: yes
|
||||||
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
||||||
apply: yes
|
apply: yes
|
||||||
check_mode: yes
|
check_mode: yes
|
||||||
|
vars:
|
||||||
|
k8s_pod_name: apply-deploy
|
||||||
|
k8s_pod_image: gcr.io/kuar-demo/kuard-amd64:v0.10.0-purple
|
||||||
|
k8s_pod_service_account: apply-deploy
|
||||||
|
k8s_pod_ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
name: http
|
||||||
|
protocol: TCP
|
||||||
|
k8s_pod_resources:
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
limits:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 50Mi
|
||||||
register: update_deploy_check_mode
|
register: update_deploy_check_mode
|
||||||
|
|
||||||
- name: Ensure check mode change took
|
- name: Ensure check mode change took
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- update_deploy_check_mode is changed
|
- update_deploy_check_mode is changed
|
||||||
- "update_deploy_check_mode.result.spec.template.spec.containers[0].name == 'nginx-2'"
|
- "update_deploy_check_mode.result.spec.template.spec.containers[0].image == 'gcr.io/kuar-demo/kuard-amd64:v0.10.0-purple'"
|
||||||
|
|
||||||
- name: Update the earlier deployment
|
- name: Update the earlier deployment
|
||||||
k8s:
|
k8s:
|
||||||
@@ -369,28 +374,32 @@
|
|||||||
replicas: 1
|
replicas: 1
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: apply-deploy
|
app: "{{ k8s_pod_name }}"
|
||||||
template:
|
template: "{{ k8s_pod_template }}"
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: apply-deploy
|
|
||||||
spec:
|
|
||||||
serviceAccount: apply-deploy
|
|
||||||
containers:
|
|
||||||
- name: nginx-2
|
|
||||||
image: nginx:latest
|
|
||||||
ports:
|
|
||||||
- containerPort: 80
|
|
||||||
wait: yes
|
wait: yes
|
||||||
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
||||||
apply: yes
|
apply: yes
|
||||||
|
vars:
|
||||||
|
k8s_pod_name: apply-deploy
|
||||||
|
k8s_pod_image: gcr.io/kuar-demo/kuard-amd64:v0.10.0-purple
|
||||||
|
k8s_pod_service_account: apply-deploy
|
||||||
|
k8s_pod_ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
name: http
|
||||||
|
protocol: TCP
|
||||||
|
k8s_pod_resources:
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
limits:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 50Mi
|
||||||
register: update_deploy_for_real
|
register: update_deploy_for_real
|
||||||
|
|
||||||
- name: Ensure change took
|
- name: Ensure change took
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- update_deploy_for_real is changed
|
- update_deploy_for_real is changed
|
||||||
- "update_deploy_for_real.result.spec.template.spec.containers[0].name == 'nginx-2'"
|
- "update_deploy_for_real.result.spec.template.spec.containers[0].image == 'gcr.io/kuar-demo/kuard-amd64:v0.10.0-purple'"
|
||||||
|
|
||||||
- name: Remove the serviceaccount
|
- name: Remove the serviceaccount
|
||||||
k8s:
|
k8s:
|
||||||
@@ -414,23 +423,27 @@
|
|||||||
replicas: 1
|
replicas: 1
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: apply-deploy
|
app: "{{ k8s_pod_name }}"
|
||||||
template:
|
template: "{{ k8s_pod_template }}"
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: apply-deploy
|
|
||||||
spec:
|
|
||||||
serviceAccount: apply-deploy
|
|
||||||
containers:
|
|
||||||
- name: nginx-3
|
|
||||||
image: nginx:latest
|
|
||||||
ports:
|
|
||||||
- containerPort: 80
|
|
||||||
wait: yes
|
wait: yes
|
||||||
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
||||||
apply: yes
|
apply: yes
|
||||||
ignore_errors: true
|
vars:
|
||||||
|
k8s_pod_name: apply-deploy
|
||||||
|
k8s_pod_image: gcr.io/kuar-demo/kuard-amd64:v0.10.0-green
|
||||||
|
k8s_pod_service_account: apply-deploy
|
||||||
|
k8s_pod_ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
name: http
|
||||||
|
protocol: TCP
|
||||||
|
k8s_pod_resources:
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
limits:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 50Mi
|
||||||
register: deploy_after_serviceaccount_removal
|
register: deploy_after_serviceaccount_removal
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
- name: Ensure that updating deployment after service account removal failed
|
- name: Ensure that updating deployment after service account removal failed
|
||||||
assert:
|
assert:
|
||||||
@@ -454,7 +467,7 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- k8s_secret is changed
|
- k8s_secret is changed
|
||||||
- k8s_secret.result.data.foo != ""
|
- k8s_secret.result.data.foo
|
||||||
|
|
||||||
- name: Add same secret
|
- name: Add same secret
|
||||||
k8s:
|
k8s:
|
||||||
@@ -735,7 +748,7 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- _create is changed
|
- _create is changed
|
||||||
- _info.resources | length == 0
|
- not _info.resources
|
||||||
|
|
||||||
# server side apply over kubernetes client releases
|
# server side apply over kubernetes client releases
|
||||||
- name: Create temporary directory
|
- name: Create temporary directory
|
||||||
|
|||||||
@@ -14,9 +14,3 @@ pod_with_two_container:
|
|||||||
|
|
||||||
pod_without_executable_find:
|
pod_without_executable_find:
|
||||||
name: openjdk-pod
|
name: openjdk-pod
|
||||||
|
|
||||||
pod_with_initcontainer_and_container:
|
|
||||||
name: pod-copy-2
|
|
||||||
container:
|
|
||||||
- container-20
|
|
||||||
- container-21
|
|
||||||
|
|||||||
@@ -18,23 +18,6 @@
|
|||||||
wait: yes
|
wait: yes
|
||||||
template: pods_definition.j2
|
template: pods_definition.j2
|
||||||
|
|
||||||
- name: Create Init Pod
|
|
||||||
k8s:
|
|
||||||
namespace: '{{ copy_namespace }}'
|
|
||||||
template: pods_definition_init.j2
|
|
||||||
|
|
||||||
- kubernetes.core.k8s_info:
|
|
||||||
api_version: v1
|
|
||||||
kind: Pod
|
|
||||||
name: '{{ pod_with_initcontainer_and_container.name }}'
|
|
||||||
namespace: '{{ copy_namespace }}'
|
|
||||||
register: init_pod_status
|
|
||||||
until: >-
|
|
||||||
init_pod_status.resources|length > 0
|
|
||||||
and 'initContainerStatuses' in init_pod_status.resources.0.status
|
|
||||||
and init_pod_status.resources.0.status.initContainerStatuses|length > 0
|
|
||||||
and init_pod_status.resources.0.status.initContainerStatuses.0.started|bool
|
|
||||||
|
|
||||||
- include_tasks: test_copy_errors.yml
|
- include_tasks: test_copy_errors.yml
|
||||||
- include_tasks: test_check_mode.yml
|
- include_tasks: test_check_mode.yml
|
||||||
- include_tasks: test_copy_file.yml
|
- include_tasks: test_copy_file.yml
|
||||||
@@ -42,7 +25,6 @@
|
|||||||
- include_tasks: test_copy_directory.yml
|
- include_tasks: test_copy_directory.yml
|
||||||
- include_tasks: test_copy_large_file.yml
|
- include_tasks: test_copy_large_file.yml
|
||||||
- include_tasks: test_copy_item_with_space_in_its_name.yml
|
- include_tasks: test_copy_item_with_space_in_its_name.yml
|
||||||
- include_tasks: test_init_container_pod.yml
|
|
||||||
|
|
||||||
always:
|
always:
|
||||||
|
|
||||||
|
|||||||
@@ -69,51 +69,49 @@
|
|||||||
ignore_errors: true
|
ignore_errors: true
|
||||||
register: _result
|
register: _result
|
||||||
|
|
||||||
# - name: Validate that 'find' executable is missing from Pod
|
- name: Validate that 'find' executable is missing from Pod
|
||||||
# assert:
|
assert:
|
||||||
# that:
|
that:
|
||||||
# - _result is failed
|
- _result is failed
|
||||||
# fail_msg: "Pod contains 'find' executable, therefore we cannot run the next tasks."
|
fail_msg: "Pod contains 'find' executable, therefore we cannot run the next tasks."
|
||||||
|
|
||||||
- name: Copy directory into Pod without 'find' executable
|
- name: Copy files into container
|
||||||
block:
|
k8s_cp:
|
||||||
- name: Copy files into container
|
namespace: "{{ copy_namespace }}"
|
||||||
k8s_cp:
|
pod: '{{ pod_without_executable_find.name }}'
|
||||||
namespace: "{{ copy_namespace }}"
|
remote_path: '{{ item.path }}'
|
||||||
pod: '{{ pod_without_executable_find.name }}'
|
content: '{{ item.content }}'
|
||||||
remote_path: '{{ item.path }}'
|
state: to_pod
|
||||||
content: '{{ item.content }}'
|
with_items:
|
||||||
state: to_pod
|
- path: /ansible/root.txt
|
||||||
with_items:
|
content: this file is located at the root directory
|
||||||
- path: /ansible/root.txt
|
- path: /ansible/.hidden_root.txt
|
||||||
content: this file is located at the root directory
|
content: this hidden file is located at the root directory
|
||||||
- path: /ansible/.hidden_root.txt
|
- path: /ansible/.sudir/root.txt
|
||||||
content: this hidden file is located at the root directory
|
content: this file is located at the root of the sub directory
|
||||||
- path: /ansible/.sudir/root.txt
|
- path: /ansible/.sudir/.hidden_root.txt
|
||||||
content: this file is located at the root of the sub directory
|
content: this hidden file is located at the root of the sub directory
|
||||||
- path: /ansible/.sudir/.hidden_root.txt
|
|
||||||
content: this hidden file is located at the root of the sub directory
|
|
||||||
|
|
||||||
- name: Delete existing directory
|
- name: Delete existing directory
|
||||||
file:
|
file:
|
||||||
path: /tmp/openjdk-files
|
path: /tmp/openjdk-files
|
||||||
state: absent
|
state: absent
|
||||||
ignore_errors: true
|
ignore_errors: true
|
||||||
|
|
||||||
- name: copy directory from Pod into local filesystem (new directory to create)
|
- name: copy directory from Pod into local filesystem (new directory to create)
|
||||||
k8s_cp:
|
k8s_cp:
|
||||||
namespace: '{{ copy_namespace }}'
|
namespace: '{{ copy_namespace }}'
|
||||||
pod: '{{ pod_without_executable_find.name }}'
|
pod: '{{ pod_without_executable_find.name }}'
|
||||||
remote_path: /ansible
|
remote_path: /ansible
|
||||||
local_path: /tmp/openjdk-files
|
local_path: /tmp/openjdk-files
|
||||||
state: from_pod
|
state: from_pod
|
||||||
|
|
||||||
- name: Compare directories
|
- name: Compare directories
|
||||||
kubectl_file_compare:
|
kubectl_file_compare:
|
||||||
namespace: '{{ copy_namespace }}'
|
namespace: '{{ copy_namespace }}'
|
||||||
pod: '{{ pod_without_executable_find.name }}'
|
pod: '{{ pod_without_executable_find.name }}'
|
||||||
remote_path: /ansible
|
remote_path: /ansible
|
||||||
local_path: /tmp/openjdk-files
|
local_path: /tmp/openjdk-files
|
||||||
|
|
||||||
always:
|
always:
|
||||||
- name: Remove directories created into remote Pod
|
- name: Remove directories created into remote Pod
|
||||||
|
|||||||
@@ -67,21 +67,3 @@
|
|||||||
that:
|
that:
|
||||||
- copy_fake_container is failed
|
- copy_fake_container is failed
|
||||||
- copy_fake_container.msg == "Pod has no container this_is_a_fake_container"
|
- copy_fake_container.msg == "Pod has no container this_is_a_fake_container"
|
||||||
|
|
||||||
# copy file to not started container in pod should fail
|
|
||||||
- name: copy file to not started container in pod should fail
|
|
||||||
k8s_cp:
|
|
||||||
namespace: '{{ copy_namespace }}'
|
|
||||||
pod: '{{ pod_with_initcontainer_and_container.name }}'
|
|
||||||
remote_path: /tmp
|
|
||||||
local_path: files/simple_file.txt
|
|
||||||
state: to_pod
|
|
||||||
container: '{{ pod_with_initcontainer_and_container.container[1] }}'
|
|
||||||
ignore_errors: true
|
|
||||||
register: copy_not_started_container
|
|
||||||
|
|
||||||
- name: check that error message is as expected
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- copy_not_started_container is failed
|
|
||||||
- copy_not_started_container.msg == "Pod container {{ pod_with_initcontainer_and_container.container[1] }} is not started"
|
|
||||||
|
|||||||
@@ -10,13 +10,9 @@
|
|||||||
path: "{{ test_directory }}"
|
path: "{{ test_directory }}"
|
||||||
state: directory
|
state: directory
|
||||||
|
|
||||||
- name: Create a text file with specific content
|
- name: Create a large text file
|
||||||
ansible.builtin.copy:
|
ansible.builtin.shell:
|
||||||
dest: "{{ test_directory }}/large_text_file.txt"
|
cmd: base64 /dev/random | head -c 150M > {{ test_directory }}/large_text_file.txt
|
||||||
content: |
|
|
||||||
This is a large text file
|
|
||||||
{{ 'Repeat this line 1000 times\n' * 1000 }}
|
|
||||||
mode: '0644'
|
|
||||||
|
|
||||||
- name: Create a large binary file
|
- name: Create a large binary file
|
||||||
ansible.builtin.command:
|
ansible.builtin.command:
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
---
|
|
||||||
- set_fact:
|
|
||||||
random_content: "{{ lookup('password', '/dev/null chars=ascii_lowercase,digits,punctuation length=128') }}"
|
|
||||||
|
|
||||||
- name: Copy content into init container
|
|
||||||
k8s_cp:
|
|
||||||
namespace: '{{ copy_namespace }}'
|
|
||||||
pod: '{{ pod_with_initcontainer_and_container.name }}'
|
|
||||||
remote_path: /file_from_localhost.txt
|
|
||||||
content: '{{ random_content }}'
|
|
||||||
container: '{{ pod_with_initcontainer_and_container.container[0] }}'
|
|
||||||
state: to_pod
|
|
||||||
|
|
||||||
- name: Get the content from copied file
|
|
||||||
kubernetes.core.k8s_exec:
|
|
||||||
namespace: '{{ copy_namespace }}'
|
|
||||||
pod: '{{ pod_with_initcontainer_and_container.name }}'
|
|
||||||
container: '{{ pod_with_initcontainer_and_container.container[0] }}'
|
|
||||||
command: cat /file_from_localhost.txt
|
|
||||||
register: exec_out
|
|
||||||
|
|
||||||
- name: check that content is found and the same as generated earlier
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- exec_out.stdout == random_content
|
|
||||||
@@ -6,7 +6,7 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: '{{ pod_with_one_container.container }}'
|
- name: '{{ pod_with_one_container.container }}'
|
||||||
image: busybox:latest
|
image: busybox
|
||||||
command:
|
command:
|
||||||
- /bin/sh
|
- /bin/sh
|
||||||
- -c
|
- -c
|
||||||
@@ -19,13 +19,13 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: '{{ pod_with_two_container.container[0] }}'
|
- name: '{{ pod_with_two_container.container[0] }}'
|
||||||
image: busybox:latest
|
image: busybox:1.32.0
|
||||||
command:
|
command:
|
||||||
- /bin/sh
|
- /bin/sh
|
||||||
- -c
|
- -c
|
||||||
- while true;do date;sleep 5; done
|
- while true;do date;sleep 5; done
|
||||||
- name: '{{ pod_with_two_container.container[1] }}'
|
- name: '{{ pod_with_two_container.container[1] }}'
|
||||||
image: busybox:latest
|
image: busybox:1.33.0
|
||||||
command:
|
command:
|
||||||
- /bin/sh
|
- /bin/sh
|
||||||
- -c
|
- -c
|
||||||
@@ -37,8 +37,8 @@ metadata:
|
|||||||
name: '{{ pod_without_executable_find.name }}'
|
name: '{{ pod_without_executable_find.name }}'
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: openjdk
|
- name: openjdk17
|
||||||
image: openjdk:27-ea
|
image: openjdk:17
|
||||||
command:
|
command:
|
||||||
- /bin/sh
|
- /bin/sh
|
||||||
- -c
|
- -c
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
name: '{{ pod_with_initcontainer_and_container.name }}'
|
|
||||||
spec:
|
|
||||||
initContainers:
|
|
||||||
- name: '{{ pod_with_initcontainer_and_container.container[0] }}'
|
|
||||||
image: busybox
|
|
||||||
command:
|
|
||||||
- /bin/sh
|
|
||||||
- -c
|
|
||||||
- while true;do date;sleep 5; done
|
|
||||||
containers:
|
|
||||||
- name: '{{ pod_with_initcontainer_and_container.container[1] }}'
|
|
||||||
image: busybox
|
|
||||||
command:
|
|
||||||
- /bin/sh
|
|
||||||
- -c
|
|
||||||
- while true;do date;sleep 5; done
|
|
||||||
@@ -24,7 +24,7 @@ spec:
|
|||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: busybox-d
|
name: openjdk-d
|
||||||
labels:
|
labels:
|
||||||
context: ansible
|
context: ansible
|
||||||
spec:
|
spec:
|
||||||
@@ -38,8 +38,8 @@ spec:
|
|||||||
context: ansible
|
context: ansible
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: busybox
|
- name: openjdk
|
||||||
image: busybox:latest
|
image: openjdk:17
|
||||||
command:
|
command:
|
||||||
- /bin/sh
|
- /bin/sh
|
||||||
- -c
|
- -c
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
wait_timeout: 400
|
wait_timeout: 400
|
||||||
vars:
|
vars:
|
||||||
k8s_pod_name: delete-ds
|
k8s_pod_name: delete-ds
|
||||||
k8s_pod_image: docker.io/nginx:latest
|
k8s_pod_image: gcr.io/kuar-demo/kuard-amd64:1
|
||||||
register: ds
|
register: ds
|
||||||
|
|
||||||
- name: Check that daemonset wait worked
|
- name: Check that daemonset wait worked
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
- name: Assert that there are pods
|
- name: Assert that there are pods
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- pods_create.resources | length > 0
|
- pods_create.resources
|
||||||
|
|
||||||
- name: Remove the daemonset
|
- name: Remove the daemonset
|
||||||
k8s:
|
k8s:
|
||||||
@@ -74,7 +74,7 @@
|
|||||||
- name: Assert that deleting the daemonset deleted the pods
|
- name: Assert that deleting the daemonset deleted the pods
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- pods_delete.resources | length == 0
|
- not pods_delete.resources
|
||||||
|
|
||||||
# test deletion using label selector
|
# test deletion using label selector
|
||||||
- name: Deploy load balancer
|
- name: Deploy load balancer
|
||||||
@@ -152,27 +152,6 @@
|
|||||||
register: _deployment
|
register: _deployment
|
||||||
failed_when: _deployment.resources | length == 0
|
failed_when: _deployment.resources | length == 0
|
||||||
|
|
||||||
- name: Trying to delete nginx deployment in check mode and with deleteOptions set
|
|
||||||
k8s:
|
|
||||||
kind: Deployment
|
|
||||||
api_version: apps/v1
|
|
||||||
namespace: "{{ test_namespace }}"
|
|
||||||
name: nginx-d
|
|
||||||
state: absent
|
|
||||||
delete_options:
|
|
||||||
propagationPolicy: Foreground
|
|
||||||
check_mode: true
|
|
||||||
register: _delete
|
|
||||||
|
|
||||||
- name: Validate that Deployment nginx-d still exists
|
|
||||||
k8s_info:
|
|
||||||
kind: Deployment
|
|
||||||
api_version: apps/v1
|
|
||||||
namespace: "{{ test_namespace }}"
|
|
||||||
name: nginx-d
|
|
||||||
register: _deployment
|
|
||||||
failed_when: _deployment.resources | length != 1
|
|
||||||
|
|
||||||
- name: Trying to delete using delete_all=true but missing kind option
|
- name: Trying to delete using delete_all=true but missing kind option
|
||||||
k8s:
|
k8s:
|
||||||
api_version: apps/v1
|
api_version: apps/v1
|
||||||
|
|||||||
@@ -182,7 +182,7 @@
|
|||||||
- name: assert that pods are running on cordoned node
|
- name: assert that pods are running on cordoned node
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- Pod.resources | selectattr('status.phase', 'equalto', 'Running') | selectattr('spec.nodeName', 'equalto', node_to_drain) | list | length > 0
|
- "{{ Pod.resources | selectattr('status.phase', 'equalto', 'Running') | selectattr('spec.nodeName', 'equalto', node_to_drain) | list | length > 0 }}"
|
||||||
|
|
||||||
- name: Uncordon node
|
- name: Uncordon node
|
||||||
k8s_drain:
|
k8s_drain:
|
||||||
@@ -236,7 +236,7 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- drain_result is changed
|
- drain_result is changed
|
||||||
- '"node "+node_to_drain+" marked unschedulable." in drain_result.result'
|
- '"node {{ node_to_drain }} marked unschedulable." in drain_result.result'
|
||||||
|
|
||||||
- name: assert that unmanaged pod were deleted
|
- name: assert that unmanaged pod were deleted
|
||||||
k8s_info:
|
k8s_info:
|
||||||
@@ -244,7 +244,7 @@
|
|||||||
kind: Pod
|
kind: Pod
|
||||||
name: '{{ drain_pod_name }}'
|
name: '{{ drain_pod_name }}'
|
||||||
register: _result
|
register: _result
|
||||||
failed_when: _result.resources | length > 0
|
failed_when: _result.resources
|
||||||
|
|
||||||
- name: assert that emptyDir pod was deleted
|
- name: assert that emptyDir pod was deleted
|
||||||
k8s_info:
|
k8s_info:
|
||||||
@@ -338,7 +338,7 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- disable_evict is changed
|
- disable_evict is changed
|
||||||
- '"node "+node_to_drain+" marked unschedulable." in disable_evict.result'
|
- '"node {{ node_to_drain }} marked unschedulable." in disable_evict.result'
|
||||||
|
|
||||||
- name: assert that unmanaged pod were deleted
|
- name: assert that unmanaged pod were deleted
|
||||||
k8s_info:
|
k8s_info:
|
||||||
@@ -346,7 +346,7 @@
|
|||||||
kind: Pod
|
kind: Pod
|
||||||
name: '{{ drain_pod_name }}-01'
|
name: '{{ drain_pod_name }}-01'
|
||||||
register: _result
|
register: _result
|
||||||
failed_when: _result.resources | length > 0
|
failed_when: _result.resources
|
||||||
|
|
||||||
# test: drain using pod_selectors
|
# test: drain using pod_selectors
|
||||||
- name: Uncordon node
|
- name: Uncordon node
|
||||||
@@ -401,7 +401,7 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- drain_pod_selector is changed
|
- drain_pod_selector is changed
|
||||||
- '"node "+node_to_drain+" marked unschedulable." in drain_pod_selector.result'
|
- '"node {{ node_to_drain }} marked unschedulable." in drain_pod_selector.result'
|
||||||
|
|
||||||
- name: assert that pod created before is still running
|
- name: assert that pod created before is still running
|
||||||
k8s_info:
|
k8s_info:
|
||||||
@@ -429,8 +429,8 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- drain_pod_selector_equal is changed
|
- drain_pod_selector_equal is changed
|
||||||
- '"node "+node_to_drain+" already marked unschedulable." in drain_pod_selector_equal.result'
|
- '"node {{ node_to_drain }} already marked unschedulable." in drain_pod_selector_equal.result'
|
||||||
- '"Deleting Pods not managed by ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet: "+test_namespace+"/ansible-drain-pod." in drain_pod_selector_equal.warnings'
|
- '"Deleting Pods not managed by ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet: {{ test_namespace }}/ansible-drain-pod." in drain_pod_selector_equal.warnings'
|
||||||
|
|
||||||
- name: Uncordon node
|
- name: Uncordon node
|
||||||
k8s_drain:
|
k8s_drain:
|
||||||
|
|||||||
@@ -394,11 +394,9 @@
|
|||||||
register: k8s_info_testing6
|
register: k8s_info_testing6
|
||||||
failed_when: not k8s_info_testing6.resources or k8s_info_testing6.resources[0].status.phase != "Active"
|
failed_when: not k8s_info_testing6.resources or k8s_info_testing6.resources[0].status.phase != "Active"
|
||||||
|
|
||||||
- name: Create a file with specific size and attributes, to be used as swap space
|
- name: Create large configmap data
|
||||||
community.general.filesize:
|
command: dd if=/dev/urandom bs=500K count=1
|
||||||
path: /tmp/configmap.bin
|
register: cmap_data
|
||||||
size: 500K
|
|
||||||
source: /dev/urandom
|
|
||||||
|
|
||||||
- name: Create configmap with large value
|
- name: Create configmap with large value
|
||||||
k8s:
|
k8s:
|
||||||
@@ -409,7 +407,7 @@
|
|||||||
name: testmap
|
name: testmap
|
||||||
namespace: testing
|
namespace: testing
|
||||||
data:
|
data:
|
||||||
testkey: "{{ lookup('file', '/tmp/configmap.bin') | b64encode }}"
|
testkey: "{{ cmap_data.stdout | b64encode }}"
|
||||||
wait: true
|
wait: true
|
||||||
register: result
|
register: result
|
||||||
|
|
||||||
@@ -426,7 +424,7 @@
|
|||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- result.resources[0].data.testkey == (lookup('file', '/tmp/configmap.bin') | b64encode)
|
- result.resources[0].data.testkey == "{{ cmap_data.stdout | b64encode }}"
|
||||||
|
|
||||||
# test setting module defaults for kubernetes.core.k8s_info
|
# test setting module defaults for kubernetes.core.k8s_info
|
||||||
- block:
|
- block:
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user