Compare commits

..

26 Commits

Author SHA1 Message Date
Bikouo Aubin
7b0190f8d5 Prepare release 5.0.0 (#733) 2024-06-10 15:39:42 +02:00
patchback[bot]
c47e691101 Doc: add example of using kubectl connection plugin (#741) (#744)
[PR #741/fb80d973 backport][stable-5] Doc: add example of using kubectl connection plugin

This is a backport of PR #741 as merged into main (fb80d97).
SUMMARY
Currently documentation for collection don't include any examples of using kubenrenes.core.kubectl connection plugin and it's hard to start using that plugin.
ISSUE TYPE

Docs Pull Request

COMPONENT NAME
kubenrenes.core.kubectl connection plugin
ADDITIONAL INFORMATION
This PR was inspired by #288 and based on feedback on that PR and my own experience. Thanks @tpo for his try and @geerlingguy for his Ansible for DevOps book

Reviewed-by: Mike Graves <mgraves@redhat.com>
2024-06-06 14:34:01 +00:00
patchback[bot]
8ae6469696 Defer removal of inventory/k8s to 6.0.0 (#734) (#740)
Defer removal of inventory/k8s to 6.0.0

SUMMARY
Defer removal of inventory plugin k8s to release 6.0.0.

ISSUE TYPE

Feature Pull Request

Reviewed-by: Alina Buzachis
Reviewed-by: Mike Graves <mgraves@redhat.com>
(cherry picked from commit 0c5233a650)

Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>
2024-05-31 10:09:39 +02:00
patchback[bot]
1174fee5c9 Remove support for ansible-core<2.15 (#737) (#739)
Drop support for ansible-core<2.15

SUMMARY

Remove support for ansible-core<2.15

ISSUE TYPE

Feature Pull Request

Reviewed-by: Mike Graves <mgraves@redhat.com>
(cherry picked from commit 8363a4debf)

Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>
2024-05-31 10:06:48 +02:00
Bikouo Aubin
f22ffcab18 Prepare release 4.0.0 (#727)
* Prepare release 4.0.0

* update documentation
2024-05-28 11:37:32 +02:00
Bikouo Aubin
072a08091b Remove deprecated function from module_utils/common.py (#726)
Remove deprecated function from module_utils/common.py

SUMMARY

Remove deprecated functions and class from module_utils/common.py in order to prepare release 4.0.0

ISSUE TYPE


Feature Pull Request

COMPONENT NAME

module_utils/common.py

Reviewed-by: Alina Buzachis
2024-05-24 05:29:46 +00:00
Alina Buzachis
cbadbe32f9 Defer removal of k8s inventory plugin to version 5.0. (#723)
Defer removal of k8s inventory plugin to version 5.0.

SUMMARY

Defer removal of k8s inventory plugin to version 5.0.

ISSUE TYPE


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

COMPONENT NAME

inventory/k8s.py
ADDITIONAL INFORMATION

Reviewed-by: Bikouo Aubin
Reviewed-by: Mike Graves <mgraves@redhat.com>
2024-05-22 10:13:50 +00:00
Alina Buzachis
966fa7e906 k8s - remove support for merge_type=json (#722)
k8s - remove support for merge_type=json

SUMMARY

Support for merge_type=json has been removed in version 4.0.0. Please use kubernetes.core.k8s_json_patch instead.

ISSUE TYPE


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

COMPONENT NAME

k8s.py
ADDITIONAL INFORMATION

Reviewed-by: Bikouo Aubin
Reviewed-by: Mike Graves <mgraves@redhat.com>
2024-05-22 10:13:47 +00:00
Mike Graves
485eae3b10 Release 3.1.0 (#719) (#720)
Sync stable-3 to main branch (#719)

Release 3.1.0
SUMMARY
Release prep for 3.1.0
ISSUE TYPE
Bugfix Pull Request
Docs Pull Request
Feature Pull Request
New Module Pull Request
COMPONENT NAME
ADDITIONAL INFORMATION
Reviewed-by: Alina Buzachis
Reviewed-by: Helen Bailey hebailey@redhat.com
(cherry picked from commit ef829b8)

Reviewed-by: Alina Buzachis
2024-05-16 18:43:34 +00:00
Conner Crosby
a4c1bd8541 Update deprecation version for merge_type=json (#700)
Update deprecation version for merge_type=json

SUMMARY
When looking at the parts of plugins/module_utils/common.py and plugins/module_utils/k8s/service.py during the post 3.0.0 release (see https://github.com/ansible-collections/kubernetes.core/pull/663/files#diff-9ee2d0860a5643da4e1f35136e9e7c3a41c5f2fd2952c197e7e32b941e5a301c) that affect merge_type when set to json, I don't believe merge_type=json was deprecated for (and removed from) the k8s module, and instead the deprecation version has moved to 4.0.0. Hence, the documentation update.
ISSUE TYPE

Docs Pull Request

COMPONENT NAME
k8s module

Reviewed-by: Mike Graves <mgraves@redhat.com>
2024-05-15 18:02:55 +00:00
Mike Graves
8858b19121 Fix unsafe text assertion in tests (#716)
Fix unsafe text assertion in tests

SUMMARY

This fixes a problem with unsafe text in an assertion.

ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME

ADDITIONAL INFORMATION

Reviewed-by: GomathiselviS
Reviewed-by: Bikouo Aubin
2024-05-15 06:50:26 +00:00
Yuriy Novostavskiy
6360763098 minor: doc: use the same style of version_added across repo (#703)
minor(doc): use the same style of version_added across repo

SUMMARY
Currently is no single style of version_added, in some places it's unquoted, somewhere single quote is used, in another places it's double quoted. Moreover, some file had different styles in one single file.
The aim of this PR is to update whole repo to single style for version_added
ISSUE TYPE

Docs Pull Request

COMPONENT NAME
kustomize
helm
helm_info
helm_plugin
helm_plugin_info
helm_pull
helm_repository
helm_template
k8s_cluster_info
k8s_cp
k8s_drain
k8s_exec
k8s_log
k8s_rollback
k8s_taint
ADDITIONAL INFORMATION
The same style is proposed as used in amazon.aws collections

Reviewed-by: Kelv Gooding
Reviewed-by: Alina Buzachis
Reviewed-by: Mike Graves <mgraves@redhat.com>
2024-05-14 15:50:12 +00:00
Dennis Ochocki
ac943e9890 fixed typo in filename of 'k8s_json_patch'-action (#652)
fixed typo in filename of 'k8s_json_patch'-action 

SUMMARY

The filename/symlink of the action for the 'k8s_json_patch'-module was wrong. Renamed file from 'ks8_json_patch.py' to ' k8s_json_patch.py'

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME

k8s_json_patch
ADDITIONAL INFORMATION


Because of the wrong filename things like unvaulting kubeconfig files did not worked.

Reviewed-by: Mike Graves <mgraves@redhat.com>
2024-05-14 15:48:01 +00:00
John Lathouwers
0408aa9328 Update kustomize.py add --enable-helm support (#592)
Update kustomize.py add --enable-helm support

Add --enable-helm support
SUMMARY
Fixes #568
ISSUE TYPE

Feature Pull Request

COMPONENT NAME
Lookup plugin: kubernetes.core.kustomize
ADDITIONAL INFORMATION
Current and maintained arg:
lookup('kubernetes.core.kustomize', dir=item)

Additional feature args:
lookup('kubernetes.core.kustomize', dir=item, enable_helm=false)
lookup('kubernetes.core.kustomize', dir=item, enable_helm=true)

Reviewed-by: Mike Graves <mgraves@redhat.com>
2024-05-13 17:16:16 +00:00
Mike Graves
874fbfedd5 Merge pull request #707 from gravesm/linting-fix
Update ansible-lint GHA
2024-05-08 11:09:30 -04:00
Mike Graves
d8d9133912 Update ansible-lint GHA
There seems to be a bug in older versions of ansible-lint where pinning
to a version for the GHA still installs the main branch.
2024-05-07 12:35:35 -04:00
Alina Buzachis
86d9a3f45f Add tests/sanity/ignore-2.18.txt (#704)
Add tests/sanity/ignore-2.18.txt

SUMMARY

Add tests/sanity/ignore-2.18.txt

ISSUE TYPE


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

COMPONENT NAME

ADDITIONAL INFORMATION

Reviewed-by: Mike Graves <mgraves@redhat.com>
2024-05-07 15:27:13 +00:00
Yuriy Novostavskiy
fb25ff44f1 add support of kubectl_local_env_vars (#698) (#702)
add support of kubectl_local_env_vars (#698)

SUMMARY
Support of local environmental variable that may be required to be set on Ansible Controller before the connection is set and may be used for kubectl command. This PR addressed for #698
The main idea is to have the support of  additional/extra local environmental variable that may be required for kubectl itself, i.e. for authorization in case of public clouds
ISSUE TYPE

Feature Pull Request

COMPONENT NAME
kubernetes.core.kubectl connection plugin
ADDITIONAL INFORMATION
This PR attempts to implement local env support for the kubectl connection plugin that may be useful in case of using kubectl against public cloud kubernetes environment that uses some authorization (i.e. aws cli) additionally to kubeconfig file. More detail in #698
The output that shows that the connection plugin can use local environment variable for kubectl command (with some debug that used during development but removed then):
root@ubuntu-shell:/# cat test.yaml
- hosts: localhost
  gather_facts: no
  any_errors_fatal: yes
  vars:
    ansible_connection: "kubectl"
    ansible_kubectl_namespace: "test"
    ansible_kubectl_config: "/.kube/config"
    ansible_kubectl_pod: "ubuntu"
    ansible_kubectl_container: "ubuntu"
    ansible_kubectl_local_env_vars:
      TESTVAR1: "test"
      TESTVAR2: "test"
      TESTVAR3: "test"
  environment:
    TEST_ENV1: value1
    TEST_ENV2: value2

  tasks:
  - name: test
    ansible.builtin.shell: env
    register: result
  - debug:
      var: result.stdout_lines
root@ubuntu-shell:/# ansible-playbook test.yaml
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] **************************************************************************************************************************************

TASK [test] *******************************************************************************************************************************************
changed: [localhost]

TASK [debug] ******************************************************************************************************************************************
ok: [localhost] => {
    "result.stdout_lines": [
        "KUBERNETES_PORT=tcp://10.96.0.1:443",
        "KUBERNETES_SERVICE_PORT=443",
        "HOSTNAME=ubuntu",
        "HOME=/root",
        "LC_CTYPE=C.UTF-8",
        "TEST_ENV1=value1",
        "TEST_ENV2=value2",
        "TERM=xterm",
        "KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1",
        "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
        "KUBERNETES_PORT_443_TCP_PORT=443",
        "KUBERNETES_PORT_443_TCP_PROTO=tcp",
        "KUBERNETES_SERVICE_PORT_HTTPS=443",
        "KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443",
        "KUBERNETES_SERVICE_HOST=10.96.0.1",
        "PWD=/"
    ]
}

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

root@ubuntu-shell:/# ansible-playbook test.yaml -vvv
ansible-playbook [core 2.14.5]
  config file = None
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.10/dist-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/local/bin/ansible-playbook
  python version = 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] (/usr/bin/python3)
  jinja version = 3.1.3
  libyaml = True
No config file found; using defaults
host_list declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Skipping due to inventory source not existing or not being readable by the current user
script declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
auto declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Skipping due to inventory source not existing or not being readable by the current user
yaml declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Skipping due to inventory source not existing or not being readable by the current user
ini declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Skipping due to inventory source not existing or not being readable by the current user
toml declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.

PLAYBOOK: test.yaml ***********************************************************************************************************************************
1 plays in test.yaml

PLAY [localhost] **************************************************************************************************************************************

TASK [test] *******************************************************************************************************************************************
task path: /test.yaml:19
redirecting (type: connection) ansible.builtin.kubectl to kubernetes.core.kubectl
<127.0.0.1> ESTABLISH kubectl CONNECTION
<127.0.0.1> ENV: KUBERNETES_SERVICE_PORT_HTTPS=443
<127.0.0.1> ENV: KUBERNETES_SERVICE_PORT=443
<127.0.0.1> ENV: HOSTNAME=ubuntu-shell
<127.0.0.1> ENV: PWD=/
<127.0.0.1> ENV: HOME=/root
<127.0.0.1> ENV: KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
<127.0.0.1> ENV: LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:
<127.0.0.1> ENV: TERM=xterm
<127.0.0.1> ENV: SHLVL=1
<127.0.0.1> ENV: KUBERNETES_PORT_443_TCP_PROTO=tcp
<127.0.0.1> ENV: KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
<127.0.0.1> ENV: KUBERNETES_SERVICE_HOST=10.96.0.1
<127.0.0.1> ENV: KUBERNETES_PORT=tcp://10.96.0.1:443
<127.0.0.1> ENV: KUBERNETES_PORT_443_TCP_PORT=443
<127.0.0.1> ENV: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
<127.0.0.1> ENV: _=/usr/local/bin/ansible-playbook
<127.0.0.1> ENV: LC_CTYPE=C.UTF-8
<127.0.0.1> ENV: TESTVAR1=test
<127.0.0.1> ENV: TESTVAR2=test
<127.0.0.1> ENV: TESTVAR3=test
<127.0.0.1> EXEC ['/usr/local/bin/kubectl', '-n', 'test', '--kubeconfig', '/.kube/config', 'exec', '-i', 'ubuntu', '-c', 'ubuntu', '--', '/bin/sh', '-c', "/bin/sh -c 'echo ~ && sleep 0'"]
<127.0.0.1> EXEC ['/usr/local/bin/kubectl', '-n', 'test', '--kubeconfig', '/.kube/config', 'exec', '-i', 'ubuntu', '-c', 'ubuntu', '--', '/bin/sh', '-c', '/bin/sh -c \'( umask 77 && mkdir -p "` echo /root/.ansible/tmp `"&& mkdir "` echo /root/.ansible/tmp/ansible-tmp-1713785852.548581-6866-69007595335133 `" && echo ansible-tmp-1713785852.548581-6866-69007595335133="` echo /root/.ansible/tmp/ansible-tmp-1713785852.548581-6866-69007595335133 `" ) && sleep 0\'']
Using module file /usr/local/lib/python3.10/dist-packages/ansible/modules/command.py
<127.0.0.1> PUT /root/.ansible/tmp/ansible-local-6862s5_lr_wb/tmpxwmx0qeh TO /root/.ansible/tmp/ansible-tmp-1713785852.548581-6866-69007595335133/AnsiballZ_command.py
<127.0.0.1> EXEC ['/usr/local/bin/kubectl', '-n', 'test', '--kubeconfig', '/.kube/config', 'exec', '-i', 'ubuntu', '-c', 'ubuntu', '--', '/bin/sh', '-c', "/bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1713785852.548581-6866-69007595335133/ /root/.ansible/tmp/ansible-tmp-1713785852.548581-6866-69007595335133/AnsiballZ_command.py && sleep 0'"]
<127.0.0.1> EXEC ['/usr/local/bin/kubectl', '-n', 'test', '--kubeconfig', '/.kube/config', 'exec', '-i', 'ubuntu', '-c', 'ubuntu', '--', '/bin/sh', '-c', "/bin/sh -c 'TEST_ENV1=value1 TEST_ENV2=value2 /usr/bin/python3 /root/.ansible/tmp/ansible-tmp-1713785852.548581-6866-69007595335133/AnsiballZ_command.py && sleep 0'"]
<127.0.0.1> EXEC ['/usr/local/bin/kubectl', '-n', 'test', '--kubeconfig', '/.kube/config', 'exec', '-i', 'ubuntu', '-c', 'ubuntu', '--', '/bin/sh', '-c', "/bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-tmp-1713785852.548581-6866-69007595335133/ > /dev/null 2>&1 && sleep 0'"]
changed: [localhost] => {
    "changed": true,
    "cmd": "env",
    "delta": "0:00:00.005088",
    "end": "2024-04-22 11:37:33.655340",
    "invocation": {
        "module_args": {
            "_raw_params": "env",
            "_uses_shell": true,
            "argv": null,
            "chdir": null,
            "creates": null,
            "executable": null,
            "removes": null,
            "stdin": null,
            "stdin_add_newline": true,
            "strip_empty_ends": true
        }
    },
    "msg": "",
    "rc": 0,
    "start": "2024-04-22 11:37:33.650252",
    "stderr": "",
    "stderr_lines": [],
    "stdout": "KUBERNETES_PORT=tcp://10.96.0.1:443\nKUBERNETES_SERVICE_PORT=443\nHOSTNAME=ubuntu\nHOME=/root\nLC_CTYPE=C.UTF-8\nTEST_ENV1=value1\nTEST_ENV2=value2\nTERM=xterm\nKUBERNETES_PORT_443_TCP_ADDR=10.96.0.1\nPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\nKUBERNETES_PORT_443_TCP_PORT=443\nKUBERNETES_PORT_443_TCP_PROTO=tcp\nKUBERNETES_SERVICE_PORT_HTTPS=443\nKUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443\nKUBERNETES_SERVICE_HOST=10.96.0.1\nPWD=/",
    "stdout_lines": [
        "KUBERNETES_PORT=tcp://10.96.0.1:443",
        "KUBERNETES_SERVICE_PORT=443",
        "HOSTNAME=ubuntu",
        "HOME=/root",
        "LC_CTYPE=C.UTF-8",
        "TEST_ENV1=value1",
        "TEST_ENV2=value2",
        "TERM=xterm",
        "KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1",
        "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
        "KUBERNETES_PORT_443_TCP_PORT=443",
        "KUBERNETES_PORT_443_TCP_PROTO=tcp",
        "KUBERNETES_SERVICE_PORT_HTTPS=443",
        "KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443",
        "KUBERNETES_SERVICE_HOST=10.96.0.1",
        "PWD=/"
    ]
}

TASK [debug] ******************************************************************************************************************************************
task path: /test.yaml:22
redirecting (type: connection) ansible.builtin.kubectl to kubernetes.core.kubectl
ok: [localhost] => {
    "result.stdout_lines": [
        "KUBERNETES_PORT=tcp://10.96.0.1:443",
        "KUBERNETES_SERVICE_PORT=443",
        "HOSTNAME=ubuntu",
        "HOME=/root",
        "LC_CTYPE=C.UTF-8",
        "TEST_ENV1=value1",
        "TEST_ENV2=value2",
        "TERM=xterm",
        "KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1",
        "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
        "KUBERNETES_PORT_443_TCP_PORT=443",
        "KUBERNETES_PORT_443_TCP_PROTO=tcp",
        "KUBERNETES_SERVICE_PORT_HTTPS=443",
        "KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443",
        "KUBERNETES_SERVICE_HOST=10.96.0.1",
        "PWD=/"
    ]
}

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

root@ubuntu-shell:/#

Reviewed-by: Bikouo Aubin
Reviewed-by: Yuriy Novostavskiy
Reviewed-by: Mike Graves <mgraves@redhat.com>
2024-05-07 15:27:09 +00:00
Felix Matouschek
600c10dffb k8s: Display warnings to users (#701)
k8s: Display warnings to users

SUMMARY
This changes K8sService and the k8s module so warnings returned by the K8S API are displayed to the user.
Fixes kubevirt/kubevirt.core#30
Fixes kubevirt/kubevirt.core#31
ISSUE TYPE


Feature Pull Request

COMPONENT NAME


k8s module
K8sService

ADDITIONAL INFORMATION



Before:
TASK [Create VM] **********************************************************************************************************************************************
ok: [localhost]

After:
TASK [Create VM] **********************************************************************************************************************************************
[WARNING]: unknown field "spec.template.spec.disk"
[WARNING]: unknown field "spec.template.spec.domain.bogus"
ok: [localhost]

Reviewed-by: Adam Miller <admiller@redhat.com>
Reviewed-by: Mike Graves <mgraves@redhat.com>
Reviewed-by: Felix Matouschek <felix@matouschek.org>
2024-05-06 13:35:52 +00:00
Wout Van De Wiel
9f7c865c9c helm - expand kubeconfig path with user's home dir (#654)
helm - expand kubeconfig path with user's home dir

SUMMARY

Currently the helm module fails when providing the default kubeconfig path explicitly, while the same path is fine for the k8s module.

ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME

helm
ADDITIONAL INFORMATION



- name: Deploy kubelet-csr-approver
  delegate_to: client
  run_once: true
  kubernetes.core.helm:
    update_repo_cache: true
    kubeconfig: "~/.kube/config"
    state: present
    name: kubelet-csr-approver
    namespace: kubelet-csr-approver
    create_namespace: true
    chart_ref: kubelet-csr-approver/kubelet-csr-approver
    chart_version: 1.0.5
    values: "{{ lookup('template', 'values.yaml.j2') | from_yaml }}"
    atomic: true

Before change:
TASK [kubernetes/kubelet_csr_approver : Deploy kubelet-csr-approver] ***
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: FileNotFoundError: [Errno 2] No such file or directory: '~/.kube/config'
fatal: [node-1 -> client(192.168.121.56)]: FAILED! => {"changed": false, "module_stderr": "", "module_stdout": "Traceback (most recent call last):\r\n  File \"/home/vagrant/.ansible/tmp/ansible-tmp-1697293347.7135417-118207-9805169252135/AnsiballZ_helm.py\", line 107, in <module>\r\n    _ansiballz_main()\r\n  File \"/home/vagrant/.ansible/tmp/ansible-tmp-1697293347.7135417-118207-9805169252135/AnsiballZ_helm.py\", line 99, in _ansiballz_main\r\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n  File \"/home/vagrant/.ansible/tmp/ansible-tmp-1697293347.7135417-118207-9805169252135/AnsiballZ_helm.py\", line 47, in invoke_module\r\n    runpy.run_module(mod_name='ansible_collections.kubernetes.core.plugins.modules.helm', init_globals=dict(_module_fqn='ansible_collections.kubernetes.core.plugins.modules.helm', _modlib_path=modlib_path),\r\n  File \"/usr/lib/python3.10/runpy.py\", line 224, in run_module\r\n    return _run_module_code(code, init_globals, run_name, mod_spec)\r\n  File \"/usr/lib/python3.10/runpy.py\", line 96, in _run_module_code\r\n    _run_code(code, mod_globals, init_globals,\r\n  File \"/usr/lib/python3.10/runpy.py\", line 86, in _run_code\r\n    exec(code, run_globals)\r\n  File \"/tmp/ansible_kubernetes.core.helm_payload_o8s36dti/ansible_kubernetes.core.helm_payload.zip/ansible_collections/kubernetes/core/plugins/modules/helm.py\", line 924, in <module>\r\n  File \"/tmp/ansible_kubernetes.core.helm_payload_o8s36dti/ansible_kubernetes.core.helm_payload.zip/ansible_collections/kubernetes/core/plugins/modules/helm.py\", line 737, in main\r\n  File \"/tmp/ansible_kubernetes.core.helm_payload_o8s36dti/ansible_kubernetes.core.helm_payload.zip/ansible_collections/kubernetes/core/plugins/modules/helm.py\", line 435, in run_repo_update\r\n  File \"/tmp/ansible_kubernetes.core.helm_payload_o8s36dti/ansible_kubernetes.core.helm_payload.zip/ansible_collections/kubernetes/core/plugins/module_utils/helm.py\", line 169, in run_helm_command\r\n  File \"/tmp/ansible_kubernetes.core.helm_payload_o8s36dti/ansible_kubernetes.core.helm_payload.zip/ansible_collections/kubernetes/core/plugins/module_utils/helm.py\", line 162, in env_update\r\n  File \"/tmp/ansible_kubernetes.core.helm_payload_o8s36dti/ansible_kubernetes.core.helm_payload.zip/ansible_collections/kubernetes/core/plugins/module_utils/helm.py\", line 120, in _prepare_helm_environment\r\nFileNotFoundError: [Errno 2] No such file or directory: '~/.kube/config'\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}

After change:
TASK [kubernetes/kubelet_csr_approver : Deploy kubelet-csr-approver] ***
changed: [node-1 -> client(192.168.121.56)]

Reviewed-by: Mike Graves <mgraves@redhat.com>
Reviewed-by: Bikouo Aubin
2024-03-13 13:16:38 +00:00
Bikouo Aubin
23e94b60c1 helm - Add reuse-values when running helm diff (#683)
helm - Add reuse-values when running helm diff

SUMMARY

closes #680

ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME

helm

Reviewed-by: GomathiselviS
Reviewed-by: Alina Buzachis
2024-03-01 16:15:11 +00:00
bastienbosser
1955989278 fix(Collection's util resource discovery fails when complex subresources present #659) (#676)
* fix(Collection's util resource discovery fails when complex subresources present #659)

* fix(add changelog fragment)

* update node image

* Create discovery.yml

* Update main.yml

---------

Co-authored-by: Bastien Bosser <bastien.bosser@eviden.com>
Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>
2024-02-29 14:38:45 +01:00
psmolkin
7c4ec3b982 Align helmdiff_check behavior with the deploy function (#670)
Align `helmdiff_check` behavior with the `deploy` function

SUMMARY
Align helmdiff_check behavior with the deploy function

Fixes #638
helmdiff_check respects set_values parameter
Fixes #669
helmdiff_check command line parameters sequence aligned to the deploy function

ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME
kubernetes.core.helm

Reviewed-by: Mike Graves <mgraves@redhat.com>
2024-02-19 17:01:23 +00:00
Alina Buzachis
8d15489ec2 Remove ignore files and entries which are not useful anymore (#667)
Remove ignore files and entries which are not useful anymore

SUMMARY

Remove ignore files and entries which are not useful anymore

ISSUE TYPE


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

COMPONENT NAME

ADDITIONAL INFORMATION

Reviewed-by: Helen Bailey <hebailey@redhat.com>
Reviewed-by: Mike Graves <mgraves@redhat.com>
2023-12-12 16:09:14 +00:00
Bikouo Aubin
3dcdcbc85d avoid unsafe condition in integration (#665)
avoid unsafe condition in integration

SUMMARY


ISSUE TYPE


Bugfix Pull Request

COMPONENT NAME

integration tests

Reviewed-by: Helen Bailey <hebailey@redhat.com>
Reviewed-by: Alina Buzachis
2023-12-12 07:23:09 +00:00
GomathiselviS
fe9c12326d Update main branch post 3.0.0 release (#663)
Update main branch post 3.0.0 release

SUMMARY


ISSUE TYPE


Docs Pull Request

COMPONENT NAME

ADDITIONAL INFORMATION

Reviewed-by: Bikouo Aubin
2023-11-21 17:23:25 +00:00
87 changed files with 961 additions and 2300 deletions

View File

@@ -2,7 +2,5 @@
profile: production
exclude_paths:
- .ansible/
- tests/integration
- tests/unit
- tests/sanity

View File

@@ -1,7 +1,2 @@
# 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]

60
.github/stale.yml vendored Normal file
View File

@@ -0,0 +1,60 @@
---
# Configuration for probot-stale - https://github.com/probot/stale
# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 90
# Number of days of inactivity before an Issue or Pull Request with the stale
# label is closed. Set to false to disable. If disabled, issues still need to be
# closed manually, but will remain marked as stale.
daysUntilClose: 30
# Only issues or pull requests with all of these labels are check if stale.
# Defaults to `[]` (disabled)
onlyLabels: []
# Issues or Pull Requests with these labels will never be considered stale. Set
# to `[]` to disable
exemptLabels:
- security
- planned
- priority/critical
- lifecycle/frozen
- verified
# Set to true to ignore issues in a project (defaults to false)
exemptProjects: false
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: true
# Set to true to ignore issues with an assignee (defaults to false)
exemptAssignees: false
# Label to use when marking as stale
staleLabel: lifecycle/stale
# Limit the number of actions per hour, from 1-30. Default is 30
limitPerRun: 30
pulls:
markComment: |-
PRs go stale after 90 days of inactivity.
If there is no further activity, the PR will be closed in another 30 days.
unmarkComment: >-
This pull request is no longer stale.
closeComment: >-
This pull request has been closed due to inactivity.
issues:
markComment: |-
Issues go stale after 90 days of inactivity.
If there is no further activity, the issue will be closed in another 30 days.
unmarkComment: >-
This issue is no longer stale.
closeComment: >-
This issue has been closed due to inactivity.

View File

@@ -50,7 +50,6 @@ jobs:
source: "./source"
cloud_common: "./cloudcommon"
ansible_posix: "./ansible_posix"
community_general: "./community_general"
strategy:
fail-fast: false
matrix:
@@ -62,7 +61,7 @@ jobs:
- true
- false
workflow-id: ${{ fromJson(needs.splitter.outputs.test_jobs) }}
name: "integration-py${{ matrix.python-version }}-${{ matrix.ansible-version }}-${{ matrix.workflow-id }}-enable_turbo=${{ matrix.enable-turbo-mode }}"
name: "integration-py${{ matrix.python-version }}-${{ matrix.ansible-version }}-${{ matrix.workflow-id }}"
steps:
- name: Read target
id: read-targets
@@ -119,13 +118,6 @@ jobs:
path: ${{ env.ansible_posix }}
ref: main
- name: checkout ansible-collections/community.general
uses: ansible-network/github_actions/.github/actions/checkout_dependency@main
with:
repository: ansible-collections/community.general
path: ${{ env.community_general }}
ref: main
- name: install cloud.common collection
uses: ansible-network/github_actions/.github/actions/build_install_collection@main
with:
@@ -138,12 +130,6 @@ jobs:
install_python_dependencies: true
source_path: ${{ env.ansible_posix }}
- name: install community.general collection
uses: ansible-network/github_actions/.github/actions/build_install_collection@main
with:
install_python_dependencies: false
source_path: ${{ env.community_general }}
- name: create kubernetes cluster
uses: helm/kind-action@v1.8.0
with:

View File

@@ -19,5 +19,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: run-ansible-lint
uses: ansible/ansible-lint@v25.1.2
- name: Run ansible-lint
uses: ansible/ansible-lint@v24.2.3

1
.gitignore vendored
View File

@@ -13,7 +13,6 @@ changelogs/.plugin-cache.yaml
tests/output
tests/integration/cloud-config-*
.cache
.ansible
# Helm charts
tests/integration/*-chart-*.tgz

View File

@@ -5,24 +5,16 @@ rules:
braces:
max-spaces-inside: 1
level: error
brackets:
max-spaces-inside: 1
level: error
comments:
min-spaces-from-content: 1
comments-indentation: false
document-start: disable
line-length: disable
truthy: disable
indentation:
spaces: 2
indent-sequences: consistent
octal-values:
forbid-implicit-octal: true
forbid-explicit-octal: true
ignore: |
.cache
.tox
.ansible
tests/output

View File

@@ -4,48 +4,56 @@ Kubernetes Collection Release Notes
.. contents:: Topics
v3.3.1
v5.0.0
======
Release Summary
---------------
This release fixes the CI issues with the ``linters`` workflow.
This major release drops support for ``ansible-core<2.15``.
v3.3.0
Minor Changes
-------------
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 6.0.0 (https://github.com/ansible-collections/kubernetes.core/pull/734).
Breaking Changes / Porting Guide
--------------------------------
- Remove support for ``ansible-core<2.15`` (https://github.com/ansible-collections/kubernetes.core/pull/737).
v4.0.0
======
Release Summary
---------------
This major release brings several bug fixes. We have also removed support for ``ansible-core<2.15`` and deprecated functions and class from ``module_utils/common.py``.
Minor Changes
-------------
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 5.0 (https://github.com/ansible-collections/kubernetes.core/pull/723).
- 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).
- k8s - The module and K8sService were changed so warnings returned by the K8S API are now displayed to the user.
Removed Features (previously deprecated)
----------------------------------------
- k8s - Support for ``merge_type=json`` has been removed in version 4.0.0. Please use ``kubernetes.core.k8s_json_patch`` instead (https://github.com/ansible-collections/kubernetes.core/pull/722).
- k8s_exec - the previously deprecated ``result.return_code`` return value has been removed, consider using ``result.rc`` instead (https://github.com/ansible-collections/kubernetes.core/pull/726).
- module_utils/common.py - the previously deprecated ``K8sAnsibleMixin`` class has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
- module_utils/common.py - the previously deprecated ``configuration_digest()`` function has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
- module_utils/common.py - the previously deprecated ``get_api_client()`` function has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
- module_utils/common.py - the previously deprecated ``unique_string()`` function has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
Bugfixes
--------
- helm - Helm version checks did not support RC versions. They now accept any version tags. (https://github.com/ansible-collections/kubernetes.core/pull/745).
- helm_pull - Apply no_log=True to pass_credentials to silence false positive warning.. (https://github.com/ansible-collections/kubernetes.core/pull/796).
- k8s_drain - Fix k8s_drain does not wait for single pod (https://github.com/ansible-collections/kubernetes.core/issues/769).
- k8s_drain - Fix k8s_drain runs into a timeout when evicting a pod which is part of a stateful set (https://github.com/ansible-collections/kubernetes.core/issues/792).
- kubeconfig option should not appear in module invocation log (https://github.com/ansible-collections/kubernetes.core/issues/782).
- kustomize - kustomize plugin fails with deprecation warnings (https://github.com/ansible-collections/kubernetes.core/issues/639).
- waiter - Fix waiting for daemonset when desired number of pods is 0. (https://github.com/ansible-collections/kubernetes.core/pull/756).
v3.2.0
======
Release Summary
---------------
This release comes with documentation updates.
Minor Changes
-------------
- connection/kubectl.py - Added an example of using the kubectl connection plugin to the documentation (https://github.com/ansible-collections/kubernetes.core/pull/741).
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 6.0.0 (https://github.com/ansible-collections/kubernetes.core/pull/734).
- Resolve Collections util resource discovery fails when complex subresources present (https://github.com/ansible-collections/kubernetes.core/pull/676).
- align `helmdiff_check()` function commandline rendering with the `deploy()` function (https://github.com/ansible-collections/kubernetes.core/pull/670).
- avoid unsafe conditions in integration tests (https://github.com/ansible-collections/kubernetes.core/pull/665).
- helm - use ``reuse-values`` when running ``helm diff`` command (https://github.com/ansible-collections/kubernetes.core/issues/680).
- integrations test helm_kubeconfig - set helm version to v3.10.3 to avoid incompatability with new bitnami charts (https://github.com/ansible-collections/kubernetes.core/pull/670).
v3.1.0
======

View File

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

View File

@@ -4,16 +4,12 @@
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.
## Requirements
<!--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.15.0**.
For collections that support Ansible 2.9, please ensure you update your `network_os` to use the
fully qualified collection name (for example, `cisco.ios.ios`).
@@ -22,43 +18,43 @@ A collection may contain metadata that identifies these versions.
PEP440 is the schema used to describe the versions of Ansible.
<!--end requires_ansible-->
### Python Support
## Python Support
* Collection supports 3.9+
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.
### Included content
## Included content
Click on the name of a plugin or module to view that content's documentation:
<!--start collection content-->
#### Connection plugins
### Connection plugins
Name | Description
--- | ---
[kubernetes.core.kubectl](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.kubectl_connection.rst)|Execute tasks in pods running on Kubernetes.
#### K8s filter plugins
### K8s filter plugins
Name | Description
--- | ---
kubernetes.core.k8s_config_resource_name|Generate resource name for the given resource of type ConfigMap, Secret
#### Inventory plugins
### Inventory plugins
Name | Description
--- | ---
[kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_inventory.rst)|Kubernetes (K8s) inventory source
#### Lookup plugins
### Lookup plugins
Name | Description
--- | ---
[kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_lookup.rst)|Query the K8s API
[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
--- | ---
[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
@@ -83,7 +79,9 @@ Name | Description
<!--end collection content-->
## Installation
## Installation and Usage
### Installing the Collection from Ansible Galaxy
Before using the Kubernetes collection, you need to install it with the Ansible Galaxy CLI:
@@ -95,7 +93,7 @@ You can also include it in a `requirements.yml` file and install it via `ansible
---
collections:
- name: kubernetes.core
version: 3.3.1
version: 5.0.0
```
### Installing the Kubernetes Python Library
@@ -104,7 +102,7 @@ Content in this collection requires the [Kubernetes Python client](https://pypi.
pip3 install kubernetes
## Use Cases
### Using modules from the Kubernetes Collection in your playbooks
It's preferable to use content in this collection using their Fully Qualified Collection Namespace (FQCN), for example `kubernetes.core.k8s_info`:
@@ -191,16 +189,12 @@ defined in the playbook using `environment` keyword as above, you must set it us
Please read more about Ansible Turbo mode - [here](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/ansible_turbo_mode.rst).
## Contributing to this collection
## Testing and Development
If you want to develop new content for this collection or improve what's already here, the easiest way to work on the collection is to clone it into one of the configured [`COLLECTIONS_PATHS`](https://docs.ansible.com/ansible/latest/reference_appendices/config.html#collections-paths), and work on it there.
See [Contributing to kubernetes.core](CONTRIBUTING.md).
## Testing
[![Linters](https://img.shields.io/github/actions/workflow/status/ansible-collections/kubernetes.core/linters.yaml?label=linters)](https://github.com/ansible-collections/kubernetes.core/actions/workflows/linters.yaml) [![Integration tests](https://img.shields.io/github/actions/workflow/status/ansible-collections/kubernetes.core/integration-tests.yaml?label=integration%20tests)](https://github.com/ansible-collections/kubernetes.core/actions/workflows/integration-tests.yaml) [![Sanity tests](https://img.shields.io/github/actions/workflow/status/ansible-collections/kubernetes.core/sanity-tests.yaml?label=sanity%20tests)](https://github.com/ansible-collections/kubernetes.core/actions/workflows/sanity-tests.yaml) [![Unit tests](https://img.shields.io/github/actions/workflow/status/ansible-collections/kubernetes.core/unit-tests.yaml?label=unit%20tests)](https://github.com/ansible-collections/kubernetes.core/actions/workflows/unit-tests.yaml) [![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/kubernetes.core)](https://app.codecov.io/gh/ansible-collections/kubernetes.core)
### 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).
@@ -237,36 +231,10 @@ 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.
## 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
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
GNU General Public License v3.0 or later

View File

@@ -854,54 +854,58 @@ releases:
- 652-fix-json-patch-action.yml
- 654-helm-expand-user.yml
release_date: '2024-05-16'
3.2.0:
changes:
minor_changes:
- connection/kubectl.py - Added an example of using the kubectl connection plugin
to the documentation (https://github.com/ansible-collections/kubernetes.core/pull/741).
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 5.0 (https://github.com/ansible-collections/kubernetes.core/pull/723).
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 6.0.0
(https://github.com/ansible-collections/kubernetes.core/pull/734).
release_summary: This release comes with documentation updates.
fragments:
- 20240530-defer-removal-and-ansible-core-support-update.yaml
- 20240601-doc-example-of-using-kubectl.yaml
- 3.2.0.yml
- inventory-update_removal_date.yml
release_date: '2024-06-14'
3.3.0:
4.0.0:
changes:
bugfixes:
- helm - Helm version checks did not support RC versions. They now accept any
version tags. (https://github.com/ansible-collections/kubernetes.core/pull/745).
- helm_pull - Apply no_log=True to pass_credentials to silence false positive
warning. (https://github.com/ansible-collections/kubernetes.core/pull/796).
- k8s_drain - Fix k8s_drain does not wait for single pod (https://github.com/ansible-collections/kubernetes.core/issues/769).
- k8s_drain - Fix k8s_drain runs into a timeout when evicting a pod which is
part of a stateful set (https://github.com/ansible-collections/kubernetes.core/issues/792).
- kubeconfig option should not appear in module invocation log (https://github.com/ansible-collections/kubernetes.core/issues/782).
- kustomize - kustomize plugin fails with deprecation warnings (https://github.com/ansible-collections/kubernetes.core/issues/639).
- waiter - Fix waiting for daemonset when desired number of pods is 0. (https://github.com/ansible-collections/kubernetes.core/pull/756).
- Resolve Collections util resource discovery fails when complex subresources
present (https://github.com/ansible-collections/kubernetes.core/pull/676).
- align `helmdiff_check()` function commandline rendering with the `deploy()`
function (https://github.com/ansible-collections/kubernetes.core/pull/670).
- avoid unsafe conditions in integration tests (https://github.com/ansible-collections/kubernetes.core/pull/665).
- helm - use ``reuse-values`` when running ``helm diff`` command (https://github.com/ansible-collections/kubernetes.core/issues/680).
- integrations test helm_kubeconfig - set helm version to v3.10.3 to avoid incompatability
with new bitnami charts (https://github.com/ansible-collections/kubernetes.core/pull/670).
minor_changes:
- k8s_drain - Improve error message for pod disruption budget when draining
a node (https://github.com/ansible-collections/kubernetes.core/issues/797).
release_summary: This release comes with improvements to the error messages in the k8s_drain module and several bug fixes.
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 5.0 (https://github.com/ansible-collections/kubernetes.core/pull/723).
- k8s - The module and K8sService were changed so warnings returned by the K8S
API are now displayed to the user.
release_summary: This major release brings several bug fixes. We have also removed
support for ``ansible-core<2.15`` and deprecated functions and class from
``module_utils/common.py``.
removed_features:
- k8s - Support for ``merge_type=json`` has been removed in version 4.0.0. Please
use ``kubernetes.core.k8s_json_patch`` instead (https://github.com/ansible-collections/kubernetes.core/pull/722).
- k8s_exec - the previously deprecated ``result.return_code`` return value has
been removed, consider using ``result.rc`` instead (https://github.com/ansible-collections/kubernetes.core/pull/726).
- module_utils/common.py - the previously deprecated ``K8sAnsibleMixin`` class
has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
- module_utils/common.py - the previously deprecated ``configuration_digest()``
function has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
- module_utils/common.py - the previously deprecated ``get_api_client()`` function
has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
- module_utils/common.py - the previously deprecated ``unique_string()`` function
has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
fragments:
- 20231206-fix-unsafe-condition-in-integration.yml
- 20240117-fix-helm-diff-cmd-line-rendering.yml
- 20240222-Collections-util-resource-discovery-fails-when-complex-subresources-present.yml
- 20240228-fix-helm-diff-with-reuse-values.yml
- 20240423-k8s-display-warnings-to-users.yml
- 4.0.0.yaml
- inventory-update_removal_date.yml
- k8s-merge_type-removed.yml
- module_utils-common-remove-deprecated-functions-and-class.yaml
release_date: '2024-05-24'
5.0.0:
changes:
breaking_changes:
- Remove support for ``ansible-core<2.15`` (https://github.com/ansible-collections/kubernetes.core/pull/737).
minor_changes:
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 6.0.0
(https://github.com/ansible-collections/kubernetes.core/pull/734).
release_summary: This major release drops support for ``ansible-core<2.15``.
fragments:
- 20240530-ansible-core-support-update.yaml
- 20240611-helm-rc-version.yaml
- 20240620-fix-kustomize-plugin-fails-with-deprecation-warnings.yml
- 20241102-fix-ci-post-2.18-issue.yaml
- 20241213-kubeconfig-set-no_log-true.yaml
- 756-fix-daemonset-waiting.yaml
- 770-fix-k8s-drain-doesnt-wait-for-single-pod.yaml
- 793-fix-k8s-drain-runs-into-timeout.yaml
- 796-false-positive-helmull.yaml
- 798-drain-pdb-error-message.yaml
- readme_template_update.yml
release_date: '2025-01-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'
- 20240530-defer-removal-and-ansible-core-support-update.yaml
- 5.0.0.yml
release_date: '2024-05-31'

View File

@@ -0,0 +1,3 @@
---
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).

View File

@@ -1,3 +0,0 @@
---
minor_changes:
- action/k8s_info - update templating mechanism with changes from ``ansible-core 2.19`` (https://github.com/ansible-collections/kubernetes.core/pull/888).

View File

@@ -1,3 +0,0 @@
---
bugfixes:
- module_utils/k8s/service - fix issue when trying to delete resource using `delete_options` and `check_mode=true` (https://github.com/ansible-collections/kubernetes.core/issues/892).

View File

@@ -1,3 +0,0 @@
---
minor_changes:
- Bump version of ansible-lint to 25.1.2 (https://github.com/ansible-collections/kubernetes.core/pull/919).

View File

@@ -443,7 +443,7 @@ Parameters
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.5.0</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
@@ -463,7 +463,7 @@ Parameters
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.5.0</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>

View File

@@ -423,7 +423,7 @@ Parameters
<span style="color: purple">list</span>
/ <span style="color: purple">elements=string</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.5.0</div>
</td>
<td>
</td>

View File

@@ -168,7 +168,7 @@ Parameters
<span style="color: purple">list</span>
/ <span style="color: purple">elements=string</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.5.0</div>
</td>
<td>
</td>

View File

@@ -121,7 +121,7 @@ Parameters
<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> works better with Services than &#x27;force=yes&#x27;</div>
<div>mutually exclusive with <code>merge_type</code></div>
<div>Mutually exclusive with <code>merge_type</code>.</div>
</td>
</tr>
<tr>
@@ -216,7 +216,7 @@ Parameters
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.5.0</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
@@ -389,7 +389,7 @@ Parameters
<span style="color: purple">list</span>
/ <span style="color: purple">elements=string</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.5.0</div>
</td>
<td>
</td>
@@ -513,18 +513,17 @@ Parameters
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li>json</li>
<li>merge</li>
<li>strategic-merge</li>
</ul>
</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>For example, Custom Resource Definitions typically aren&#x27;t updatable by the usual strategic merge. You may want to use <code>merge</code> if you see &quot;strategic merge patch format is not supported&quot;</div>
<div>For example, Custom Resource Definitions typically aren&#x27;t updatable by the usual strategic merge. You may want to use <code>merge</code> if you see &quot;strategic merge patch format is not supported&quot;.</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>[&#x27;strategic-merge&#x27;, &#x27;merge&#x27;]</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><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>
<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>
</td>
</tr>
<tr>

View File

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

View File

@@ -1,5 +1,5 @@
---
requires_ansible: '>=2.14.0'
requires_ansible: '>=2.15.0'
action_groups:
helm:

View File

@@ -25,18 +25,30 @@ from ansible.module_utils.parsing.convert_bool import boolean
from ansible.module_utils.six import iteritems, string_types
from ansible.plugins.action import ActionBase
try:
from ansible.template import trust_as_template
except ImportError:
trust_as_template = None
def _from_yaml_to_definition(buffer):
class RemoveOmit(object):
def __init__(self, buffer, omit_value):
try:
import yaml
except ImportError:
raise AnsibleError("Failed to import the required Python library (PyYAML).")
return list(yaml.safe_load_all(buffer))
self.data = yaml.safe_load_all(buffer)
self.omit = omit_value
def remove_omit(self, data):
if isinstance(data, dict):
result = dict()
for key, value in iteritems(data):
if value == self.omit:
continue
result[key] = self.remove_omit(value)
return result
if isinstance(data, list):
return [self.remove_omit(v) for v in data if v != self.omit]
return data
def output(self):
return [self.remove_omit(d) for d in self.data]
ENV_KUBECONFIG_PATH_SEPARATOR = ";" if platform.system() == "Windows" else ":"
@@ -195,6 +207,7 @@ class ActionModule(ActionBase):
"'template' is only a supported parameter for the 'k8s' module."
)
omit_value = task_vars.get("omit")
template_params = []
if isinstance(template, string_types) or isinstance(template, dict):
template_params.append(self.get_template_args(template))
@@ -217,7 +230,6 @@ class ActionModule(ActionBase):
old_vars = self._templar.available_variables
default_environment = {}
if trust_as_template is None:
for key in (
"newline_sequence",
"variable_start_string",
@@ -245,35 +257,26 @@ class ActionModule(ActionBase):
with self.get_template_data(template_item["path"]) as template_data:
# add ansible 'template' vars
temp_vars = copy.deepcopy(task_vars)
overrides = {}
for key, value in iteritems(template_item):
if hasattr(self._templar.environment, key):
if value is not None:
overrides[key] = value
if trust_as_template is None:
setattr(self._templar.environment, key, value)
elif trust_as_template is None:
else:
setattr(
self._templar.environment,
key,
default_environment.get(key),
)
self._templar.available_variables = temp_vars
if trust_as_template:
template_data = trust_as_template(template_data)
result = self._templar.template(
template_data,
preserve_trailing_newlines=True,
escape_backslashes=False,
overrides=overrides,
)
else:
result = self._templar.do_template(
template_data,
preserve_trailing_newlines=True,
escape_backslashes=False,
)
result_template.extend(_from_yaml_to_definition(result))
if omit_value is not None:
result_template.extend(RemoveOmit(result, omit_value).output())
else:
result_template.append(result)
self._templar.available_variables = old_vars
resource_definition = self._task.args.get("definition", None)
if not resource_definition:

View File

@@ -125,18 +125,18 @@ import json
from ansible.errors import AnsibleError
from ansible.plugins.inventory import BaseInventoryPlugin, Cacheable, Constructable
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
HAS_K8S_MODULE_HELPER,
k8s_import_exception,
)
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
get_api_client,
)
try:
from kubernetes.dynamic.exceptions import DynamicApiError
except ImportError:
pass
HAS_K8S_MODULE_HELPER = True
k8s_import_exception = None
except ImportError as e:
HAS_K8S_MODULE_HELPER = False
k8s_import_exception = e
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
get_api_client,
)
def format_dynamic_api_exc(exc):

View File

@@ -94,8 +94,7 @@ def get_binary_from_path(name, opt_dirs=None):
def run_command(command):
cmd = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = cmd.communicate()
return cmd.returncode, stdout, stderr
return cmd.communicate()
class LookupModule(LookupBase):
@@ -141,18 +140,9 @@ class LookupModule(LookupBase):
if enable_helm:
command += ["--enable-helm"]
(ret, out, err) = run_command(command)
if ret != 0:
(out, err) = run_command(command)
if err:
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
)
"kustomize command failed with: {0}".format(err.decode("utf-8"))
)
return [out.decode("utf-8")]

View File

@@ -149,6 +149,7 @@ def k8s_apply(resource, definition, **kwargs):
force_conflicts=kwargs.get("force_conflicts"),
field_manager=kwargs.get("field_manager"),
dry_run=kwargs.get("dry_run"),
serialize=kwargs.get("serialize"),
)
if not existing:
return resource.create(
@@ -158,6 +159,7 @@ def k8s_apply(resource, definition, **kwargs):
return resource.get(
name=definition["metadata"]["name"],
namespace=definition["metadata"].get("namespace"),
**kwargs
)
return resource.patch(
body=desired,

View File

@@ -18,7 +18,7 @@ AUTH_PROXY_HEADERS_SPEC = dict(
)
AUTH_ARG_SPEC = {
"kubeconfig": {"type": "raw", "no_log": True},
"kubeconfig": {"type": "raw"},
"context": {},
"host": {},
"api_key": {"no_log": True},

File diff suppressed because it is too large Load Diff

View File

@@ -77,6 +77,7 @@ def write_temp_kubeconfig(server, validate_certs=True, ca_cert=None, kubeconfig=
class AnsibleHelmModule(object):
"""
An Ansible module class for Kubernetes.core helm modules
"""
@@ -183,10 +184,10 @@ class AnsibleHelmModule(object):
def get_helm_version(self):
command = self.get_helm_binary() + " version"
rc, out, err = self.run_command(command)
m = re.match(r'version.BuildInfo{Version:"v(.*?)",', out)
m = re.match(r'version.BuildInfo{Version:"v([0-9\.]*)",', out)
if m:
return m.group(1)
m = re.match(r'Client: &version.Version{SemVer:"v(.*?)", ', out)
m = re.match(r'Client: &version.Version{SemVer:"v([0-9\.]*)", ', out)
if m:
return m.group(1)
return None

View File

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

View File

@@ -139,6 +139,7 @@ def perform_action(svc, definition: Dict, params: Dict) -> Dict:
result = {"changed": False, "result": {}}
instance = {}
warnings = []
resource = svc.find_resource(kind, api_version, fail=True)
definition["kind"] = resource.kind
@@ -172,7 +173,7 @@ def perform_action(svc, definition: Dict, params: Dict) -> Dict:
return result
if params.get("apply"):
instance = svc.apply(resource, definition, existing)
instance, warnings = svc.apply(resource, definition, existing)
result["method"] = "apply"
elif not existing:
if state == "patched":
@@ -183,16 +184,19 @@ def perform_action(svc, definition: Dict, params: Dict) -> Dict:
)
)
return result
instance = svc.create(resource, definition)
instance, warnings = svc.create(resource, definition)
result["method"] = "create"
result["changed"] = True
elif params.get("force", False):
instance = svc.replace(resource, definition, existing)
instance, warnings = svc.replace(resource, definition, existing)
result["method"] = "replace"
else:
instance = svc.update(resource, definition, existing)
instance, warnings = svc.update(resource, definition, existing)
result["method"] = "update"
if warnings:
result["warnings"] = warnings
# If needed, wait and/or create diff
success = True

View File

@@ -2,6 +2,8 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
import copy
from json import loads
from re import compile
from typing import Any, Dict, List, Optional, Tuple
from ansible.module_utils.common.dict_transformations import dict_merge
@@ -142,18 +144,12 @@ class K8sService:
name: str,
namespace: str,
merge_type: str = None,
) -> 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",
)
) -> Tuple[Dict, List[str]]:
try:
params = dict(name=name, namespace=namespace)
params = dict(name=name, namespace=namespace, serialize=False)
if merge_type:
params["content_type"] = "application/{0}-patch+json".format(merge_type)
return self.client.patch(resource, definition, **params).to_dict()
return decode_response(self.client.patch(resource, definition, **params))
except Exception as e:
reason = e.body if hasattr(e, "body") else e
msg = "Failed to patch object: {0}".format(reason)
@@ -330,17 +326,19 @@ class K8sService:
result["resources"].append(hide_fields(res, hidden_fields))
return result
def create(self, resource: Resource, definition: Dict) -> Dict:
def create(self, resource: Resource, definition: Dict) -> Tuple[Dict, List[str]]:
namespace = definition["metadata"].get("namespace")
name = definition["metadata"].get("name")
if self._client_side_dry_run:
k8s_obj = _encode_stringdata(definition)
else:
return _encode_stringdata(definition), []
try:
k8s_obj = self.client.create(
resource, definition, namespace=namespace
).to_dict()
return decode_response(
self.client.create(
resource, definition, namespace=namespace, serialize=False
)
)
except ConflictError:
# Some resources, like ProjectRequests, can't be created multiple times,
# because the resources that they create don't match their kind
@@ -351,102 +349,101 @@ class K8sService:
name
)
)
return dict()
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
return k8s_obj
def apply(
self,
resource: Resource,
definition: Dict,
existing: Optional[ResourceInstance] = None,
) -> Dict:
) -> Tuple[Dict, List[str]]:
namespace = definition["metadata"].get("namespace")
server_side_apply = self.module.params.get("server_side_apply")
if server_side_apply:
requires("kubernetes", "19.15.0", reason="to use server side apply")
if self._client_side_dry_run:
ignored, patch = apply_object(resource, _encode_stringdata(definition))
if existing:
k8s_obj = dict_merge(existing.to_dict(), patch)
else:
k8s_obj = patch
return dict_merge(existing.to_dict(), patch), []
else:
return patch, []
try:
params = {}
if server_side_apply:
params["server_side"] = True
params.update(server_side_apply)
k8s_obj = self.client.apply(
resource, definition, namespace=namespace, **params
).to_dict()
return decode_response(
self.client.apply(
resource, definition, namespace=namespace, serialize=False, **params
)
)
except Exception as e:
reason = e.body if hasattr(e, "body") else e
msg = "Failed to apply object: {0}".format(reason)
raise CoreException(msg) from e
return k8s_obj
def replace(
self,
resource: Resource,
definition: Dict,
existing: ResourceInstance,
) -> Dict:
) -> Tuple[Dict, List[str]]:
append_hash = self.module.params.get("append_hash", False)
name = definition["metadata"].get("name")
namespace = definition["metadata"].get("namespace")
if self._client_side_dry_run:
k8s_obj = _encode_stringdata(definition)
else:
return _encode_stringdata(definition), []
try:
k8s_obj = self.client.replace(
return decode_response(
self.client.replace(
resource,
definition,
name=name,
namespace=namespace,
append_hash=append_hash,
).to_dict()
serialize=False,
)
)
except Exception as e:
reason = e.body if hasattr(e, "body") else e
msg = "Failed to replace object: {0}".format(reason)
raise CoreException(msg) from e
return k8s_obj
def update(
self, resource: Resource, definition: Dict, existing: ResourceInstance
) -> Dict:
) -> Tuple[Dict, List[str]]:
name = definition["metadata"].get("name")
namespace = definition["metadata"].get("namespace")
if self._client_side_dry_run:
k8s_obj = dict_merge(existing.to_dict(), _encode_stringdata(definition))
else:
return dict_merge(existing.to_dict(), _encode_stringdata(definition)), []
exception = None
for merge_type in self.module.params.get("merge_type") or [
"strategic-merge",
"merge",
]:
try:
k8s_obj = self.patch_resource(
return self.patch_resource(
resource,
definition,
name,
namespace,
merge_type=merge_type,
)
exception = None
except CoreException as e:
exception = e
continue
break
if exception:
raise exception
return k8s_obj
def delete(
self,
@@ -476,7 +473,7 @@ class K8sService:
if label_selectors:
params["label_selector"] = ",".join(label_selectors)
if delete_options and not self.module.check_mode:
if delete_options:
body = {
"apiVersion": "v1",
"kind": "DeleteOptions",
@@ -543,3 +540,83 @@ def hide_field(definition: dict, hidden_field: str) -> dict:
else:
del definition[split[0]]
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

View File

@@ -51,7 +51,7 @@ def daemonset_ready(daemonset: ResourceInstance) -> bool:
return bool(
daemonset.status
and daemonset.status.desiredNumberScheduled is not None
and (daemonset.status.updatedNumberScheduled or 0)
and daemonset.status.updatedNumberScheduled
== daemonset.status.desiredNumberScheduled
and daemonset.status.numberReady == daemonset.status.desiredNumberScheduled
and daemonset.status.observedGeneration == daemonset.metadata.generation

View File

@@ -137,14 +137,14 @@ options:
- If I(reset_values) is set to C(True), this is ignored.
type: bool
required: false
version_added: 3.0.0
version_added: 2.5.0
reset_values:
description:
- When upgrading package, reset the values to the ones built into the chart.
type: bool
required: false
default: True
version_added: 3.0.0
version_added: 2.5.0
#Helm options
disable_hook:

View File

@@ -189,7 +189,7 @@ def main():
repo_password=dict(
type="str", no_log=True, aliases=["password", "chart_repo_password"]
),
pass_credentials=dict(type="bool", default=False, no_log=False),
pass_credentials=dict(type="bool", default=False),
skip_tls_certs_check=dict(type="bool", default=False),
chart_devel=dict(type="bool"),
untar_chart=dict(type="bool", default=False),

View File

@@ -57,15 +57,14 @@ options:
- Whether to override the default patch merge approach with a specific type. By default, the strategic
merge will typically be used.
- 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)
- 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
combine Custom Resources and built-in resources.
- mutually exclusive with C(apply)
- I(merge_type=json) is deprecated and will be removed in version 4.0.0. Please use M(kubernetes.core.k8s_json_patch) instead.
- 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.
choices:
- json
- merge
- strategic-merge
type: list
@@ -101,7 +100,7 @@ options:
- C(apply) compares the desired resource definition with the previously supplied resource definition,
ignoring properties that are automatically generated
- C(apply) works better with Services than 'force=yes'
- mutually exclusive with C(merge_type)
- Mutually exclusive with C(merge_type).
default: False
type: bool
template:
@@ -182,7 +181,7 @@ options:
- This parameter can be used with C(label_selectors) to restrict the resources to be deleted.
type: bool
default: false
version_added: 3.0.0
version_added: 2.5.0
aliases:
- all
hidden_fields:
@@ -192,7 +191,7 @@ options:
- Only field definitions that don't reference list items are supported (so V(spec.containers[0]) would not work)
type: list
elements: str
version_added: 3.0.0
version_added: 2.5.0
requirements:
- "python >= 3.9"
@@ -460,7 +459,7 @@ def argspec():
argument_spec.update(copy.deepcopy(AUTH_ARG_SPEC))
argument_spec.update(copy.deepcopy(WAIT_ARG_SPEC))
argument_spec["merge_type"] = dict(
type="list", elements="str", choices=["json", "merge", "strategic-merge"]
type="list", elements="str", choices=["merge", "strategic-merge"]
)
argument_spec["validate"] = dict(type="dict", default=None, options=validate_spec())
argument_spec["append_hash"] = dict(type="bool", default=False)

View File

@@ -47,7 +47,7 @@ options:
- This option has effect only when C(state) is set to I(drain).
type: list
elements: str
version_added: 3.0.0
version_added: 2.5.0
aliases:
- label_selectors
delete_options:
@@ -143,7 +143,6 @@ result:
"""
import copy
import json
import time
import traceback
from datetime import datetime
@@ -188,17 +187,6 @@ except ImportError:
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):
k8s_kind_mirror = "kubernetes.io/config.mirror"
daemonSet, unmanaged, mirror, localStorage, to_delete = [], [], [], [], []
@@ -303,19 +291,16 @@ class K8sDrainAnsible(object):
return (datetime.now() - start).seconds
response = None
pod = None
pod = pods.pop()
while (_elapsed_time() < wait_timeout or wait_timeout == 0) and pods:
if not pod:
pod = pods[-1]
pod = pods.pop()
try:
response = self._api_instance.read_namespaced_pod(
namespace=pod[0], name=pod[1]
)
if not response or response.spec.node_name != self._module.params.get(
"name"
):
if not response:
pod = None
del pods[-1]
time.sleep(wait_sleep)
except ApiException as exc:
if exc.reason != "Not Found":
@@ -323,7 +308,6 @@ class K8sDrainAnsible(object):
msg="Exception raised: {0}".format(exc.reason)
)
pod = None
del pods[-1]
except Exception as e:
self._module.fail_json(msg="Exception raised: {0}".format(to_native(e)))
if not pods:
@@ -350,7 +334,7 @@ class K8sDrainAnsible(object):
if exc.reason != "Not Found":
self._module.fail_json(
msg="Failed to delete pod {0}/{1} due to: {2}".format(
namespace, name, to_native(format_dynamic_api_exc(exc))
namespace, name, exc.reason
)
)
except Exception as exc:

View File

@@ -135,7 +135,7 @@ from ansible.module_utils._text import to_native
from ansible_collections.kubernetes.core.plugins.module_utils.ansiblemodule import (
AnsibleModule,
)
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
AUTH_ARG_SPEC,
)
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
@@ -219,12 +219,6 @@ def execute_module(module, client):
else:
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(
# Some command might change environment, but ultimately failing at end
changed=True,

View File

@@ -51,7 +51,7 @@ options:
- Only field definitions that don't reference list items are supported (so V(spec.containers[0]) would not work)
type: list
elements: str
version_added: 3.0.0
version_added: 2.5.0
extends_documentation_fragment:
- kubernetes.core.k8s_auth_options

View File

@@ -4,4 +4,4 @@
loop_control:
loop_var: helm_version
with_items:
- "v3.8.0"
- "v3.7.0"

View File

@@ -17,7 +17,8 @@
- name: Initial chart installation
helm:
binary_path: "{{ helm_binary }}"
chart_ref: oci://registry-1.docker.io/bitnamicharts/redis
chart_ref: redis
chart_repo_url: https://charts.bitnami.com/bitnami
release_name: test-redis
release_namespace: "{{ helm_namespace }}"
create_namespace: true
@@ -41,7 +42,8 @@
- name: Upgrade chart using reuse_values=true
helm:
binary_path: "{{ helm_binary }}"
chart_ref: oci://registry-1.docker.io/bitnamicharts/redis
chart_ref: redis
chart_repo_url: https://charts.bitnami.com/bitnami
release_name: test-redis
release_namespace: "{{ helm_namespace }}"
reuse_values: true

View File

@@ -73,7 +73,7 @@
assert:
that:
- install is changed
- install.status.chart == "{{ chart_test }}-{{ chart_test_version }}"
- install.status.chart == chart_test+"-"+chart_test_version
- install.status.status | lower == 'deployed'
- name: Check helm_info content
@@ -95,7 +95,7 @@
- name: "Assert that {{ chart_test }} is installed from {{ source }} with helm_info"
assert:
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'
- release_state_content_info.status.status | lower == 'deployed'
@@ -112,7 +112,7 @@
assert:
that:
- 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'
- name: "Add vars to {{ chart_test }} from {{ source }}"
@@ -130,7 +130,7 @@
that:
- install is changed
- 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"
- name: Check idempotency after adding vars
@@ -148,7 +148,7 @@
that:
- install is not changed
- 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"
- name: "Remove Vars to {{ chart_test }} from {{ source }}"
@@ -165,7 +165,7 @@
that:
- install is changed
- install.status.status | lower == 'deployed'
- install.status.chart == "{{ chart_test }}-{{ chart_test_version }}"
- install.status.chart == chart_test+"-"+chart_test_version
- install.status['values'] == {}
- name: Check idempotency after removing vars
@@ -182,7 +182,7 @@
that:
- install is not changed
- install.status.status | lower == 'deployed'
- install.status.chart == "{{ chart_test }}-{{ chart_test_version }}"
- install.status.chart == chart_test+"-"+chart_test_version
- install.status['values'] == {}
- name: "Upgrade {{ chart_test }} from {{ source }}"
@@ -199,7 +199,7 @@
that:
- install is changed
- 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
helm:
@@ -215,7 +215,7 @@
that:
- install is not changed
- 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 }}"
helm:
@@ -316,7 +316,7 @@
that:
- install is changed
- 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"
- name: "Install {{ chart_test }} from {{ source }} with values_files (again)"
@@ -357,7 +357,7 @@
- result is changed
- result is not failed
- 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
stat:
@@ -374,8 +374,8 @@
chart_ref: "{{ chart_source }}"
chart_version: "{{ chart_source_version | default(omit) }}"
disable_hook: True
release_name: "myrelease"
release_namespace: "myreleasenamespace"
release_name: "MyRelease"
release_namespace: "MyReleaseNamespace"
show_only:
- "templates/configmap.yaml"
release_values:
@@ -388,7 +388,7 @@
- result is changed
- result is not failed
- 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")
when: chart_source is search("test-chart")
# limit assertion of test result to controlled (local) chart_source

View File

@@ -1,6 +0,0 @@
apiVersion: v2
name: test-chart-deployment-time
description: A chart with a config map containing the deployment time in data
type: application
version: 0.1.0
appVersion: "default"

View File

@@ -1,7 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ default "ansible-configmap" .Values.myConfigmapName }}
data:
myValue: {{ default "test" .Values.myValue }}
deploymentTime: {{ now }}

View File

@@ -2,4 +2,3 @@
dependencies:
- remove_namespace
- install_helm
- setup_helm_registry

View File

@@ -2,6 +2,7 @@
- name: Test helm diff functionality
vars:
test_chart_ref: "/tmp/test-chart"
redis_chart_version: '17.0.5'
block:
@@ -23,7 +24,7 @@
name: test-chart
namespace: "{{ helm_namespace }}"
chart_ref: "{{ test_chart_ref }}"
create_namespace: true
create_namespace: yes
register: install
- assert:
@@ -48,8 +49,8 @@
name: test-chart
namespace: "{{ helm_namespace }}"
chart_ref: "{{ test_chart_ref }}"
check_mode: true
diff: true
check_mode: yes
diff: yes
register: diff_result
- name: Check if helm diff check is correct
@@ -78,7 +79,7 @@
namespace: "{{ helm_namespace }}"
chart_ref: "{{ test_chart_ref }}"
check_mode: yes
diff: true
diff: yes
register: diff_result
- name: Check if no diff in check mode when no change
@@ -100,7 +101,7 @@
- name: Modify values
blockinfile:
create: true
create: yes
path: "{{ test_chart_ref }}/values.yml"
block: |
---
@@ -205,76 +206,52 @@
- install is not changed
# 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
helm_plugin:
binary_path: "{{ helm_binary }}"
state: absent
plugin_name: diff
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."
ignore_errors: yes
- name: Install helm diff (version=3.4.1)
helm_plugin:
@@ -283,36 +260,37 @@
plugin_path: https://github.com/databus23/helm-diff
plugin_version: 3.4.1
- name: Upgrade chart once again
- name: Upgrade Redis chart once again
helm:
binary_path: "{{ helm_binary }}"
chart_ref: "{{ test_chart_ref_url }}"
chart_version: 0.1.0
chart_repo_url: https://charts.bitnami.com/bitnami
chart_ref: redis
namespace: "{{ helm_namespace }}"
name: another-chart
release_values: "{{ test_chart_values }}"
check_mode: true
register: _upgrade_2
name: redis-chart
chart_version: "{{ redis_chart_version }}"
release_values: "{{ redis_chart_values }}"
check_mode: yes
register: redis_upgrade_2
- name: Assert that module raised a warning
assert:
that:
- _upgrade_2.changed
- _upgrade_2.warnings is not defined
- redis_upgrade_2.changed
- redis_upgrade_2.warnings is not defined
always:
- name: Remove chart directory
file:
path: "{{ test_chart_ref }}"
state: absent
ignore_errors: true
ignore_errors: yes
- name: Uninstall helm diff
helm_plugin:
binary_path: "{{ helm_binary }}"
state: absent
plugin_name: diff
ignore_errors: true
ignore_errors: yes
- name: Remove helm namespace
k8s:
@@ -321,6 +299,6 @@
name: "{{ helm_namespace }}"
state: absent
wait: true
ignore_errors: true
ignore_errors: yes
- include_tasks: reuse_values.yml

View File

@@ -18,12 +18,7 @@
- set_fact:
saved_kubeconfig_path: "{{ _dir.path }}/config"
- vars:
helm_repo_name: autoscaler
helm_repo_url: "https://kubernetes.github.io/autoscaler"
helm_release_name: "autoscaler"
helm_chart_name: "cluster-autoscaler"
block:
- block:
- name: Copy default kubeconfig
copy:
remote_src: true
@@ -64,14 +59,14 @@
- plugin_info.plugin_list != []
# helm_repository, helm, helm_info
- name: 'Add "{{ helm_repo_name }}" chart repository'
- name: Add test_bitnami chart repository
helm_repository:
binary_path: "{{ helm_binary }}"
name: "{{ helm_repo_name }}"
name: test_bitnami
kubeconfig: "{{ test_kubeconfig | default(omit) }}"
validate_certs: "{{ test_validate_certs | default(omit) }}"
ca_cert: "{{ test_ca_cert | default(omit) }}"
repo_url: "{{ helm_repo_url }}"
repo_url: https://charts.bitnami.com/bitnami
register: repository
- name: Assert that repository was added
@@ -82,8 +77,8 @@
- name: Install chart from repository added before
helm:
binary_path: "{{ helm_binary }}"
name: "{{ helm_release_name }}"
chart_ref: "{{ helm_repo_name }}/{{ helm_chart_name }}"
name: rabbitmq
chart_ref: test_bitnami/rabbitmq
namespace: "{{ helm_namespace }}"
update_repo_cache: true
kubeconfig: "{{ test_kubeconfig | default(omit) }}"
@@ -103,7 +98,7 @@
kubeconfig: "{{ test_kubeconfig | default(omit) }}"
validate_certs: "{{ test_validate_certs | default(omit) }}"
ca_cert: "{{ test_ca_cert | default(omit) }}"
name: "{{ helm_release_name }}"
name: "rabbitmq"
namespace: "{{ helm_namespace }}"
register: chart_info
@@ -117,7 +112,7 @@
- name: Remove chart
helm:
binary_path: "{{ helm_binary }}"
name: "{{ helm_release_name }}"
name: rabbitmq
namespace: "{{ helm_namespace }}"
kubeconfig: "{{ test_kubeconfig | default(omit) }}"
validate_certs: "{{ test_validate_certs | default(omit) }}"
@@ -136,7 +131,7 @@
kubeconfig: "{{ test_kubeconfig | default(omit) }}"
validate_certs: "{{ test_validate_certs | default(omit) }}"
ca_cert: "{{ test_ca_cert | default(omit) }}"
name: "{{ helm_release_name }}"
name: "rabbitmq"
namespace: "{{ helm_namespace }}"
register: chart_info
@@ -148,7 +143,7 @@
- name: Remove chart repository
helm_repository:
binary_path: "{{ helm_binary }}"
name: "{{ helm_repo_name }}"
name: test_bitnami
kubeconfig: "{{ test_kubeconfig | default(omit) }}"
validate_certs: "{{ test_validate_certs | default(omit) }}"
ca_cert: "{{ test_ca_cert | default(omit) }}"
@@ -197,6 +192,6 @@
- name: Delete helm repository
helm_repository:
binary_path: "{{ helm_binary }}"
name: "{{ helm_repo_name }}"
name: test_bitnami
state: absent
ignore_errors: true

View File

@@ -180,7 +180,6 @@
- '"--username ansible" in _result.command'
- '"--password ***" 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
helm_pull:
@@ -204,8 +203,9 @@
- name: Download chart using untar_chart
helm_pull:
binary_path: "{{ helm_path }}"
chart_ref: "oci://registry-1.docker.io/bitnamicharts/redis"
chart_ref: redis
destination: "{{ destination }}"
repo_url: "https://charts.bitnami.com/bitnami"
untar_chart: true
register: _result

View File

@@ -1,7 +1,8 @@
- name: Install helm using set_values parameters
helm:
binary_path: "{{ helm_binary }}"
chart_ref: oci://registry-1.docker.io/bitnamicharts/mariadb
chart_ref: mariadb
chart_repo_url: https://charts.bitnami.com/bitnami
release_name: test-mariadb
release_namespace: "{{ helm_namespace }}"
create_namespace: true
@@ -35,7 +36,8 @@
- name: Install helm using set_values parameters
helm:
binary_path: "{{ helm_binary }}"
chart_ref: oci://registry-1.docker.io/bitnamicharts/apache
chart_ref: apache
chart_repo_url: https://charts.bitnami.com/bitnami
release_name: test-apache
release_namespace: "{{ helm_namespace }}"
create_namespace: true
@@ -77,7 +79,8 @@
- name: Install helm using set_values parameters
helm:
binary_path: "{{ helm_binary }}"
chart_ref: oci://registry-1.docker.io/bitnamicharts/minio
chart_ref: minio
chart_repo_url: https://charts.bitnami.com/bitnami
release_name: test-minio
release_namespace: "{{ helm_namespace }}"
create_namespace: true
@@ -104,11 +107,3 @@
file:
state: absent
path: "{{ ymlfile.path }}"
ignore_errors: true
- name: Delete namespace
k8s:
state: absent
kind: namespace
name: "{{ helm_namespace }}"
ignore_errors: true

View File

@@ -1,4 +1,4 @@
---
helm_version: v3.8.0
helm_version: v3.7.0
helm_install_path: /tmp/helm
helm_default_archive_name: "helm-{{ helm_version }}-{{ ansible_system | lower }}-amd64.tar.gz"

View File

@@ -26,8 +26,7 @@
assert:
that:
- k8s_configmap is changed
- '"annotations" in k8s_configmap.result.metadata'
- k8s_configmap.result.metadata.annotations != {}
- k8s_configmap.result.metadata.annotations|default(False)
- name: Add same configmap again
k8s:
@@ -468,7 +467,7 @@
assert:
that:
- k8s_secret is changed
- k8s_secret.result.data.foo != ""
- k8s_secret.result.data.foo
- name: Add same secret
k8s:
@@ -749,7 +748,7 @@
assert:
that:
- _create is changed
- _info.resources | length == 0
- not _info.resources
# server side apply over kubernetes client releases
- name: Create temporary directory

View File

@@ -38,7 +38,7 @@
- name: Assert that there are pods
assert:
that:
- pods_create.resources | length > 0
- pods_create.resources
- name: Remove the daemonset
k8s:
@@ -74,7 +74,7 @@
- name: Assert that deleting the daemonset deleted the pods
assert:
that:
- pods_delete.resources | length == 0
- not pods_delete.resources
# test deletion using label selector
- name: Deploy load balancer
@@ -152,27 +152,6 @@
register: _deployment
failed_when: _deployment.resources | length == 0
- name: Trying to delete nginx deployment in check mode and with deleteOptions set
k8s:
kind: Deployment
api_version: apps/v1
namespace: "{{ test_namespace }}"
name: nginx-d
state: absent
delete_options:
propagationPolicy: Foreground
check_mode: true
register: _delete
- name: Validate that Deployment nginx-d still exists
k8s_info:
kind: Deployment
api_version: apps/v1
namespace: "{{ test_namespace }}"
name: nginx-d
register: _deployment
failed_when: _deployment.resources | length != 1
- name: Trying to delete using delete_all=true but missing kind option
k8s:
api_version: apps/v1

View File

@@ -182,7 +182,7 @@
- name: assert that pods are running on cordoned node
assert:
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
k8s_drain:
@@ -236,7 +236,7 @@
assert:
that:
- 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
k8s_info:
@@ -244,7 +244,7 @@
kind: Pod
name: '{{ drain_pod_name }}'
register: _result
failed_when: _result.resources | length > 0
failed_when: _result.resources
- name: assert that emptyDir pod was deleted
k8s_info:
@@ -338,7 +338,7 @@
assert:
that:
- 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
k8s_info:
@@ -346,7 +346,7 @@
kind: Pod
name: '{{ drain_pod_name }}-01'
register: _result
failed_when: _result.resources | length > 0
failed_when: _result.resources
# test: drain using pod_selectors
- name: Uncordon node
@@ -401,7 +401,7 @@
assert:
that:
- 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
k8s_info:
@@ -429,8 +429,8 @@
assert:
that:
- drain_pod_selector_equal is changed
- '"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'
- '"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'
- name: Uncordon node
k8s_drain:

View File

@@ -394,11 +394,9 @@
register: k8s_info_testing6
failed_when: not k8s_info_testing6.resources or k8s_info_testing6.resources[0].status.phase != "Active"
- name: Create a file with specific size and attributes, to be used as swap space
community.general.filesize:
path: /tmp/configmap.bin
size: 500K
source: /dev/urandom
- name: Create large configmap data
command: dd if=/dev/urandom bs=500K count=1
register: cmap_data
- name: Create configmap with large value
k8s:
@@ -409,7 +407,7 @@
name: testmap
namespace: testing
data:
testkey: "{{ lookup('file', '/tmp/configmap.bin') | b64encode }}"
testkey: "{{ cmap_data.stdout | b64encode }}"
wait: true
register: result
@@ -426,7 +424,7 @@
- assert:
that:
- result.resources[0].data.testkey == (lookup('file', '/tmp/configmap.bin') | b64encode)
- result.resources[0].data.testkey == (cmap_data.stdout | b64encode)
# test setting module defaults for kubernetes.core.k8s_info
- block:

View File

@@ -36,7 +36,7 @@
label_selectors:
- "job=gc"
register: wait_job
until: wait_job.resources | length > 0
until: wait_job.resources
retries: 5
delay: 10
@@ -87,7 +87,7 @@
label_selectors:
- "job=gc"
register: wait_job
until: wait_job.resources | length > 0
until: wait_job.resources
retries: 5
delay: 10
@@ -139,7 +139,7 @@
label_selectors:
- "job=gc"
register: wait_job
until: wait_job.resources | length > 0
until: wait_job.resources
retries: 5
delay: 10
@@ -225,7 +225,7 @@
- name: Assert job is deleted
assert:
that: job.resources | length == 0
that: not job.resources
always:
- name: Delete namespace

View File

@@ -69,7 +69,7 @@
- name: assert pod has been created
assert:
that:
- "{{ pods.resources | length == 1 }}"
- pods.resources | length == 1
- name: create pod using generate_name parameter should succeed
k8s:
@@ -86,7 +86,7 @@
- name: assert pod has been created
assert:
that:
- "{{ pods.resources | length == 2 }}"
- pods.resources | length == 2
- name: create pod using metadata.generateName parameter should succeed
k8s:
@@ -102,7 +102,7 @@
- name: assert pod has been created
assert:
that:
- "{{ pods.resources | length == 3 }}"
- pods.resources | length == 3
- name: create object using metadata.generateName should support wait option
k8s:

View File

@@ -47,7 +47,7 @@
- result.changed
- result.result.metadata.labels.label2 == "bar"
- result.result.spec.containers[0].image == "busybox:glibc"
- result.diff != {}
- result.diff
- name: Describe pod
kubernetes.core.k8s_info:

View File

@@ -11,7 +11,7 @@
assert:
that:
- 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
k8s:

View File

@@ -23,7 +23,7 @@
- name: Update directory permissions
file:
path: "{{ manifests_dir.path }}"
mode: '0755'
mode: 0755
- name: Create manifests files
copy:

View File

@@ -129,7 +129,7 @@
that:
- scale_down is changed
- '"duration" in scale_down'
- scale_down.diff != {}
- scale_down.diff
- name: Scale the deployment once again (idempotency)
k8s_scale:
@@ -274,7 +274,7 @@
assert:
that:
- scale_down_no_wait is changed
- scale_down_no_wait.diff != {}
- scale_down_no_wait.diff
- scale_down_no_wait_pods.resources | length == 1
# scale multiple resource using label selectors

View File

@@ -65,7 +65,7 @@
assert:
that:
- _result.result.status.phase == 'Running'
- _result.result.spec.nodeName == "{{ node_to_taint }}"
- _result.result.spec.nodeName == node_to_taint
- name: Taint node (check_mode)
kubernetes.core.k8s_taint:
@@ -89,8 +89,8 @@
assert:
that:
- _result.changed
- "{{ item['effect'] == taint_patch_1[0]['effect'] }}"
- "{{ item['key'] == taint_patch_1[0]['key'] }}"
- item['effect'] == taint_patch_1[0]['effect']
- item['key'] == taint_patch_1[0]['key']
loop: "{{ _result.result.spec.taints }}"
- name: Taint node (idempotency) - (check_mode)
@@ -421,7 +421,7 @@
- name: Assert that taints have been removed
assert:
that:
- _result.resources | selectattr('spec.taints', 'undefined') | list | length > 0
- _result.resources | selectattr('spec.taints', 'undefined')
always:

View File

@@ -7,7 +7,7 @@
kubernetes.core.k8s_service:
template: "pod_one.j2"
state: present
ignore_errors: true
ignore_errors: yes
register: r
- name: Check for expected failures in last tasks
@@ -35,7 +35,7 @@
k8s_pod_name_one: pod
k8s_pod_namespace: "{{ template_namespace }}"
register: r
ignore_errors: true
ignore_errors: yes
- name: Check if definition and template are mutually exclusive
assert:
@@ -52,7 +52,7 @@
k8s_pod_name_one: pod
k8s_pod_namespace: "{{ template_namespace }}"
register: r
ignore_errors: true
ignore_errors: yes
- name: Check if src and template are mutually exclusive
assert:
@@ -63,7 +63,7 @@
- name: Create pod using template (direct specification)
kubernetes.core.k8s:
template: "pod_one.j2"
wait: true
wait: yes
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
vars:
k8s_pod_name_one: pod-1
@@ -79,7 +79,7 @@
kubernetes.core.k8s:
template:
- default
wait: true
wait: yes
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
vars:
k8s_pod_name_one: pod-2
@@ -96,7 +96,7 @@
kubernetes.core.k8s:
template:
path: "pod_one.j2"
wait: true
wait: yes
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
vars:
k8s_pod_name_one: pod-3
@@ -114,11 +114,12 @@
path: "pod_two.j2"
variable_start_string: '[['
variable_end_string: ']]'
wait: true
wait: yes
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
vars:
k8s_pod_name_two: pod-4
k8s_pod_namespace: "template-test"
k8s_pod_namespace: "[[ template_namespace ]]"
ansible_python_interpreter: "[[ ansible_playbook_python ]]"
register: r
- name: Assert that pod creation succeeded using template
@@ -130,7 +131,7 @@
kubernetes.core.k8s:
template:
path: "pod_three.j2"
wait: true
wait: yes
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
vars:
k8s_pod_name_three_one: pod-5
@@ -151,7 +152,7 @@
variable_start_string: '[['
variable_end_string: ']]'
- path: "pod_three.j2"
wait: true
wait: yes
wait_timeout: "{{ k8s_wait_timeout | default(omit) }}"
vars:
k8s_pod_name_one: pod-7
@@ -212,8 +213,8 @@
- name: check that resources creation failed
assert:
that:
- '{{ resource.results[0].resources | length == 0 }}'
- '{{ resource.results[1].resources | length == 0 }}'
- resource.results.0.resources | length == 0
- resource.results.1.resources | length == 0
- name: create pod without namespace (continue_on_error = true)
kubernetes.core.k8s:
@@ -238,6 +239,63 @@
- resource.result.results | selectattr('changed') | list | length == 1
- resource.result.results | selectattr('error', 'defined') | list | length == 1
# Test resource definition using template with 'omit'
- name: Deploy configmap using template
k8s:
namespace: "{{ template_namespace }}"
name: test-data
template: configmap.yml.j2
- name: Read configmap created
k8s_info:
kind: configmap
namespace: "{{ template_namespace }}"
name: test-data
register: _configmap
- name: Validate that the configmap does not contains annotations
assert:
that:
- '"annotations" not in _configmap.resources.0.metadata'
- name: Create resource once again
k8s:
namespace: "{{ template_namespace }}"
name: test-data
template: configmap.yml.j2
register: _configmap
- name: assert that nothing changed
assert:
that:
- _configmap is not changed
- name: Create resource once again (using description)
k8s:
namespace: "{{ template_namespace }}"
name: test-data
template: configmap.yml.j2
register: _configmap
vars:
k8s_configmap_desc: "This is a simple configmap used to test ansible k8s collection"
- name: assert that configmap was changed
assert:
that:
- _configmap is changed
- name: Read configmap created
k8s_info:
kind: configmap
namespace: "{{ template_namespace }}"
name: test-data
register: _configmap
- name: Validate that the configmap does not contains annotations
assert:
that:
- _configmap.resources.0.metadata.annotations.description == "This is a simple configmap used to test ansible k8s collection"
always:
- name: Remove namespace (Cleanup)
kubernetes.core.k8s:

View File

@@ -0,0 +1,7 @@
apiVersion: v1
kind: ConfigMap
metadata:
annotations:
description: "{{ k8s_configmap_desc | default(omit) }}"
data:
key: "testing-template"

View File

@@ -5,7 +5,6 @@ k8s_pod_metadata:
k8s_pod_spec:
serviceAccount: "{{ k8s_pod_service_account }}"
nodeSelector: "{{ k8s_pod_node_selector }}"
containers:
- image: "{{ k8s_pod_image }}"
imagePullPolicy: Always
@@ -34,8 +33,6 @@ k8s_pod_ports: []
k8s_pod_env: []
k8s_pod_node_selector: {}
k8s_pod_template:
metadata: "{{ k8s_pod_metadata }}"
spec: "{{ k8s_pod_spec }}"

View File

@@ -127,48 +127,6 @@
- ds.result.status.currentNumberScheduled == ds.result.status.desiredNumberScheduled
- 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
k8s:
definition:

View File

@@ -56,8 +56,8 @@
# Without wantlist=True lookup should return mapping
- test5 is mapping
- test6 is mapping
# errors='ignore' (return null with ansible-core 2.19)
- test7 is string or not test7
# errors='ignore'
- test7 is string
- test8 is not defined
- name: Create another namespace with label
@@ -130,9 +130,9 @@
assert:
that:
- result_configmap.apiVersion == 'v1'
- result_configmap.metadata.name == "{{ configmap_name }}"
- result_configmap.metadata.namespace == "{{ test_namespace[2] }}"
- result_configmap.data.value == "{{ configmap_data }}"
- result_configmap.metadata.name == configmap_name
- result_configmap.metadata.namespace == test_namespace[2]
- result_configmap.data.value == configmap_data
# test lookup plugin using src parameter
- block:
@@ -159,9 +159,9 @@
assert:
that:
- src_configmap.apiVersion == 'v1'
- src_configmap.metadata.name == "{{ configmap_name }}"
- src_configmap.metadata.namespace == "{{ test_namespace[2] }}"
- src_configmap.data.value == "{{ configmap_data }}"
- src_configmap.metadata.name == configmap_name
- src_configmap.metadata.namespace == test_namespace[2]
- src_configmap.data.value == configmap_data
always:
- name: Delete temporary file created
@@ -198,9 +198,9 @@
assert:
that:
- configmap_no_ssl.apiVersion == 'v1'
- configmap_no_ssl.metadata.name == "{{ configmap_name }}"
- configmap_no_ssl.metadata.namespace == "{{ test_namespace[2] }}"
- configmap_no_ssl.data.value == "{{ configmap_data }}"
- configmap_no_ssl.metadata.name == configmap_name
- configmap_no_ssl.metadata.namespace == test_namespace[2]
- configmap_no_ssl.data.value == configmap_data
- name: Retrieve configmap using authentication aliases (validate_certs=true)
set_fact:
@@ -210,9 +210,9 @@
assert:
that:
- configmap_with_ssl.apiVersion == 'v1'
- configmap_with_ssl.metadata.name == "{{ configmap_name }}"
- configmap_with_ssl.metadata.namespace == "{{ test_namespace[2] }}"
- configmap_with_ssl.data.value == "{{ configmap_data }}"
- configmap_with_ssl.metadata.name == configmap_name
- configmap_with_ssl.metadata.namespace == test_namespace[2]
- configmap_with_ssl.data.value == configmap_data
always:
- name: Delete temporary directory

View File

@@ -45,7 +45,7 @@
- name: make script as executable
file:
path: "{{ tmp_dir_path }}/install_kustomize.sh"
mode: '0755'
mode: 0755
- name: Install kustomize
command: "{{ tmp_dir_path }}/install_kustomize.sh"

View File

@@ -1 +0,0 @@
disabled

View File

@@ -1,5 +0,0 @@
---
helm_binary_path: "helm"
chart_repo_url: 'localhost:6035'
chart_repo_username: testuser
chart_repo_password: 'pass123!'

View File

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

View File

@@ -1 +0,0 @@
disabled

View File

@@ -1,5 +0,0 @@
---
# user: testuser, password: pass123!
registry_credentials: testuser:$2y$05$d8tw6L1hojRFW.FjHOAnIOihJWAvFb0/Pu/30hLbQNJIYzCmlyBCi
registry_name: helm_registry
registry_port: 6035

View File

@@ -1,3 +0,0 @@
---
- name: Teardown registry
include_tasks: teardown_registry.yml

View File

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

View File

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

View File

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

View File

@@ -4,17 +4,10 @@
namespace_to_create: "{{ item.name | default(item) }}"
namespace_labels: "{{ item.labels | default(omit) }}"
with_items: "{{ test_namespace }}"
when:
- test_namespace is not string
- test_namespace is not mapping
- test_namespace is iterable
when: test_namespace | type_debug == "list"
- include_tasks: tasks/create.yml
vars:
namespace_to_create: "{{ test_namespace }}"
namespace_labels: "{{ test_namespace_labels | default(omit) }}"
when:
- test_namespace is string
- test_namespace is iterable
- test_namespace is sequence
- test_namespace is not mapping
when: test_namespace | type_debug == "AnsibleUnicode"

View File

@@ -1,18 +1,9 @@
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.10!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.10!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.10!skip
plugins/module_utils/k8sdynamicclient.py import-3.11!skip
@@ -34,4 +25,3 @@ plugins/modules/k8s_service.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/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

View File

@@ -1,18 +1,9 @@
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.10!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.10!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.10!skip
plugins/module_utils/k8sdynamicclient.py import-3.11!skip
@@ -35,4 +26,3 @@ 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

View File

@@ -1,20 +1,11 @@
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.10!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/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.10!skip
plugins/module_utils/client/resource.py import-3.11!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.10!skip
plugins/module_utils/k8sdynamicclient.py import-3.11!skip
@@ -38,4 +29,3 @@ 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

View File

@@ -29,4 +29,3 @@ 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

View File

@@ -1,12 +1,15 @@
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.12!skip
plugins/module_utils/client/discovery.py import-3.13!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.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.9!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.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
@@ -26,4 +29,3 @@ 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

View File

@@ -1,29 +0,0 @@
plugins/module_utils/client/discovery.py import-3.11!skip
plugins/module_utils/client/discovery.py import-3.12!skip
plugins/module_utils/client/discovery.py import-3.13!skip
plugins/module_utils/client/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

View File

@@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2022, Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from datetime import datetime
from ansible_collections.kubernetes.core.plugins.action.k8s_info import RemoveOmit
def get_omit_token():
return "__omit_place_holder__%s" % datetime.now().strftime("%Y%m%d%H%M%S")
def test_remove_omit_from_str():
omit_token = get_omit_token()
src = """
project: ansible
collection: {omit}
""".format(
omit=omit_token
)
result = RemoveOmit(src, omit_value=omit_token).output()
assert len(result) == 1
assert result[0] == dict(project="ansible")
def test_remove_omit_from_list():
omit_token = get_omit_token()
src = """
items:
- {omit}
""".format(
omit=omit_token
)
result = RemoveOmit(src, omit_value=omit_token).output()
assert len(result) == 1
assert result[0] == dict(items=[])
def test_remove_omit_from_list_of_dict():
omit_token = get_omit_token()
src = """
items:
- owner: ansible
team: {omit}
- simple_list_item
""".format(
omit=omit_token
)
result = RemoveOmit(src, omit_value=omit_token).output()
assert len(result) == 1
assert result[0] == dict(items=[dict(owner="ansible"), "simple_list_item"])
def test_remove_omit_combined():
omit_token = get_omit_token()
src = """
items:
- {omit}
- list_item_a
- list_item_b
parent:
child:
subchilda: {omit}
subchildb:
name: {omit}
age: 3
""".format(
omit=omit_token
)
result = RemoveOmit(src, omit_value=omit_token).output()
assert len(result) == 1
assert result[0] == dict(
items=["list_item_a", "list_item_b"],
parent=dict(child=dict(subchildb=dict(age=3))),
)
def test_remove_omit_mutiple_documents():
omit_token = get_omit_token()
src = [
"""
project: ansible
collection: {omit}
""".format(
omit=omit_token
),
"---",
"""
project: kubernetes
environment: production
collection: {omit}""".format(
omit=omit_token
),
]
src = "\n".join(src)
print(src)
result = RemoveOmit(src, omit_value=omit_token).output()
assert len(result) == 2
assert result[0] == dict(project="ansible")
assert result[1] == dict(project="kubernetes", environment="production")

View File

@@ -44,8 +44,8 @@ def test_warn_on_k8s_version(monkeypatch, stdin, capfd):
assert return_value.get("warnings") is not None
warnings = return_value["warnings"]
assert len(warnings) == 1
assert "kubernetes" in str(warnings[0])
assert MINIMAL_K8S_VERSION in str(warnings[0])
assert "kubernetes" in warnings[0]
assert MINIMAL_K8S_VERSION in warnings[0]
dependencies = [

View File

@@ -200,10 +200,6 @@ def test_module_get_values(_ansible_helm_module, no_values, get_all):
'version.BuildInfo{Version:"v3.10.3", GitCommit:7870ab3ed4135f136eec, GoVersion:"go1.18.9"}',
"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"', None),
],

View File

@@ -31,7 +31,7 @@ modified_def["metadata"]["labels"]["environment"] = "testing"
@pytest.mark.parametrize(
"action, params, existing, instance, expected",
"action, params, existing, instance_warnings, expected",
[
(
"delete",
@@ -51,14 +51,26 @@ modified_def["metadata"]["labels"]["environment"] = "testing"
"apply",
{"apply": "yes"},
{},
definition,
(definition, []),
{"changed": True, "method": "apply", "result": definition},
),
(
"apply",
{"apply": "yes"},
{},
(definition, ["test warning"]),
{
"changed": True,
"method": "apply",
"result": definition,
"warnings": ["test warning"],
},
),
(
"create",
{"state": "patched"},
{},
{},
({}, []),
{
"changed": False,
"result": {},
@@ -71,42 +83,78 @@ modified_def["metadata"]["labels"]["environment"] = "testing"
"create",
{},
{},
definition,
(definition, []),
{"changed": True, "method": "create", "result": definition},
),
(
"create",
{},
{},
(definition, ["test warning"]),
{
"changed": True,
"method": "create",
"result": definition,
"warnings": ["test warning"],
},
),
(
"replace",
{"force": "yes"},
definition,
definition,
(definition, []),
{"changed": False, "method": "replace", "result": definition},
),
(
"replace",
{"force": "yes"},
definition,
modified_def,
(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",
{},
definition,
definition,
(definition, []),
{"changed": False, "method": "update", "result": definition},
),
(
"update",
{},
definition,
modified_def,
(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",
{"label_selectors": ["app=foo"]},
{},
definition,
(definition, []),
{
"changed": False,
"msg": "resource 'kind=Pod,name=foo,namespace=foo' filtered by label_selectors.",
@@ -116,18 +164,18 @@ modified_def["metadata"]["labels"]["environment"] = "testing"
"create",
{"label_selectors": ["app=nginx"]},
{},
definition,
(definition, []),
{"changed": True, "method": "create", "result": definition},
),
],
)
def test_perform_action(action, params, existing, instance, expected):
def test_perform_action(action, params, existing, instance_warnings, expected):
svc = Mock()
svc.find_resource.return_value = Mock(
kind=definition["kind"], group_version=definition["apiVersion"]
)
svc.retrieve.return_value = ResourceInstance(None, existing) if existing else None
spec = {action + ".return_value": instance}
spec = {action + ".return_value": instance_warnings}
svc.configure_mock(**spec)
result = perform_action(svc, definition, params)

View File

@@ -1,9 +1,11 @@
from json import dumps
from unittest.mock import Mock
import pytest
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.service import (
K8sService,
diff_objects,
parse_quoted_string,
)
from kubernetes.dynamic.exceptions import NotFoundError
from kubernetes.dynamic.resource import Resource, ResourceInstance
@@ -57,6 +59,22 @@ def mock_pod_updated_resource_instance():
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():
match, diff = diff_objects(pod_definition, pod_definition)
@@ -159,16 +177,33 @@ def test_service_delete_existing_resource_check_mode(mock_pod_resource_instance)
client.delete.assert_not_called()
def test_service_create_resource(mock_pod_resource_instance):
spec = {"create.side_effect": [mock_pod_resource_instance]}
def test_service_create_resource(mock_pod_response, mock_pod_resource_instance):
spec = {"create.side_effect": [mock_pod_response]}
client = Mock(**spec)
module = Mock()
module.params = {}
module.check_mode = False
svc = K8sService(client, module)
result = svc.create(Mock(), pod_definition)
result, warnings = svc.create(Mock(), pod_definition)
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():
@@ -176,9 +211,10 @@ def test_service_create_resource_check_mode():
client.create.return_value = mock_pod_resource_instance
module = Mock(params={}, check_mode=True)
svc = K8sService(client, module)
result = svc.create(Mock(), pod_definition)
result, warnings = svc.create(Mock(), pod_definition)
assert result == pod_definition
assert not warnings
client.create.assert_not_called()
@@ -224,40 +260,99 @@ def test_create_project_request():
assert results["result"] == project_definition
def test_service_apply_existing_resource(mock_pod_resource_instance):
spec = {"apply.side_effect": [mock_pod_resource_instance]}
def test_service_apply_existing_resource(mock_pod_response, mock_pod_resource_instance):
spec = {"apply.side_effect": [mock_pod_response]}
client = Mock(**spec)
module = Mock()
module.params = {"apply": True}
module.check_mode = False
svc = K8sService(client, module)
result = svc.apply(Mock(), pod_definition_updated, mock_pod_resource_instance)
result, warnings = svc.apply(
Mock(), pod_definition_updated, mock_pod_resource_instance
)
assert result == mock_pod_resource_instance.to_dict()
assert not warnings
def test_service_replace_existing_resource(mock_pod_resource_instance):
spec = {"replace.side_effect": [mock_pod_resource_instance]}
def test_service_apply_existing_resource_warnings(
mock_pod_warnings_response, 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)
module = Mock()
module.params = {}
module.check_mode = False
svc = K8sService(client, module)
result = svc.replace(Mock(), pod_definition, mock_pod_resource_instance)
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(mock_pod_resource_instance):
spec = {"replace.side_effect": [mock_pod_resource_instance]}
def test_service_replace_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 = svc.replace(Mock(), pod_definition, mock_pod_resource_instance)
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_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):
@@ -288,3 +383,24 @@ def test_service_find_error():
assert isinstance(results, dict)
assert results["api_found"] is True
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