mirror of
https://github.com/ansible-collections/kubernetes.core.git
synced 2026-05-11 20:12:18 +00:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4fa6465f3e | ||
|
|
e1b341d9be | ||
|
|
8feb564b4d | ||
|
|
42832bc9d2 | ||
|
|
19b2efd0dd | ||
|
|
1c3bf95b74 | ||
|
|
018c92429b | ||
|
|
9267e03538 | ||
|
|
eb3ab99709 | ||
|
|
a1ac6b99dc | ||
|
|
4ad57fdb6c | ||
|
|
ee9939c54f | ||
|
|
c1549db1bb | ||
|
|
c6bd8ab453 | ||
|
|
6299f242a2 | ||
|
|
cd55f596ab | ||
|
|
00bbf16cff | ||
|
|
31fd4058f1 | ||
|
|
5c748bd4e9 | ||
|
|
1c295560ba | ||
|
|
615d3d8bd0 | ||
|
|
4854d7fbd9 | ||
|
|
baa59f388c | ||
|
|
e071ae73b6 | ||
|
|
00cb40094a | ||
|
|
ef829b8a56 | ||
|
|
d86a652c36 | ||
|
|
a4242f0131 | ||
|
|
d75e9a0fa3 | ||
|
|
5044cfc030 | ||
|
|
ddd7e79a12 | ||
|
|
edc979ff11 | ||
|
|
37c1f911cb | ||
|
|
80a5bf623a | ||
|
|
8f653558f6 | ||
|
|
1c0734dd4e | ||
|
|
e6d138dbf0 | ||
|
|
eed4ebb0af | ||
|
|
d3031fcbd3 | ||
|
|
e756cedf33 |
7
.ansible-lint-ignore
Normal file
7
.ansible-lint-ignore
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# 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]
|
||||||
|
# stable-3 branch support ansible-core>=2.14.0
|
||||||
|
meta/runtime.yml meta-runtime[unsupported-version]
|
||||||
@@ -2,5 +2,7 @@
|
|||||||
profile: production
|
profile: production
|
||||||
|
|
||||||
exclude_paths:
|
exclude_paths:
|
||||||
|
- .ansible/
|
||||||
- tests/integration
|
- tests/integration
|
||||||
|
- tests/unit
|
||||||
- tests/sanity
|
- tests/sanity
|
||||||
60
.github/stale.yml
vendored
60
.github/stale.yml
vendored
@@ -1,60 +0,0 @@
|
|||||||
---
|
|
||||||
# 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.
|
|
||||||
127
.github/workflows/integration-tests-kubevirt.yaml
vendored
127
.github/workflows/integration-tests-kubevirt.yaml
vendored
@@ -1,127 +0,0 @@
|
|||||||
name: Integration tests Kubevirt
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types:
|
|
||||||
- opened
|
|
||||||
- reopened
|
|
||||||
- synchronize
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- stable-*
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
splitter:
|
|
||||||
continue-on-error: true
|
|
||||||
env:
|
|
||||||
kubernetes: "./kubernetes"
|
|
||||||
kubevirt: "./kubevirt"
|
|
||||||
py_version: 3.9
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
test_targets: ${{ steps.splitter.outputs.kubevirt_targets }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout kubernetes.core repository
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
path: ${{ env.kubernetes }}
|
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
|
||||||
|
|
||||||
- name: Checkout the kubevirt.core collection
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
repository: kubevirt/kubevirt.core
|
|
||||||
path: ${{ env.kubevirt }}
|
|
||||||
|
|
||||||
- name: "Set up Python ${{ env.py_version }}"
|
|
||||||
uses: actions/setup-python@v4
|
|
||||||
with:
|
|
||||||
python-version: "${{ env.py_version }}"
|
|
||||||
|
|
||||||
- name: List targets from kubevirt.core collection
|
|
||||||
id: splitter
|
|
||||||
run: python ${{ env.kubernetes }}/tools/kubevirt_list_targets.py ${{ env.kubevirt }}
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
integration:
|
|
||||||
if: ${{ needs.splitter.outputs.test_targets != '' }}
|
|
||||||
name: "integration-kubevirt-${{ matrix.test-target }}"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
continue-on-error: true
|
|
||||||
needs:
|
|
||||||
- splitter
|
|
||||||
env:
|
|
||||||
kubernetes: "./kubernetes"
|
|
||||||
kubevirt: "./kubevirt"
|
|
||||||
ansible_version: milestone
|
|
||||||
python_version: 3.12
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
test-target: ${{ fromJson(needs.splitter.outputs.test_targets) }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout kubernetes.core repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
path: ${{ env.kubernetes }}
|
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
|
||||||
|
|
||||||
- name: Checkout kubevirt.core repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
repository: kubevirt/kubevirt.core
|
|
||||||
path: ${{ env.kubevirt }}
|
|
||||||
ref: main
|
|
||||||
|
|
||||||
# Install ansible
|
|
||||||
- name: Install ansible-core (${{ env.ansible_version }})
|
|
||||||
run: >-
|
|
||||||
python3 -m pip install
|
|
||||||
https://github.com/ansible/ansible/archive/${{ env.ansible_version }}.tar.gz
|
|
||||||
--disable-pip-version-check
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Build and install kubevirt.core collection
|
|
||||||
id: install-kubevirt
|
|
||||||
uses: ansible-network/github_actions/.github/actions/build_install_collection@main
|
|
||||||
with:
|
|
||||||
install_python_dependencies: true
|
|
||||||
source_path: ${{ env.kubevirt }}
|
|
||||||
|
|
||||||
- name: Build and install kubernetes.core collection
|
|
||||||
id: install-kubernetes
|
|
||||||
uses: ansible-network/github_actions/.github/actions/build_install_collection@main
|
|
||||||
with:
|
|
||||||
install_python_dependencies: true
|
|
||||||
source_path: ${{ env.kubernetes }}
|
|
||||||
|
|
||||||
- name: Install kind / kubectl
|
|
||||||
uses: helm/kind-action@v1.9.0
|
|
||||||
with:
|
|
||||||
version: v0.22.0
|
|
||||||
install_only: true
|
|
||||||
|
|
||||||
- name: Deploy kubevirt
|
|
||||||
run: >-
|
|
||||||
${{ env.kubevirt }}/hack/e2e-setup.sh \
|
|
||||||
-v \
|
|
||||||
--configure-inotify-limits \
|
|
||||||
--configure-secondary-network \
|
|
||||||
--deploy-kubevirt \
|
|
||||||
--deploy-kubevirt-cdi \
|
|
||||||
--deploy-kubevirt-common-instancetypes \
|
|
||||||
--deploy-cnao \
|
|
||||||
--create-cluster \
|
|
||||||
--create-nad
|
|
||||||
env:
|
|
||||||
KIND: kind
|
|
||||||
KUBECTL: kubectl
|
|
||||||
|
|
||||||
- name: Run integration tests
|
|
||||||
uses: ansible-network/github_actions/.github/actions/ansible_test_integration@main
|
|
||||||
with:
|
|
||||||
collection_path: ${{ steps.install-kubevirt.outputs.collection_path }}
|
|
||||||
python_version: ${{ env.python_version }}
|
|
||||||
ansible_version: ${{ env.ansible_version }}
|
|
||||||
ansible_test_targets: ${{ matrix.test-target }}
|
|
||||||
env:
|
|
||||||
ANSIBLE_COLLECTIONS_PATHS: /home/runner/collections
|
|
||||||
5
.github/workflows/linters.yaml
vendored
5
.github/workflows/linters.yaml
vendored
@@ -19,6 +19,5 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
- name: run-ansible-lint
|
||||||
- name: Run ansible-lint
|
uses: ansible/ansible-lint@v24.12.2
|
||||||
uses: ansible/ansible-lint@v24.2.3
|
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -13,6 +13,7 @@ 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
|
||||||
|
|||||||
@@ -5,16 +5,24 @@ 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
|
||||||
|
|||||||
@@ -4,38 +4,48 @@ Kubernetes Collection Release Notes
|
|||||||
|
|
||||||
.. contents:: Topics
|
.. contents:: Topics
|
||||||
|
|
||||||
v4.0.0
|
v3.3.1
|
||||||
======
|
======
|
||||||
|
|
||||||
Release Summary
|
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``.
|
This release fixes the CI issues with the ``linters`` workflow.
|
||||||
|
|
||||||
|
v3.3.0
|
||||||
|
======
|
||||||
|
|
||||||
Minor Changes
|
Minor Changes
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
- 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 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.
|
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 6.0.0 (https://github.com/ansible-collections/kubernetes.core/pull/734).
|
||||||
|
- k8s_drain - Improve error message for pod disruption budget when draining a node (https://github.com/ansible-collections/kubernetes.core/issues/797).
|
||||||
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
|
Bugfixes
|
||||||
--------
|
--------
|
||||||
|
|
||||||
- Resolve Collections util resource discovery fails when complex subresources present (https://github.com/ansible-collections/kubernetes.core/pull/676).
|
- helm - Helm version checks did not support RC versions. They now accept any version tags. (https://github.com/ansible-collections/kubernetes.core/pull/745).
|
||||||
- align `helmdiff_check()` function commandline rendering with the `deploy()` function (https://github.com/ansible-collections/kubernetes.core/pull/670).
|
- helm_pull - Apply no_log=True to pass_credentials to silence false positive warning.. (https://github.com/ansible-collections/kubernetes.core/pull/796).
|
||||||
- avoid unsafe conditions in integration tests (https://github.com/ansible-collections/kubernetes.core/pull/665).
|
- k8s_drain - Fix k8s_drain does not wait for single pod (https://github.com/ansible-collections/kubernetes.core/issues/769).
|
||||||
- helm - use ``reuse-values`` when running ``helm diff`` command (https://github.com/ansible-collections/kubernetes.core/issues/680).
|
- 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).
|
||||||
- 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).
|
- 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 6.0.0 (https://github.com/ansible-collections/kubernetes.core/pull/734).
|
||||||
|
|
||||||
v3.1.0
|
v3.1.0
|
||||||
======
|
======
|
||||||
|
|||||||
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 = 4.0.0
|
VERSION = 3.3.1
|
||||||
|
|
||||||
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]))'`
|
||||||
|
|||||||
62
README.md
62
README.md
@@ -4,10 +4,14 @@
|
|||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
<!--start requires_ansible-->
|
<!--start requires_ansible-->
|
||||||
## Ansible version compatibility
|
### Ansible version compatibility
|
||||||
|
|
||||||
This collection has been tested against following Ansible versions: **>=2.14.0**.
|
This collection has been tested against following Ansible versions: **>=2.14.0**.
|
||||||
|
|
||||||
@@ -18,43 +22,43 @@ 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-->
|
||||||
|
|
||||||
## Python Support
|
### 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
|
||||||
[kubernetes.core.kustomize](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.kustomize_lookup.rst)|Build a set of kubernetes resources using a 'kustomization.yaml' file.
|
[kubernetes.core.kustomize](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.kustomize_lookup.rst)|Build a set of kubernetes resources using a 'kustomization.yaml' file.
|
||||||
|
|
||||||
### Modules
|
#### Modules
|
||||||
Name | Description
|
Name | Description
|
||||||
--- | ---
|
--- | ---
|
||||||
[kubernetes.core.helm](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_module.rst)|Manages Kubernetes packages with the Helm package manager
|
[kubernetes.core.helm](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_module.rst)|Manages Kubernetes packages with the Helm package manager
|
||||||
@@ -79,9 +83,7 @@ Name | Description
|
|||||||
|
|
||||||
<!--end collection content-->
|
<!--end collection content-->
|
||||||
|
|
||||||
## Installation and Usage
|
## Installation
|
||||||
|
|
||||||
### 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:
|
||||||
|
|
||||||
@@ -93,7 +95,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: 4.0.0
|
version: 3.3.1
|
||||||
```
|
```
|
||||||
|
|
||||||
### Installing the Kubernetes Python Library
|
### Installing the Kubernetes Python Library
|
||||||
@@ -102,7 +104,7 @@ Content in this collection requires the [Kubernetes Python client](https://pypi.
|
|||||||
|
|
||||||
pip3 install kubernetes
|
pip3 install kubernetes
|
||||||
|
|
||||||
### Using modules from the Kubernetes Collection in your playbooks
|
## Use Cases
|
||||||
|
|
||||||
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`:
|
||||||
|
|
||||||
@@ -189,12 +191,16 @@ 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).
|
||||||
|
|
||||||
## Testing and Development
|
## Contributing to this collection
|
||||||
|
|
||||||
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).
|
||||||
@@ -231,10 +237,36 @@ 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
|
||||||
|
|
||||||
|
<!--List available communication channels. In addition to channels specific to your collection, we also recommend to use the following ones.-->
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
## More Information
|
## More Information
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
## 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
|
||||||
|
|||||||
@@ -854,45 +854,54 @@ 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'
|
||||||
4.0.0:
|
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:
|
changes:
|
||||||
bugfixes:
|
bugfixes:
|
||||||
- Resolve Collections util resource discovery fails when complex subresources
|
- helm - Helm version checks did not support RC versions. They now accept any
|
||||||
present (https://github.com/ansible-collections/kubernetes.core/pull/676).
|
version tags. (https://github.com/ansible-collections/kubernetes.core/pull/745).
|
||||||
- align `helmdiff_check()` function commandline rendering with the `deploy()`
|
- helm_pull - Apply no_log=True to pass_credentials to silence false positive
|
||||||
function (https://github.com/ansible-collections/kubernetes.core/pull/670).
|
warning. (https://github.com/ansible-collections/kubernetes.core/pull/796).
|
||||||
- avoid unsafe conditions in integration tests (https://github.com/ansible-collections/kubernetes.core/pull/665).
|
- k8s_drain - Fix k8s_drain does not wait for single pod (https://github.com/ansible-collections/kubernetes.core/issues/769).
|
||||||
- helm - use ``reuse-values`` when running ``helm diff`` command (https://github.com/ansible-collections/kubernetes.core/issues/680).
|
- k8s_drain - Fix k8s_drain runs into a timeout when evicting a pod which is
|
||||||
- integrations test helm_kubeconfig - set helm version to v3.10.3 to avoid incompatability
|
part of a stateful set (https://github.com/ansible-collections/kubernetes.core/issues/792).
|
||||||
with new bitnami charts (https://github.com/ansible-collections/kubernetes.core/pull/670).
|
- 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:
|
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_drain - Improve error message for pod disruption budget when draining
|
||||||
- k8s - The module and K8sService were changed so warnings returned by the K8S
|
a node (https://github.com/ansible-collections/kubernetes.core/issues/797).
|
||||||
API are now displayed to the user.
|
release_summary: This release comes with improvements to the error messages in the k8s_drain module and several bug fixes.
|
||||||
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:
|
fragments:
|
||||||
- 20231206-fix-unsafe-condition-in-integration.yml
|
- 20240530-ansible-core-support-update.yaml
|
||||||
- 20240117-fix-helm-diff-cmd-line-rendering.yml
|
- 20240611-helm-rc-version.yaml
|
||||||
- 20240222-Collections-util-resource-discovery-fails-when-complex-subresources-present.yml
|
- 20240620-fix-kustomize-plugin-fails-with-deprecation-warnings.yml
|
||||||
- 20240228-fix-helm-diff-with-reuse-values.yml
|
- 20241102-fix-ci-post-2.18-issue.yaml
|
||||||
- 20240423-k8s-display-warnings-to-users.yml
|
- 20241213-kubeconfig-set-no_log-true.yaml
|
||||||
- 4.0.0.yaml
|
- 756-fix-daemonset-waiting.yaml
|
||||||
- inventory-update_removal_date.yml
|
- 770-fix-k8s-drain-doesnt-wait-for-single-pod.yaml
|
||||||
- k8s-merge_type-removed.yml
|
- 793-fix-k8s-drain-runs-into-timeout.yaml
|
||||||
- module_utils-common-remove-deprecated-functions-and-class.yaml
|
- 796-false-positive-helmull.yaml
|
||||||
release_date: '2024-05-24'
|
- 798-drain-pdb-error-message.yaml
|
||||||
|
- readme_template_update.yml
|
||||||
|
release_date: '2025-01-22'
|
||||||
|
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'
|
||||||
|
|||||||
@@ -443,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 2.5.0</div>
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
@@ -463,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 2.5.0</div>
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
|||||||
@@ -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 2.5.0</div>
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -168,7 +168,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 2.5.0</div>
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -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 5.0.0.
|
remove the k8s inventory plugin in release 6.0.0.
|
||||||
|
|
||||||
:Alternative: Use :ref:`kubernetes.core.k8s_info <kubernetes.core.k8s_info_module>` and :ref:`ansible.builtin.add_host <ansible.builtin.add_host_module>` instead.
|
: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 5.0.0. *[deprecated]*
|
- This inventory will be removed in version 6.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 2.5.0</div>
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.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,7 +389,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 2.5.0</div>
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
@@ -513,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,6 +365,82 @@ 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: 4.0.0
|
version: 3.3.1
|
||||||
build_ignore:
|
build_ignore:
|
||||||
- .DS_Store
|
- .DS_Store
|
||||||
- "*.tar.gz"
|
- "*.tar.gz"
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ plugin_routing:
|
|||||||
redirect: community.okd.openshift
|
redirect: community.okd.openshift
|
||||||
k8s:
|
k8s:
|
||||||
deprecation:
|
deprecation:
|
||||||
removal_version: 5.0.0
|
removal_version: 6.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 5.0.0.
|
will be removed in release 6.0.0.
|
||||||
modules:
|
modules:
|
||||||
k8s_auth:
|
k8s_auth:
|
||||||
redirect: community.okd.k8s_auth
|
redirect: community.okd.k8s_auth
|
||||||
|
|||||||
@@ -181,6 +181,81 @@ 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
|
||||||
|
|||||||
@@ -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: 5.0.0
|
removed_in: 6.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 5.0.0.
|
remove the k8s inventory plugin in release 6.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 5.0.0",
|
"The 'k8s' inventory plugin has been deprecated and will be removed in release 6.0.0",
|
||||||
version="5.0.0",
|
version="6.0.0",
|
||||||
collection_name="kubernetes.core",
|
collection_name="kubernetes.core",
|
||||||
)
|
)
|
||||||
cache_key = self._get_cache_prefix(path)
|
cache_key = self._get_cache_prefix(path)
|
||||||
|
|||||||
@@ -94,7 +94,8 @@ 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)
|
||||||
return cmd.communicate()
|
stdout, stderr = cmd.communicate()
|
||||||
|
return cmd.returncode, stdout, stderr
|
||||||
|
|
||||||
|
|
||||||
class LookupModule(LookupBase):
|
class LookupModule(LookupBase):
|
||||||
@@ -140,9 +141,18 @@ class LookupModule(LookupBase):
|
|||||||
if enable_helm:
|
if enable_helm:
|
||||||
command += ["--enable-helm"]
|
command += ["--enable-helm"]
|
||||||
|
|
||||||
(out, err) = run_command(command)
|
(ret, out, err) = run_command(command)
|
||||||
if err:
|
if ret != 0:
|
||||||
raise AnsibleLookupError(
|
if err:
|
||||||
"kustomize command failed with: {0}".format(err.decode("utf-8"))
|
raise AnsibleLookupError(
|
||||||
)
|
"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,
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ AUTH_PROXY_HEADERS_SPEC = dict(
|
|||||||
)
|
)
|
||||||
|
|
||||||
AUTH_ARG_SPEC = {
|
AUTH_ARG_SPEC = {
|
||||||
"kubeconfig": {"type": "raw"},
|
"kubeconfig": {"type": "raw", "no_log": True},
|
||||||
"context": {},
|
"context": {},
|
||||||
"host": {},
|
"host": {},
|
||||||
"api_key": {"no_log": True},
|
"api_key": {"no_log": True},
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -77,7 +77,6 @@ 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
|
||||||
"""
|
"""
|
||||||
@@ -184,10 +183,10 @@ 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([0-9\.]*)",', out)
|
m = re.match(r'version.BuildInfo{Version:"v(.*?)",', out)
|
||||||
if m:
|
if m:
|
||||||
return m.group(1)
|
return m.group(1)
|
||||||
m = re.match(r'Client: &version.Version{SemVer:"v([0-9\.]*)", ', out)
|
m = re.match(r'Client: &version.Version{SemVer:"v(.*?)", ', out)
|
||||||
if m:
|
if m:
|
||||||
return m.group(1)
|
return m.group(1)
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ HELM_AUTH_ARG_SPEC = dict(
|
|||||||
type="raw",
|
type="raw",
|
||||||
aliases=["kubeconfig_path"],
|
aliases=["kubeconfig_path"],
|
||||||
fallback=(env_fallback, ["K8S_AUTH_KUBECONFIG"]),
|
fallback=(env_fallback, ["K8S_AUTH_KUBECONFIG"]),
|
||||||
|
no_log=True,
|
||||||
),
|
),
|
||||||
host=dict(type="str", fallback=(env_fallback, ["K8S_AUTH_HOST"])),
|
host=dict(type="str", fallback=(env_fallback, ["K8S_AUTH_HOST"])),
|
||||||
ca_cert=dict(
|
ca_cert=dict(
|
||||||
|
|||||||
@@ -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,8 +2,6 @@
|
|||||||
# 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 re import compile
|
|
||||||
from typing import Any, Dict, List, Optional, Tuple
|
from typing import Any, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
from ansible.module_utils.common.dict_transformations import dict_merge
|
from ansible.module_utils.common.dict_transformations import dict_merge
|
||||||
@@ -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,
|
||||||
@@ -540,83 +543,3 @@ def hide_field(definition: dict, hidden_field: str) -> dict:
|
|||||||
else:
|
else:
|
||||||
del definition[split[0]]
|
del definition[split[0]]
|
||||||
return definition
|
return definition
|
||||||
|
|
||||||
|
|
||||||
def decode_response(resp) -> Tuple[Dict, List[str]]:
|
|
||||||
"""
|
|
||||||
This function decodes unserialized responses from the Kubernetes python
|
|
||||||
client and decodes the RFC2616 14.46 warnings found in the response
|
|
||||||
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
|
|
||||||
|
|||||||
@@ -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
|
and (daemonset.status.updatedNumberScheduled or 0)
|
||||||
== 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
|
||||||
|
|||||||
@@ -137,14 +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: 2.5.0
|
version_added: 3.0.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: 2.5.0
|
version_added: 3.0.0
|
||||||
|
|
||||||
#Helm options
|
#Helm options
|
||||||
disable_hook:
|
disable_hook:
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ 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),
|
pass_credentials=dict(type="bool", default=False, no_log=False),
|
||||||
skip_tls_certs_check=dict(type="bool", default=False),
|
skip_tls_certs_check=dict(type="bool", default=False),
|
||||||
chart_devel=dict(type="bool"),
|
chart_devel=dict(type="bool"),
|
||||||
untar_chart=dict(type="bool", default=False),
|
untar_chart=dict(type="bool", default=False),
|
||||||
|
|||||||
@@ -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,7 +182,7 @@ 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: 2.5.0
|
version_added: 3.0.0
|
||||||
aliases:
|
aliases:
|
||||||
- all
|
- all
|
||||||
hidden_fields:
|
hidden_fields:
|
||||||
@@ -191,7 +192,7 @@ options:
|
|||||||
- Only field definitions that don't reference list items are supported (so V(spec.containers[0]) would not work)
|
- Only field definitions that don't reference list items are supported (so V(spec.containers[0]) would not work)
|
||||||
type: list
|
type: list
|
||||||
elements: str
|
elements: str
|
||||||
version_added: 2.5.0
|
version_added: 3.0.0
|
||||||
|
|
||||||
requirements:
|
requirements:
|
||||||
- "python >= 3.9"
|
- "python >= 3.9"
|
||||||
@@ -459,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)
|
||||||
|
|||||||
@@ -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: 2.5.0
|
version_added: 3.0.0
|
||||||
aliases:
|
aliases:
|
||||||
- label_selectors
|
- label_selectors
|
||||||
delete_options:
|
delete_options:
|
||||||
@@ -143,6 +143,7 @@ result:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
import json
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@@ -187,6 +188,17 @@ 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 = [], [], [], [], []
|
||||||
@@ -291,16 +303,19 @@ class K8sDrainAnsible(object):
|
|||||||
return (datetime.now() - start).seconds
|
return (datetime.now() - start).seconds
|
||||||
|
|
||||||
response = None
|
response = None
|
||||||
pod = pods.pop()
|
pod = None
|
||||||
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.pop()
|
pod = pods[-1]
|
||||||
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:
|
if not response or response.spec.node_name != self._module.params.get(
|
||||||
|
"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":
|
||||||
@@ -308,6 +323,7 @@ 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:
|
||||||
@@ -334,7 +350,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, exc.reason
|
namespace, name, to_native(format_dynamic_api_exc(exc))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ options:
|
|||||||
- Only field definitions that don't reference list items are supported (so V(spec.containers[0]) would not work)
|
- Only field definitions that don't reference list items are supported (so V(spec.containers[0]) would not work)
|
||||||
type: list
|
type: list
|
||||||
elements: str
|
elements: str
|
||||||
version_added: 2.5.0
|
version_added: 3.0.0
|
||||||
|
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- kubernetes.core.k8s_auth_options
|
- kubernetes.core.k8s_auth_options
|
||||||
|
|||||||
@@ -4,4 +4,4 @@
|
|||||||
loop_control:
|
loop_control:
|
||||||
loop_var: helm_version
|
loop_var: helm_version
|
||||||
with_items:
|
with_items:
|
||||||
- "v3.7.0"
|
- "v3.8.0"
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
- name: Initial chart installation
|
- name: Initial chart installation
|
||||||
helm:
|
helm:
|
||||||
binary_path: "{{ helm_binary }}"
|
binary_path: "{{ helm_binary }}"
|
||||||
chart_ref: redis
|
chart_ref: oci://registry-1.docker.io/bitnamicharts/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
|
||||||
@@ -42,8 +41,7 @@
|
|||||||
- 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: redis
|
chart_ref: oci://registry-1.docker.io/bitnamicharts/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
|
||||||
|
|||||||
@@ -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,7 +130,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
|
- install.status.chart == "{{ chart_test }}-{{ chart_test_version }}"
|
||||||
- "install.status['values'].revisionHistoryLimit == 0"
|
- "install.status['values'].revisionHistoryLimit == 0"
|
||||||
|
|
||||||
- name: Check idempotency after adding vars
|
- name: Check idempotency after adding vars
|
||||||
@@ -148,7 +148,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
|
- install.status.chart == "{{ chart_test }}-{{ chart_test_version }}"
|
||||||
- "install.status['values'].revisionHistoryLimit == 0"
|
- "install.status['values'].revisionHistoryLimit == 0"
|
||||||
|
|
||||||
- name: "Remove Vars to {{ chart_test }} from {{ source }}"
|
- name: "Remove Vars to {{ chart_test }} from {{ source }}"
|
||||||
@@ -165,7 +165,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
|
- install.status.chart == "{{ chart_test }}-{{ chart_test_version }}"
|
||||||
- install.status['values'] == {}
|
- install.status['values'] == {}
|
||||||
|
|
||||||
- name: Check idempotency after removing vars
|
- name: Check idempotency after removing vars
|
||||||
@@ -182,7 +182,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
|
- install.status.chart == "{{ chart_test }}-{{ chart_test_version }}"
|
||||||
- install.status['values'] == {}
|
- install.status['values'] == {}
|
||||||
|
|
||||||
- name: "Upgrade {{ chart_test }} from {{ source }}"
|
- name: "Upgrade {{ chart_test }} from {{ source }}"
|
||||||
@@ -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,7 +316,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
|
- install.status.chart == "{{ chart_test }}-{{ chart_test_version }}"
|
||||||
- "install.status['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)"
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
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"
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: {{ default "ansible-configmap" .Values.myConfigmapName }}
|
||||||
|
data:
|
||||||
|
myValue: {{ default "test" .Values.myValue }}
|
||||||
|
deploymentTime: {{ now }}
|
||||||
@@ -2,3 +2,4 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
- remove_namespace
|
- remove_namespace
|
||||||
- install_helm
|
- install_helm
|
||||||
|
- setup_helm_registry
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
- 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:
|
||||||
|
|
||||||
@@ -24,7 +23,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: yes
|
create_namespace: true
|
||||||
register: install
|
register: install
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
@@ -49,8 +48,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: yes
|
check_mode: true
|
||||||
diff: yes
|
diff: true
|
||||||
register: diff_result
|
register: diff_result
|
||||||
|
|
||||||
- name: Check if helm diff check is correct
|
- name: Check if helm diff check is correct
|
||||||
@@ -79,7 +78,7 @@
|
|||||||
namespace: "{{ helm_namespace }}"
|
namespace: "{{ helm_namespace }}"
|
||||||
chart_ref: "{{ test_chart_ref }}"
|
chart_ref: "{{ test_chart_ref }}"
|
||||||
check_mode: yes
|
check_mode: yes
|
||||||
diff: yes
|
diff: true
|
||||||
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
|
||||||
@@ -101,7 +100,7 @@
|
|||||||
|
|
||||||
- name: Modify values
|
- name: Modify values
|
||||||
blockinfile:
|
blockinfile:
|
||||||
create: yes
|
create: true
|
||||||
path: "{{ test_chart_ref }}/values.yml"
|
path: "{{ test_chart_ref }}/values.yml"
|
||||||
block: |
|
block: |
|
||||||
---
|
---
|
||||||
@@ -206,52 +205,76 @@
|
|||||||
- 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: yes
|
ignore_errors: true
|
||||||
|
|
||||||
|
- 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:
|
||||||
@@ -260,37 +283,36 @@
|
|||||||
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 Redis chart once again
|
- name: Upgrade chart once again
|
||||||
helm:
|
helm:
|
||||||
binary_path: "{{ helm_binary }}"
|
binary_path: "{{ helm_binary }}"
|
||||||
chart_repo_url: https://charts.bitnami.com/bitnami
|
chart_ref: "{{ test_chart_ref_url }}"
|
||||||
chart_ref: redis
|
chart_version: 0.1.0
|
||||||
namespace: "{{ helm_namespace }}"
|
namespace: "{{ helm_namespace }}"
|
||||||
name: redis-chart
|
name: another-chart
|
||||||
chart_version: "{{ redis_chart_version }}"
|
release_values: "{{ test_chart_values }}"
|
||||||
release_values: "{{ redis_chart_values }}"
|
check_mode: true
|
||||||
check_mode: yes
|
register: _upgrade_2
|
||||||
register: redis_upgrade_2
|
|
||||||
|
|
||||||
- name: Assert that module raised a warning
|
- name: Assert that module raised a warning
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- redis_upgrade_2.changed
|
- _upgrade_2.changed
|
||||||
- redis_upgrade_2.warnings is not defined
|
- _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: yes
|
ignore_errors: true
|
||||||
|
|
||||||
- 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: yes
|
ignore_errors: true
|
||||||
|
|
||||||
- name: Remove helm namespace
|
- name: Remove helm namespace
|
||||||
k8s:
|
k8s:
|
||||||
@@ -299,6 +321,6 @@
|
|||||||
name: "{{ helm_namespace }}"
|
name: "{{ helm_namespace }}"
|
||||||
state: absent
|
state: absent
|
||||||
wait: true
|
wait: true
|
||||||
ignore_errors: yes
|
ignore_errors: true
|
||||||
|
|
||||||
- include_tasks: reuse_values.yml
|
- include_tasks: reuse_values.yml
|
||||||
|
|||||||
@@ -18,7 +18,12 @@
|
|||||||
- set_fact:
|
- set_fact:
|
||||||
saved_kubeconfig_path: "{{ _dir.path }}/config"
|
saved_kubeconfig_path: "{{ _dir.path }}/config"
|
||||||
|
|
||||||
- block:
|
- vars:
|
||||||
|
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
|
||||||
@@ -59,14 +64,14 @@
|
|||||||
- plugin_info.plugin_list != []
|
- plugin_info.plugin_list != []
|
||||||
|
|
||||||
# helm_repository, helm, helm_info
|
# helm_repository, helm, helm_info
|
||||||
- name: Add test_bitnami chart repository
|
- name: 'Add "{{ helm_repo_name }}" chart repository'
|
||||||
helm_repository:
|
helm_repository:
|
||||||
binary_path: "{{ helm_binary }}"
|
binary_path: "{{ helm_binary }}"
|
||||||
name: test_bitnami
|
name: "{{ helm_repo_name }}"
|
||||||
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: https://charts.bitnami.com/bitnami
|
repo_url: "{{ helm_repo_url }}"
|
||||||
register: repository
|
register: repository
|
||||||
|
|
||||||
- name: Assert that repository was added
|
- name: Assert that repository was added
|
||||||
@@ -77,8 +82,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: rabbitmq
|
name: "{{ helm_release_name }}"
|
||||||
chart_ref: test_bitnami/rabbitmq
|
chart_ref: "{{ helm_repo_name }}/{{ helm_chart_name }}"
|
||||||
namespace: "{{ helm_namespace }}"
|
namespace: "{{ helm_namespace }}"
|
||||||
update_repo_cache: true
|
update_repo_cache: true
|
||||||
kubeconfig: "{{ test_kubeconfig | default(omit) }}"
|
kubeconfig: "{{ test_kubeconfig | default(omit) }}"
|
||||||
@@ -98,7 +103,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: "rabbitmq"
|
name: "{{ helm_release_name }}"
|
||||||
namespace: "{{ helm_namespace }}"
|
namespace: "{{ helm_namespace }}"
|
||||||
register: chart_info
|
register: chart_info
|
||||||
|
|
||||||
@@ -112,7 +117,7 @@
|
|||||||
- name: Remove chart
|
- name: Remove chart
|
||||||
helm:
|
helm:
|
||||||
binary_path: "{{ helm_binary }}"
|
binary_path: "{{ helm_binary }}"
|
||||||
name: rabbitmq
|
name: "{{ helm_release_name }}"
|
||||||
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) }}"
|
||||||
@@ -131,7 +136,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: "rabbitmq"
|
name: "{{ helm_release_name }}"
|
||||||
namespace: "{{ helm_namespace }}"
|
namespace: "{{ helm_namespace }}"
|
||||||
register: chart_info
|
register: chart_info
|
||||||
|
|
||||||
@@ -143,7 +148,7 @@
|
|||||||
- name: Remove chart repository
|
- name: Remove chart repository
|
||||||
helm_repository:
|
helm_repository:
|
||||||
binary_path: "{{ helm_binary }}"
|
binary_path: "{{ helm_binary }}"
|
||||||
name: test_bitnami
|
name: "{{ helm_repo_name }}"
|
||||||
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) }}"
|
||||||
@@ -192,6 +197,6 @@
|
|||||||
- name: Delete helm repository
|
- name: Delete helm repository
|
||||||
helm_repository:
|
helm_repository:
|
||||||
binary_path: "{{ helm_binary }}"
|
binary_path: "{{ helm_binary }}"
|
||||||
name: test_bitnami
|
name: "{{ helm_repo_name }}"
|
||||||
state: absent
|
state: absent
|
||||||
ignore_errors: true
|
ignore_errors: true
|
||||||
|
|||||||
@@ -180,6 +180,7 @@
|
|||||||
- '"--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:
|
||||||
@@ -203,9 +204,8 @@
|
|||||||
- 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: redis
|
chart_ref: "oci://registry-1.docker.io/bitnamicharts/redis"
|
||||||
destination: "{{ destination }}"
|
destination: "{{ destination }}"
|
||||||
repo_url: "https://charts.bitnami.com/bitnami"
|
|
||||||
untar_chart: true
|
untar_chart: true
|
||||||
register: _result
|
register: _result
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
- 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: mariadb
|
chart_ref: oci://registry-1.docker.io/bitnamicharts/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
|
||||||
@@ -36,8 +35,7 @@
|
|||||||
- 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: apache
|
chart_ref: oci://registry-1.docker.io/bitnamicharts/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
|
||||||
@@ -79,8 +77,7 @@
|
|||||||
- 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: minio
|
chart_ref: oci://registry-1.docker.io/bitnamicharts/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
|
||||||
@@ -107,3 +104,11 @@
|
|||||||
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.7.0
|
helm_version: v3.8.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"
|
||||||
|
|||||||
@@ -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:
|
||||||
@@ -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:
|
||||||
@@ -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:
|
||||||
|
|||||||
@@ -424,7 +424,7 @@
|
|||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- result.resources[0].data.testkey == (cmap_data.stdout | 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:
|
||||||
|
|||||||
@@ -69,7 +69,7 @@
|
|||||||
- name: assert pod has been created
|
- name: assert pod has been created
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- pods.resources | length == 1
|
- "{{ pods.resources | length == 1 }}"
|
||||||
|
|
||||||
- name: create pod using generate_name parameter should succeed
|
- name: create pod using generate_name parameter should succeed
|
||||||
k8s:
|
k8s:
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
- name: assert pod has been created
|
- name: assert pod has been created
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- pods.resources | length == 2
|
- "{{ pods.resources | length == 2 }}"
|
||||||
|
|
||||||
- name: create pod using metadata.generateName parameter should succeed
|
- name: create pod using metadata.generateName parameter should succeed
|
||||||
k8s:
|
k8s:
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
- name: assert pod has been created
|
- name: assert pod has been created
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- pods.resources | length == 3
|
- "{{ pods.resources | length == 3 }}"
|
||||||
|
|
||||||
- name: create object using metadata.generateName should support wait option
|
- name: create object using metadata.generateName should support wait option
|
||||||
k8s:
|
k8s:
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- fake_pod is failed
|
- fake_pod is failed
|
||||||
- fake_pod.msg == "Pod "+test_namespace+"/this_pod_does_exist not found."
|
- 'fake_pod.msg == "Pod {{ test_namespace }}/this_pod_does_exist not found."'
|
||||||
|
|
||||||
- name: create hello-world deployment
|
- name: create hello-world deployment
|
||||||
k8s:
|
k8s:
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
- name: Update directory permissions
|
- name: Update directory permissions
|
||||||
file:
|
file:
|
||||||
path: "{{ manifests_dir.path }}"
|
path: "{{ manifests_dir.path }}"
|
||||||
mode: 0755
|
mode: '0755'
|
||||||
|
|
||||||
- name: Create manifests files
|
- name: Create manifests files
|
||||||
copy:
|
copy:
|
||||||
|
|||||||
@@ -65,7 +65,7 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- _result.result.status.phase == 'Running'
|
- _result.result.status.phase == 'Running'
|
||||||
- _result.result.spec.nodeName == node_to_taint
|
- _result.result.spec.nodeName == "{{ node_to_taint }}"
|
||||||
|
|
||||||
- name: Taint node (check_mode)
|
- name: Taint node (check_mode)
|
||||||
kubernetes.core.k8s_taint:
|
kubernetes.core.k8s_taint:
|
||||||
@@ -89,8 +89,8 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- _result.changed
|
- _result.changed
|
||||||
- item['effect'] == taint_patch_1[0]['effect']
|
- "{{ item['effect'] == taint_patch_1[0]['effect'] }}"
|
||||||
- item['key'] == taint_patch_1[0]['key']
|
- "{{ item['key'] == taint_patch_1[0]['key'] }}"
|
||||||
loop: "{{ _result.result.spec.taints }}"
|
loop: "{{ _result.result.spec.taints }}"
|
||||||
|
|
||||||
- name: Taint node (idempotency) - (check_mode)
|
- name: Taint node (idempotency) - (check_mode)
|
||||||
|
|||||||
@@ -213,8 +213,8 @@
|
|||||||
- name: check that resources creation failed
|
- name: check that resources creation failed
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- resource.results.0.resources | length == 0
|
- '{{ resource.results[0].resources | length == 0 }}'
|
||||||
- resource.results.1.resources | length == 0
|
- '{{ resource.results[1].resources | length == 0 }}'
|
||||||
|
|
||||||
- name: create pod without namespace (continue_on_error = true)
|
- name: create pod without namespace (continue_on_error = true)
|
||||||
kubernetes.core.k8s:
|
kubernetes.core.k8s:
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ k8s_pod_metadata:
|
|||||||
|
|
||||||
k8s_pod_spec:
|
k8s_pod_spec:
|
||||||
serviceAccount: "{{ k8s_pod_service_account }}"
|
serviceAccount: "{{ k8s_pod_service_account }}"
|
||||||
|
nodeSelector: "{{ k8s_pod_node_selector }}"
|
||||||
containers:
|
containers:
|
||||||
- image: "{{ k8s_pod_image }}"
|
- image: "{{ k8s_pod_image }}"
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
@@ -33,6 +34,8 @@ k8s_pod_ports: []
|
|||||||
|
|
||||||
k8s_pod_env: []
|
k8s_pod_env: []
|
||||||
|
|
||||||
|
k8s_pod_node_selector: {}
|
||||||
|
|
||||||
k8s_pod_template:
|
k8s_pod_template:
|
||||||
metadata: "{{ k8s_pod_metadata }}"
|
metadata: "{{ k8s_pod_metadata }}"
|
||||||
spec: "{{ k8s_pod_spec }}"
|
spec: "{{ k8s_pod_spec }}"
|
||||||
|
|||||||
@@ -127,6 +127,48 @@
|
|||||||
- ds.result.status.currentNumberScheduled == ds.result.status.desiredNumberScheduled
|
- ds.result.status.currentNumberScheduled == ds.result.status.desiredNumberScheduled
|
||||||
- updated_ds_pods.resources[0].spec.containers[0].image.endswith(":3")
|
- updated_ds_pods.resources[0].spec.containers[0].image.endswith(":3")
|
||||||
|
|
||||||
|
- name: Create daemonset with nodeSelector and not existing label
|
||||||
|
k8s:
|
||||||
|
definition:
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: DaemonSet
|
||||||
|
metadata:
|
||||||
|
name: wait-daemonset-not-existing-label
|
||||||
|
namespace: "{{ wait_namespace }}"
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: "{{ k8s_pod_name }}"
|
||||||
|
template: "{{ k8s_pod_template }}"
|
||||||
|
wait: yes
|
||||||
|
wait_sleep: 5
|
||||||
|
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
|
||||||
|
vars:
|
||||||
|
k8s_pod_name: wait-daemonset-not-existing-label
|
||||||
|
k8s_pod_image: gcr.io/kuar-demo/kuard-amd64:1
|
||||||
|
k8s_pod_command:
|
||||||
|
- sleep
|
||||||
|
- "600"
|
||||||
|
k8s_pod_node_selector:
|
||||||
|
nonExisitingLabel: test-not-exiting-label
|
||||||
|
register: ds_not_existing_label
|
||||||
|
|
||||||
|
- name: Get updated pods
|
||||||
|
k8s_info:
|
||||||
|
api_version: v1
|
||||||
|
kind: Pod
|
||||||
|
namespace: "{{ wait_namespace }}"
|
||||||
|
label_selectors:
|
||||||
|
- app=wait-daemonset-not-existing-label
|
||||||
|
register: updated_ds_pods_not_existing_label
|
||||||
|
|
||||||
|
- name: Check that daemonset wait worked (when desired number is 0)
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- ds_not_existing_label.result.status.currentNumberScheduled == ds_not_existing_label.result.status.desiredNumberScheduled
|
||||||
|
- ds_not_existing_label.result.status.desiredNumberScheduled == 0
|
||||||
|
- updated_ds_pods_not_existing_label.resources | length == 0
|
||||||
|
|
||||||
- name: Add a statefulset
|
- name: Add a statefulset
|
||||||
k8s:
|
k8s:
|
||||||
definition:
|
definition:
|
||||||
|
|||||||
@@ -130,9 +130,9 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- result_configmap.apiVersion == 'v1'
|
- result_configmap.apiVersion == 'v1'
|
||||||
- result_configmap.metadata.name == configmap_name
|
- result_configmap.metadata.name == "{{ configmap_name }}"
|
||||||
- result_configmap.metadata.namespace == test_namespace[2]
|
- result_configmap.metadata.namespace == "{{ test_namespace[2] }}"
|
||||||
- result_configmap.data.value == configmap_data
|
- result_configmap.data.value == "{{ configmap_data }}"
|
||||||
|
|
||||||
# test lookup plugin using src parameter
|
# test lookup plugin using src parameter
|
||||||
- block:
|
- block:
|
||||||
@@ -159,9 +159,9 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- src_configmap.apiVersion == 'v1'
|
- src_configmap.apiVersion == 'v1'
|
||||||
- src_configmap.metadata.name == configmap_name
|
- src_configmap.metadata.name == "{{ configmap_name }}"
|
||||||
- src_configmap.metadata.namespace == test_namespace[2]
|
- src_configmap.metadata.namespace == "{{ test_namespace[2] }}"
|
||||||
- src_configmap.data.value == configmap_data
|
- src_configmap.data.value == "{{ configmap_data }}"
|
||||||
|
|
||||||
always:
|
always:
|
||||||
- name: Delete temporary file created
|
- name: Delete temporary file created
|
||||||
@@ -198,9 +198,9 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- configmap_no_ssl.apiVersion == 'v1'
|
- configmap_no_ssl.apiVersion == 'v1'
|
||||||
- configmap_no_ssl.metadata.name == configmap_name
|
- configmap_no_ssl.metadata.name == "{{ configmap_name }}"
|
||||||
- configmap_no_ssl.metadata.namespace == test_namespace[2]
|
- configmap_no_ssl.metadata.namespace == "{{ test_namespace[2] }}"
|
||||||
- configmap_no_ssl.data.value == configmap_data
|
- configmap_no_ssl.data.value == "{{ configmap_data }}"
|
||||||
|
|
||||||
- name: Retrieve configmap using authentication aliases (validate_certs=true)
|
- name: Retrieve configmap using authentication aliases (validate_certs=true)
|
||||||
set_fact:
|
set_fact:
|
||||||
@@ -210,9 +210,9 @@
|
|||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- configmap_with_ssl.apiVersion == 'v1'
|
- configmap_with_ssl.apiVersion == 'v1'
|
||||||
- configmap_with_ssl.metadata.name == configmap_name
|
- configmap_with_ssl.metadata.name == "{{ configmap_name }}"
|
||||||
- configmap_with_ssl.metadata.namespace == test_namespace[2]
|
- configmap_with_ssl.metadata.namespace == "{{ test_namespace[2] }}"
|
||||||
- configmap_with_ssl.data.value == configmap_data
|
- configmap_with_ssl.data.value == "{{ configmap_data }}"
|
||||||
|
|
||||||
always:
|
always:
|
||||||
- name: Delete temporary directory
|
- name: Delete temporary directory
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
- name: make script as executable
|
- name: make script as executable
|
||||||
file:
|
file:
|
||||||
path: "{{ tmp_dir_path }}/install_kustomize.sh"
|
path: "{{ tmp_dir_path }}/install_kustomize.sh"
|
||||||
mode: 0755
|
mode: '0755'
|
||||||
|
|
||||||
- name: Install kustomize
|
- name: Install kustomize
|
||||||
command: "{{ tmp_dir_path }}/install_kustomize.sh"
|
command: "{{ tmp_dir_path }}/install_kustomize.sh"
|
||||||
|
|||||||
1
tests/integration/targets/push_to_helm_registry/aliases
Normal file
1
tests/integration/targets/push_to_helm_registry/aliases
Normal file
@@ -0,0 +1 @@
|
|||||||
|
disabled
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
helm_binary_path: "helm"
|
||||||
|
chart_repo_url: 'localhost:6035'
|
||||||
|
chart_repo_username: testuser
|
||||||
|
chart_repo_password: 'pass123!'
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
- name: Ensure we can log into the helm registry
|
||||||
|
command: >-
|
||||||
|
{{ helm_binary_path }} registry login
|
||||||
|
-u {{ chart_repo_username }}
|
||||||
|
-p {{ chart_repo_password }}
|
||||||
|
{{ chart_repo_url }}
|
||||||
|
|
||||||
|
- name: Package chart and push to helm registry
|
||||||
|
block:
|
||||||
|
- name: Create temporary directory to store chart
|
||||||
|
ansible.builtin.tempfile:
|
||||||
|
state: directory
|
||||||
|
suffix: .chart
|
||||||
|
register: _tmpfile
|
||||||
|
|
||||||
|
- name: Package helm chart
|
||||||
|
command: '{{ helm_binary_path }} package {{ chart_local_path }} --destination {{ _tmpfile.path }}'
|
||||||
|
|
||||||
|
- name: Locate helm chart package
|
||||||
|
ansible.builtin.find:
|
||||||
|
paths: "{{ _tmpfile.path }}"
|
||||||
|
patterns: '*.tgz'
|
||||||
|
register: _files
|
||||||
|
|
||||||
|
- name: Helm push chart to the registry
|
||||||
|
command: '{{ helm_binary_path }} push {{ _files.files.0.path }} oci://{{ chart_repo_url }}/{{ chart_repo_path }}'
|
||||||
|
|
||||||
|
always:
|
||||||
|
- name: Logout from registry
|
||||||
|
command: '{{ helm_binary_path }} registry logout {{ chart_repo_url }}'
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Delete temporary directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
state: absent
|
||||||
|
path: '{{ _tmpfile.path }}'
|
||||||
|
ignore_errors: true
|
||||||
1
tests/integration/targets/setup_helm_registry/aliases
Normal file
1
tests/integration/targets/setup_helm_registry/aliases
Normal file
@@ -0,0 +1 @@
|
|||||||
|
disabled
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
# user: testuser, password: pass123!
|
||||||
|
registry_credentials: testuser:$2y$05$d8tw6L1hojRFW.FjHOAnIOihJWAvFb0/Pu/30hLbQNJIYzCmlyBCi
|
||||||
|
registry_name: helm_registry
|
||||||
|
registry_port: 6035
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
- name: Teardown registry
|
||||||
|
include_tasks: teardown_registry.yml
|
||||||
32
tests/integration/targets/setup_helm_registry/tasks/main.yml
Normal file
32
tests/integration/targets/setup_helm_registry/tasks/main.yml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
- name: Ensure we can talk to docker daemon
|
||||||
|
ansible.builtin.shell:
|
||||||
|
cmd: docker ps
|
||||||
|
|
||||||
|
- name: Create temporary directory to store file in
|
||||||
|
tempfile:
|
||||||
|
state: directory
|
||||||
|
suffix: .helm_registry
|
||||||
|
register: _tmpfile
|
||||||
|
# notify:
|
||||||
|
# - Teardown registry
|
||||||
|
|
||||||
|
- name: Create authentication file
|
||||||
|
copy:
|
||||||
|
content: "{{ registry_credentials }}"
|
||||||
|
dest: "{{ _tmpfile.path }}/htpasswd"
|
||||||
|
|
||||||
|
- name: Remove existing registry
|
||||||
|
ansible.builtin.include_tasks: remove_docker_container.yml
|
||||||
|
|
||||||
|
- name: Create registry container
|
||||||
|
command: >-
|
||||||
|
docker run -d
|
||||||
|
-p {{ registry_port }}:5000
|
||||||
|
--restart=always
|
||||||
|
--name "{{ registry_name }}"
|
||||||
|
-v "{{ _tmpfile.path }}:/auth"
|
||||||
|
-e "REGISTRY_AUTH=htpasswd"
|
||||||
|
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm"
|
||||||
|
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd
|
||||||
|
registry:2
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
- name: Inspect docker container
|
||||||
|
command: docker container inspect {{ registry_name }} -f '{{ '{{' }} .State.Running {{ '}}' }}'
|
||||||
|
register: _inspect
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Remove container
|
||||||
|
when: _inspect.rc == 0
|
||||||
|
block:
|
||||||
|
- name: Stop running container
|
||||||
|
command: docker container stop {{ registry_name }}
|
||||||
|
when: _inspect.stdout == "true"
|
||||||
|
|
||||||
|
- name: Remove container
|
||||||
|
command: docker container rm {{ registry_name }}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
- name: Remove Docker container
|
||||||
|
ansible.builtin.include_tasks: remove_docker_container.yml
|
||||||
|
|
||||||
|
- name: Delete temporary directory
|
||||||
|
file:
|
||||||
|
state: absent
|
||||||
|
path: '{{ _tmpfile.path }}'
|
||||||
|
ignore_errors: true
|
||||||
@@ -1,9 +1,18 @@
|
|||||||
|
plugins/module_utils/client/discovery.py import-3.6!skip
|
||||||
|
plugins/module_utils/client/discovery.py import-3.7!skip
|
||||||
|
plugins/module_utils/client/discovery.py import-3.8!skip
|
||||||
plugins/module_utils/client/discovery.py import-3.9!skip
|
plugins/module_utils/client/discovery.py import-3.9!skip
|
||||||
plugins/module_utils/client/discovery.py import-3.10!skip
|
plugins/module_utils/client/discovery.py import-3.10!skip
|
||||||
plugins/module_utils/client/discovery.py import-3.11!skip
|
plugins/module_utils/client/discovery.py import-3.11!skip
|
||||||
|
plugins/module_utils/client/resource.py import-3.6!skip
|
||||||
|
plugins/module_utils/client/resource.py import-3.7!skip
|
||||||
|
plugins/module_utils/client/resource.py import-3.8!skip
|
||||||
plugins/module_utils/client/resource.py import-3.9!skip
|
plugins/module_utils/client/resource.py import-3.9!skip
|
||||||
plugins/module_utils/client/resource.py import-3.10!skip
|
plugins/module_utils/client/resource.py import-3.10!skip
|
||||||
plugins/module_utils/client/resource.py import-3.11!skip
|
plugins/module_utils/client/resource.py import-3.11!skip
|
||||||
|
plugins/module_utils/k8sdynamicclient.py import-3.6!skip
|
||||||
|
plugins/module_utils/k8sdynamicclient.py import-3.7!skip
|
||||||
|
plugins/module_utils/k8sdynamicclient.py import-3.8!skip
|
||||||
plugins/module_utils/k8sdynamicclient.py import-3.9!skip
|
plugins/module_utils/k8sdynamicclient.py import-3.9!skip
|
||||||
plugins/module_utils/k8sdynamicclient.py import-3.10!skip
|
plugins/module_utils/k8sdynamicclient.py import-3.10!skip
|
||||||
plugins/module_utils/k8sdynamicclient.py import-3.11!skip
|
plugins/module_utils/k8sdynamicclient.py import-3.11!skip
|
||||||
@@ -25,3 +34,4 @@ plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
|||||||
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
||||||
tests/integration/targets/k8s_delete/files/deployments.yaml yamllint!skip
|
tests/integration/targets/k8s_delete/files/deployments.yaml yamllint!skip
|
||||||
tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip
|
tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip
|
||||||
|
tests/integration/targets/helm_diff/files/test-chart-deployment-time/templates/configmap.yaml yamllint!skip
|
||||||
|
|||||||
@@ -1,9 +1,18 @@
|
|||||||
|
plugins/module_utils/client/discovery.py import-3.6!skip
|
||||||
|
plugins/module_utils/client/discovery.py import-3.7!skip
|
||||||
|
plugins/module_utils/client/discovery.py import-3.8!skip
|
||||||
plugins/module_utils/client/discovery.py import-3.9!skip
|
plugins/module_utils/client/discovery.py import-3.9!skip
|
||||||
plugins/module_utils/client/discovery.py import-3.10!skip
|
plugins/module_utils/client/discovery.py import-3.10!skip
|
||||||
plugins/module_utils/client/discovery.py import-3.11!skip
|
plugins/module_utils/client/discovery.py import-3.11!skip
|
||||||
|
plugins/module_utils/client/resource.py import-3.6!skip
|
||||||
|
plugins/module_utils/client/resource.py import-3.7!skip
|
||||||
|
plugins/module_utils/client/resource.py import-3.8!skip
|
||||||
plugins/module_utils/client/resource.py import-3.9!skip
|
plugins/module_utils/client/resource.py import-3.9!skip
|
||||||
plugins/module_utils/client/resource.py import-3.10!skip
|
plugins/module_utils/client/resource.py import-3.10!skip
|
||||||
plugins/module_utils/client/resource.py import-3.11!skip
|
plugins/module_utils/client/resource.py import-3.11!skip
|
||||||
|
plugins/module_utils/k8sdynamicclient.py import-3.6!skip
|
||||||
|
plugins/module_utils/k8sdynamicclient.py import-3.7!skip
|
||||||
|
plugins/module_utils/k8sdynamicclient.py import-3.8!skip
|
||||||
plugins/module_utils/k8sdynamicclient.py import-3.9!skip
|
plugins/module_utils/k8sdynamicclient.py import-3.9!skip
|
||||||
plugins/module_utils/k8sdynamicclient.py import-3.10!skip
|
plugins/module_utils/k8sdynamicclient.py import-3.10!skip
|
||||||
plugins/module_utils/k8sdynamicclient.py import-3.11!skip
|
plugins/module_utils/k8sdynamicclient.py import-3.11!skip
|
||||||
@@ -26,3 +35,4 @@ plugins/modules/k8s_scale.py validate-modules:return-syntax-error
|
|||||||
plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
||||||
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
||||||
tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip
|
tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip
|
||||||
|
tests/integration/targets/helm_diff/files/test-chart-deployment-time/templates/configmap.yaml yamllint!skip
|
||||||
|
|||||||
@@ -1,11 +1,20 @@
|
|||||||
|
plugins/module_utils/client/discovery.py import-3.6!skip
|
||||||
|
plugins/module_utils/client/discovery.py import-3.7!skip
|
||||||
|
plugins/module_utils/client/discovery.py import-3.8!skip
|
||||||
plugins/module_utils/client/discovery.py import-3.9!skip
|
plugins/module_utils/client/discovery.py import-3.9!skip
|
||||||
plugins/module_utils/client/discovery.py import-3.10!skip
|
plugins/module_utils/client/discovery.py import-3.10!skip
|
||||||
plugins/module_utils/client/discovery.py import-3.11!skip
|
plugins/module_utils/client/discovery.py import-3.11!skip
|
||||||
plugins/module_utils/client/discovery.py import-3.12!skip
|
plugins/module_utils/client/discovery.py import-3.12!skip
|
||||||
|
plugins/module_utils/client/resource.py import-3.6!skip
|
||||||
|
plugins/module_utils/client/resource.py import-3.7!skip
|
||||||
|
plugins/module_utils/client/resource.py import-3.8!skip
|
||||||
plugins/module_utils/client/resource.py import-3.9!skip
|
plugins/module_utils/client/resource.py import-3.9!skip
|
||||||
plugins/module_utils/client/resource.py import-3.10!skip
|
plugins/module_utils/client/resource.py import-3.10!skip
|
||||||
plugins/module_utils/client/resource.py import-3.11!skip
|
plugins/module_utils/client/resource.py import-3.11!skip
|
||||||
plugins/module_utils/client/resource.py import-3.12!skip
|
plugins/module_utils/client/resource.py import-3.12!skip
|
||||||
|
plugins/module_utils/k8sdynamicclient.py import-3.6!skip
|
||||||
|
plugins/module_utils/k8sdynamicclient.py import-3.7!skip
|
||||||
|
plugins/module_utils/k8sdynamicclient.py import-3.8!skip
|
||||||
plugins/module_utils/k8sdynamicclient.py import-3.9!skip
|
plugins/module_utils/k8sdynamicclient.py import-3.9!skip
|
||||||
plugins/module_utils/k8sdynamicclient.py import-3.10!skip
|
plugins/module_utils/k8sdynamicclient.py import-3.10!skip
|
||||||
plugins/module_utils/k8sdynamicclient.py import-3.11!skip
|
plugins/module_utils/k8sdynamicclient.py import-3.11!skip
|
||||||
@@ -29,3 +38,4 @@ plugins/modules/k8s_scale.py validate-modules:return-syntax-error
|
|||||||
plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
||||||
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
||||||
tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip
|
tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip
|
||||||
|
tests/integration/targets/helm_diff/files/test-chart-deployment-time/templates/configmap.yaml yamllint!skip
|
||||||
|
|||||||
@@ -29,3 +29,4 @@ plugins/modules/k8s_scale.py validate-modules:return-syntax-error
|
|||||||
plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
||||||
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
||||||
tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip
|
tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip
|
||||||
|
tests/integration/targets/helm_diff/files/test-chart-deployment-time/templates/configmap.yaml yamllint!skip
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
plugins/module_utils/client/discovery.py import-3.9!skip
|
|
||||||
plugins/module_utils/client/discovery.py import-3.10!skip
|
|
||||||
plugins/module_utils/client/discovery.py import-3.11!skip
|
plugins/module_utils/client/discovery.py import-3.11!skip
|
||||||
plugins/module_utils/client/discovery.py import-3.12!skip
|
plugins/module_utils/client/discovery.py import-3.12!skip
|
||||||
plugins/module_utils/client/resource.py import-3.9!skip
|
plugins/module_utils/client/discovery.py import-3.13!skip
|
||||||
plugins/module_utils/client/resource.py import-3.10!skip
|
|
||||||
plugins/module_utils/client/resource.py import-3.11!skip
|
plugins/module_utils/client/resource.py import-3.11!skip
|
||||||
plugins/module_utils/client/resource.py import-3.12!skip
|
plugins/module_utils/client/resource.py import-3.12!skip
|
||||||
plugins/module_utils/k8sdynamicclient.py import-3.9!skip
|
plugins/module_utils/client/resource.py import-3.13!skip
|
||||||
plugins/module_utils/k8sdynamicclient.py import-3.10!skip
|
|
||||||
plugins/module_utils/k8sdynamicclient.py import-3.11!skip
|
plugins/module_utils/k8sdynamicclient.py import-3.11!skip
|
||||||
plugins/module_utils/k8sdynamicclient.py import-3.12!skip
|
plugins/module_utils/k8sdynamicclient.py import-3.12!skip
|
||||||
|
plugins/module_utils/k8sdynamicclient.py import-3.13!skip
|
||||||
plugins/module_utils/version.py pylint!skip
|
plugins/module_utils/version.py pylint!skip
|
||||||
plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc
|
plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc
|
||||||
plugins/modules/k8s_scale.py validate-modules:parameter-type-not-in-doc
|
plugins/modules/k8s_scale.py validate-modules:parameter-type-not-in-doc
|
||||||
@@ -29,3 +26,4 @@ plugins/modules/k8s_scale.py validate-modules:return-syntax-error
|
|||||||
plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
||||||
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
||||||
tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip
|
tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip
|
||||||
|
tests/integration/targets/helm_diff/files/test-chart-deployment-time/templates/configmap.yaml yamllint!skip
|
||||||
|
|||||||
29
tests/sanity/ignore-2.19.txt
Normal file
29
tests/sanity/ignore-2.19.txt
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
plugins/module_utils/client/discovery.py import-3.11!skip
|
||||||
|
plugins/module_utils/client/discovery.py import-3.12!skip
|
||||||
|
plugins/module_utils/client/discovery.py import-3.13!skip
|
||||||
|
plugins/module_utils/client/resource.py import-3.11!skip
|
||||||
|
plugins/module_utils/client/resource.py import-3.12!skip
|
||||||
|
plugins/module_utils/client/resource.py import-3.13!skip
|
||||||
|
plugins/module_utils/k8sdynamicclient.py import-3.11!skip
|
||||||
|
plugins/module_utils/k8sdynamicclient.py import-3.12!skip
|
||||||
|
plugins/module_utils/k8sdynamicclient.py import-3.13!skip
|
||||||
|
plugins/module_utils/version.py pylint!skip
|
||||||
|
plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc
|
||||||
|
plugins/modules/k8s_scale.py validate-modules:parameter-type-not-in-doc
|
||||||
|
plugins/modules/k8s_service.py validate-modules:parameter-type-not-in-doc
|
||||||
|
tests/unit/module_utils/fixtures/definitions.yml yamllint!skip
|
||||||
|
tests/unit/module_utils/fixtures/deployments.yml yamllint!skip
|
||||||
|
tests/integration/targets/k8s_delete/files/deployments.yaml yamllint!skip
|
||||||
|
tests/unit/module_utils/fixtures/pods.yml yamllint!skip
|
||||||
|
tests/integration/targets/helm/files/appversionless-chart-v2/templates/configmap.yaml yamllint!skip
|
||||||
|
tests/integration/targets/helm/files/appversionless-chart/templates/configmap.yaml yamllint!skip
|
||||||
|
tests/integration/targets/helm/files/test-chart-v2/templates/configmap.yaml yamllint!skip
|
||||||
|
tests/integration/targets/helm/files/test-chart/templates/configmap.yaml yamllint!skip
|
||||||
|
tests/integration/targets/helm_diff/files/test-chart/templates/configmap.yaml yamllint!skip
|
||||||
|
tests/integration/targets/k8s_scale/files/deployment.yaml yamllint!skip
|
||||||
|
plugins/modules/k8s.py validate-modules:return-syntax-error
|
||||||
|
plugins/modules/k8s_scale.py validate-modules:return-syntax-error
|
||||||
|
plugins/modules/k8s_service.py validate-modules:return-syntax-error
|
||||||
|
plugins/modules/k8s_taint.py validate-modules:return-syntax-error
|
||||||
|
tests/integration/targets/helm_diff/files/test-chart-reuse-values/templates/configmap.yaml yamllint!skip
|
||||||
|
tests/integration/targets/helm_diff/files/test-chart-deployment-time/templates/configmap.yaml yamllint!skip
|
||||||
@@ -200,6 +200,10 @@ def test_module_get_values(_ansible_helm_module, no_values, get_all):
|
|||||||
'version.BuildInfo{Version:"v3.10.3", GitCommit:7870ab3ed4135f136eec, GoVersion:"go1.18.9"}',
|
'version.BuildInfo{Version:"v3.10.3", GitCommit:7870ab3ed4135f136eec, GoVersion:"go1.18.9"}',
|
||||||
"3.10.3",
|
"3.10.3",
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
'version.BuildInfo{Version:"v3.15.0-rc.1", GitCommit:"d7afa3b6b432c09a02cd07342e908ba5bed34940", GitTreeState:"clean", GoVersion:"go1.22.4"}',
|
||||||
|
"3.15.0-rc.1",
|
||||||
|
),
|
||||||
('Client: &version.Version{SemVer:"v3.12.3", ', "3.12.3"),
|
('Client: &version.Version{SemVer:"v3.12.3", ', "3.12.3"),
|
||||||
('Client: &version.Version{SemVer:"v3.12.3"', None),
|
('Client: &version.Version{SemVer:"v3.12.3"', None),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ modified_def["metadata"]["labels"]["environment"] = "testing"
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"action, params, existing, instance_warnings, expected",
|
"action, params, existing, instance, expected",
|
||||||
[
|
[
|
||||||
(
|
(
|
||||||
"delete",
|
"delete",
|
||||||
@@ -51,26 +51,14 @@ modified_def["metadata"]["labels"]["environment"] = "testing"
|
|||||||
"apply",
|
"apply",
|
||||||
{"apply": "yes"},
|
{"apply": "yes"},
|
||||||
{},
|
{},
|
||||||
(definition, []),
|
definition,
|
||||||
{"changed": True, "method": "apply", "result": definition},
|
{"changed": True, "method": "apply", "result": definition},
|
||||||
),
|
),
|
||||||
(
|
|
||||||
"apply",
|
|
||||||
{"apply": "yes"},
|
|
||||||
{},
|
|
||||||
(definition, ["test warning"]),
|
|
||||||
{
|
|
||||||
"changed": True,
|
|
||||||
"method": "apply",
|
|
||||||
"result": definition,
|
|
||||||
"warnings": ["test warning"],
|
|
||||||
},
|
|
||||||
),
|
|
||||||
(
|
(
|
||||||
"create",
|
"create",
|
||||||
{"state": "patched"},
|
{"state": "patched"},
|
||||||
{},
|
{},
|
||||||
({}, []),
|
{},
|
||||||
{
|
{
|
||||||
"changed": False,
|
"changed": False,
|
||||||
"result": {},
|
"result": {},
|
||||||
@@ -83,78 +71,42 @@ modified_def["metadata"]["labels"]["environment"] = "testing"
|
|||||||
"create",
|
"create",
|
||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
(definition, []),
|
definition,
|
||||||
{"changed": True, "method": "create", "result": definition},
|
{"changed": True, "method": "create", "result": definition},
|
||||||
),
|
),
|
||||||
(
|
|
||||||
"create",
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
(definition, ["test warning"]),
|
|
||||||
{
|
|
||||||
"changed": True,
|
|
||||||
"method": "create",
|
|
||||||
"result": definition,
|
|
||||||
"warnings": ["test warning"],
|
|
||||||
},
|
|
||||||
),
|
|
||||||
(
|
(
|
||||||
"replace",
|
"replace",
|
||||||
{"force": "yes"},
|
{"force": "yes"},
|
||||||
definition,
|
definition,
|
||||||
(definition, []),
|
definition,
|
||||||
{"changed": False, "method": "replace", "result": definition},
|
{"changed": False, "method": "replace", "result": definition},
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"replace",
|
"replace",
|
||||||
{"force": "yes"},
|
{"force": "yes"},
|
||||||
definition,
|
definition,
|
||||||
(modified_def, []),
|
modified_def,
|
||||||
{"changed": True, "method": "replace", "result": modified_def},
|
{"changed": True, "method": "replace", "result": modified_def},
|
||||||
),
|
),
|
||||||
(
|
|
||||||
"replace",
|
|
||||||
{"force": "yes"},
|
|
||||||
definition,
|
|
||||||
(modified_def, ["test warning"]),
|
|
||||||
{
|
|
||||||
"changed": True,
|
|
||||||
"method": "replace",
|
|
||||||
"result": modified_def,
|
|
||||||
"warnings": ["test warning"],
|
|
||||||
},
|
|
||||||
),
|
|
||||||
(
|
(
|
||||||
"update",
|
"update",
|
||||||
{},
|
{},
|
||||||
definition,
|
definition,
|
||||||
(definition, []),
|
definition,
|
||||||
{"changed": False, "method": "update", "result": definition},
|
{"changed": False, "method": "update", "result": definition},
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"update",
|
"update",
|
||||||
{},
|
{},
|
||||||
definition,
|
definition,
|
||||||
(modified_def, []),
|
modified_def,
|
||||||
{"changed": True, "method": "update", "result": modified_def},
|
{"changed": True, "method": "update", "result": modified_def},
|
||||||
),
|
),
|
||||||
(
|
|
||||||
"update",
|
|
||||||
{},
|
|
||||||
definition,
|
|
||||||
(modified_def, ["test warning"]),
|
|
||||||
{
|
|
||||||
"changed": True,
|
|
||||||
"method": "update",
|
|
||||||
"result": modified_def,
|
|
||||||
"warnings": ["test warning"],
|
|
||||||
},
|
|
||||||
),
|
|
||||||
(
|
(
|
||||||
"create",
|
"create",
|
||||||
{"label_selectors": ["app=foo"]},
|
{"label_selectors": ["app=foo"]},
|
||||||
{},
|
{},
|
||||||
(definition, []),
|
definition,
|
||||||
{
|
{
|
||||||
"changed": False,
|
"changed": False,
|
||||||
"msg": "resource 'kind=Pod,name=foo,namespace=foo' filtered by label_selectors.",
|
"msg": "resource 'kind=Pod,name=foo,namespace=foo' filtered by label_selectors.",
|
||||||
@@ -164,18 +116,18 @@ modified_def["metadata"]["labels"]["environment"] = "testing"
|
|||||||
"create",
|
"create",
|
||||||
{"label_selectors": ["app=nginx"]},
|
{"label_selectors": ["app=nginx"]},
|
||||||
{},
|
{},
|
||||||
(definition, []),
|
definition,
|
||||||
{"changed": True, "method": "create", "result": definition},
|
{"changed": True, "method": "create", "result": definition},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_perform_action(action, params, existing, instance_warnings, expected):
|
def test_perform_action(action, params, existing, instance, expected):
|
||||||
svc = Mock()
|
svc = Mock()
|
||||||
svc.find_resource.return_value = Mock(
|
svc.find_resource.return_value = Mock(
|
||||||
kind=definition["kind"], group_version=definition["apiVersion"]
|
kind=definition["kind"], group_version=definition["apiVersion"]
|
||||||
)
|
)
|
||||||
svc.retrieve.return_value = ResourceInstance(None, existing) if existing else None
|
svc.retrieve.return_value = ResourceInstance(None, existing) if existing else None
|
||||||
spec = {action + ".return_value": instance_warnings}
|
spec = {action + ".return_value": instance}
|
||||||
svc.configure_mock(**spec)
|
svc.configure_mock(**spec)
|
||||||
|
|
||||||
result = perform_action(svc, definition, params)
|
result = perform_action(svc, definition, params)
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
from json import dumps
|
|
||||||
from unittest.mock import Mock
|
from unittest.mock import Mock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.service import (
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.service import (
|
||||||
K8sService,
|
K8sService,
|
||||||
diff_objects,
|
diff_objects,
|
||||||
parse_quoted_string,
|
|
||||||
)
|
)
|
||||||
from kubernetes.dynamic.exceptions import NotFoundError
|
from kubernetes.dynamic.exceptions import NotFoundError
|
||||||
from kubernetes.dynamic.resource import Resource, ResourceInstance
|
from kubernetes.dynamic.resource import Resource, ResourceInstance
|
||||||
@@ -59,22 +57,6 @@ def mock_pod_updated_resource_instance():
|
|||||||
return ResourceInstance(None, pod_definition_updated)
|
return ResourceInstance(None, pod_definition_updated)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
|
||||||
def mock_pod_response():
|
|
||||||
resp = Mock()
|
|
||||||
resp.data.decode.return_value = dumps(pod_definition)
|
|
||||||
resp.headers = {}
|
|
||||||
return resp
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
|
||||||
def mock_pod_warnings_response():
|
|
||||||
resp = Mock()
|
|
||||||
resp.data.decode.return_value = dumps(pod_definition)
|
|
||||||
resp.headers = {"warning": '299 - "test warning 1", 299 - "test warning 2"'}
|
|
||||||
return resp
|
|
||||||
|
|
||||||
|
|
||||||
def test_diff_objects_no_diff():
|
def test_diff_objects_no_diff():
|
||||||
match, diff = diff_objects(pod_definition, pod_definition)
|
match, diff = diff_objects(pod_definition, pod_definition)
|
||||||
|
|
||||||
@@ -177,33 +159,16 @@ def test_service_delete_existing_resource_check_mode(mock_pod_resource_instance)
|
|||||||
client.delete.assert_not_called()
|
client.delete.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
def test_service_create_resource(mock_pod_response, mock_pod_resource_instance):
|
def test_service_create_resource(mock_pod_resource_instance):
|
||||||
spec = {"create.side_effect": [mock_pod_response]}
|
spec = {"create.side_effect": [mock_pod_resource_instance]}
|
||||||
client = Mock(**spec)
|
client = Mock(**spec)
|
||||||
module = Mock()
|
module = Mock()
|
||||||
module.params = {}
|
module.params = {}
|
||||||
module.check_mode = False
|
module.check_mode = False
|
||||||
svc = K8sService(client, module)
|
svc = K8sService(client, module)
|
||||||
result, warnings = svc.create(Mock(), pod_definition)
|
result = svc.create(Mock(), pod_definition)
|
||||||
|
|
||||||
assert result == mock_pod_resource_instance.to_dict()
|
assert result == mock_pod_resource_instance.to_dict()
|
||||||
assert not warnings
|
|
||||||
|
|
||||||
|
|
||||||
def test_service_create_resource_warnings(
|
|
||||||
mock_pod_warnings_response, mock_pod_resource_instance
|
|
||||||
):
|
|
||||||
spec = {"create.side_effect": [mock_pod_warnings_response]}
|
|
||||||
client = Mock(**spec)
|
|
||||||
module = Mock()
|
|
||||||
module.params = {}
|
|
||||||
module.check_mode = False
|
|
||||||
svc = K8sService(client, module)
|
|
||||||
result, warnings = svc.create(Mock(), pod_definition)
|
|
||||||
|
|
||||||
assert result == mock_pod_resource_instance.to_dict()
|
|
||||||
assert warnings[0] == "test warning 1"
|
|
||||||
assert warnings[1] == "test warning 2"
|
|
||||||
|
|
||||||
|
|
||||||
def test_service_create_resource_check_mode():
|
def test_service_create_resource_check_mode():
|
||||||
@@ -211,10 +176,9 @@ def test_service_create_resource_check_mode():
|
|||||||
client.create.return_value = mock_pod_resource_instance
|
client.create.return_value = mock_pod_resource_instance
|
||||||
module = Mock(params={}, check_mode=True)
|
module = Mock(params={}, check_mode=True)
|
||||||
svc = K8sService(client, module)
|
svc = K8sService(client, module)
|
||||||
result, warnings = svc.create(Mock(), pod_definition)
|
result = svc.create(Mock(), pod_definition)
|
||||||
|
|
||||||
assert result == pod_definition
|
assert result == pod_definition
|
||||||
assert not warnings
|
|
||||||
client.create.assert_not_called()
|
client.create.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
@@ -260,99 +224,40 @@ def test_create_project_request():
|
|||||||
assert results["result"] == project_definition
|
assert results["result"] == project_definition
|
||||||
|
|
||||||
|
|
||||||
def test_service_apply_existing_resource(mock_pod_response, mock_pod_resource_instance):
|
def test_service_apply_existing_resource(mock_pod_resource_instance):
|
||||||
spec = {"apply.side_effect": [mock_pod_response]}
|
spec = {"apply.side_effect": [mock_pod_resource_instance]}
|
||||||
client = Mock(**spec)
|
client = Mock(**spec)
|
||||||
module = Mock()
|
module = Mock()
|
||||||
module.params = {"apply": True}
|
module.params = {"apply": True}
|
||||||
module.check_mode = False
|
module.check_mode = False
|
||||||
svc = K8sService(client, module)
|
svc = K8sService(client, module)
|
||||||
result, warnings = svc.apply(
|
result = svc.apply(Mock(), pod_definition_updated, mock_pod_resource_instance)
|
||||||
Mock(), pod_definition_updated, mock_pod_resource_instance
|
|
||||||
)
|
|
||||||
|
|
||||||
assert result == mock_pod_resource_instance.to_dict()
|
assert result == mock_pod_resource_instance.to_dict()
|
||||||
assert not warnings
|
|
||||||
|
|
||||||
|
|
||||||
def test_service_apply_existing_resource_warnings(
|
def test_service_replace_existing_resource(mock_pod_resource_instance):
|
||||||
mock_pod_warnings_response, mock_pod_resource_instance
|
spec = {"replace.side_effect": [mock_pod_resource_instance]}
|
||||||
):
|
|
||||||
spec = {"apply.side_effect": [mock_pod_warnings_response]}
|
|
||||||
client = Mock(**spec)
|
|
||||||
module = Mock()
|
|
||||||
module.params = {"apply": True}
|
|
||||||
module.check_mode = False
|
|
||||||
svc = K8sService(client, module)
|
|
||||||
result, warnings = svc.apply(
|
|
||||||
Mock(), pod_definition_updated, mock_pod_resource_instance
|
|
||||||
)
|
|
||||||
|
|
||||||
assert result == mock_pod_resource_instance.to_dict()
|
|
||||||
assert warnings[0] == "test warning 1"
|
|
||||||
assert warnings[1] == "test warning 2"
|
|
||||||
|
|
||||||
|
|
||||||
def test_service_replace_existing_resource(
|
|
||||||
mock_pod_response, mock_pod_resource_instance
|
|
||||||
):
|
|
||||||
spec = {"replace.side_effect": [mock_pod_response]}
|
|
||||||
client = Mock(**spec)
|
client = Mock(**spec)
|
||||||
module = Mock()
|
module = Mock()
|
||||||
module.params = {}
|
module.params = {}
|
||||||
module.check_mode = False
|
module.check_mode = False
|
||||||
svc = K8sService(client, module)
|
svc = K8sService(client, module)
|
||||||
result, warnings = svc.replace(Mock(), pod_definition, mock_pod_resource_instance)
|
result = svc.replace(Mock(), pod_definition, mock_pod_resource_instance)
|
||||||
|
|
||||||
assert result == mock_pod_resource_instance.to_dict()
|
assert result == mock_pod_resource_instance.to_dict()
|
||||||
assert not warnings
|
|
||||||
|
|
||||||
|
|
||||||
def test_service_replace_existing_resource_warnings(
|
def test_service_update_existing_resource(mock_pod_resource_instance):
|
||||||
mock_pod_warnings_response, mock_pod_resource_instance
|
spec = {"replace.side_effect": [mock_pod_resource_instance]}
|
||||||
):
|
|
||||||
spec = {"replace.side_effect": [mock_pod_warnings_response]}
|
|
||||||
client = Mock(**spec)
|
client = Mock(**spec)
|
||||||
module = Mock()
|
module = Mock()
|
||||||
module.params = {}
|
module.params = {}
|
||||||
module.check_mode = False
|
module.check_mode = False
|
||||||
svc = K8sService(client, module)
|
svc = K8sService(client, module)
|
||||||
result, warnings = svc.replace(Mock(), pod_definition, mock_pod_resource_instance)
|
result = svc.replace(Mock(), pod_definition, mock_pod_resource_instance)
|
||||||
|
|
||||||
assert result == mock_pod_resource_instance.to_dict()
|
assert result == mock_pod_resource_instance.to_dict()
|
||||||
assert warnings[0] == "test warning 1"
|
|
||||||
assert warnings[1] == "test warning 2"
|
|
||||||
|
|
||||||
|
|
||||||
def test_service_update_existing_resource(
|
|
||||||
mock_pod_response, mock_pod_resource_instance
|
|
||||||
):
|
|
||||||
spec = {"replace.side_effect": [mock_pod_response]}
|
|
||||||
client = Mock(**spec)
|
|
||||||
module = Mock()
|
|
||||||
module.params = {}
|
|
||||||
module.check_mode = False
|
|
||||||
svc = K8sService(client, module)
|
|
||||||
result, warnings = svc.replace(Mock(), pod_definition, mock_pod_resource_instance)
|
|
||||||
|
|
||||||
assert result == mock_pod_resource_instance.to_dict()
|
|
||||||
assert not warnings
|
|
||||||
|
|
||||||
|
|
||||||
def test_service_update_existing_resource_warnings(
|
|
||||||
mock_pod_warnings_response, mock_pod_resource_instance
|
|
||||||
):
|
|
||||||
spec = {"replace.side_effect": [mock_pod_warnings_response]}
|
|
||||||
client = Mock(**spec)
|
|
||||||
module = Mock()
|
|
||||||
module.params = {}
|
|
||||||
module.check_mode = False
|
|
||||||
svc = K8sService(client, module)
|
|
||||||
result, warnings = svc.replace(Mock(), pod_definition, mock_pod_resource_instance)
|
|
||||||
|
|
||||||
assert result == mock_pod_resource_instance.to_dict()
|
|
||||||
assert warnings[0] == "test warning 1"
|
|
||||||
assert warnings[1] == "test warning 2"
|
|
||||||
|
|
||||||
|
|
||||||
def test_service_find(mock_pod_resource_instance):
|
def test_service_find(mock_pod_resource_instance):
|
||||||
@@ -383,24 +288,3 @@ def test_service_find_error():
|
|||||||
assert isinstance(results, dict)
|
assert isinstance(results, dict)
|
||||||
assert results["api_found"] is True
|
assert results["api_found"] is True
|
||||||
assert results["resources"] == []
|
assert results["resources"] == []
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"quoted_string,expected_val,expected_remainder",
|
|
||||||
[
|
|
||||||
(
|
|
||||||
'"Response is stale" Tue, 15 Nov 1994 12:45:26 GMT',
|
|
||||||
"Response is stale",
|
|
||||||
"Tue, 15 Nov 1994 12:45:26 GMT",
|
|
||||||
),
|
|
||||||
(
|
|
||||||
'"unknown field \\"spec.template.spec.disk\\""',
|
|
||||||
'unknown field "spec.template.spec.disk"',
|
|
||||||
"",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_parse_quoted_string(quoted_string, expected_val, expected_remainder):
|
|
||||||
val, remainder = parse_quoted_string(quoted_string)
|
|
||||||
assert val == expected_val
|
|
||||||
assert remainder == expected_remainder
|
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
import os
|
|
||||||
import sys
|
|
||||||
from pathlib import PosixPath
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
|
|
||||||
src = sys.argv[1]
|
|
||||||
path = PosixPath(src) / PosixPath("tests/integration/targets/")
|
|
||||||
|
|
||||||
def _is_disable(path):
|
|
||||||
flags = ("unsupported", "disabled", "unstable", "hidden")
|
|
||||||
aliases_path = path / PosixPath("aliases")
|
|
||||||
return (aliases_path.exists() and any((d.startswith(flags) for d in aliases_path.read_text().split("\n"))))
|
|
||||||
|
|
||||||
targets = [i.stem for i in path.glob("*") if i.is_dir() and not _is_disable(i)]
|
|
||||||
with open(os.environ.get("GITHUB_OUTPUT"), "a", encoding="utf-8") as fw:
|
|
||||||
fw.write(f"kubevirt_targets={targets}\n")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
Reference in New Issue
Block a user