mirror of
https://github.com/ansible-collections/kubernetes.core.git
synced 2026-05-11 20:12:18 +00:00
Compare commits
292 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6dadd06252 | ||
|
|
69dc7d5c5d | ||
|
|
2fa1c2c6e5 | ||
|
|
f2623dd3cf | ||
|
|
8772d8c997 | ||
|
|
a32108f64f | ||
|
|
365e5e9159 | ||
|
|
448a68da3d | ||
|
|
46acab9c4c | ||
|
|
fdb77182c8 | ||
|
|
fa3d94f793 | ||
|
|
9ec27cf37c | ||
|
|
10cb241256 | ||
|
|
92e1f581fe | ||
|
|
7f69aff0d6 | ||
|
|
8c65ac066d | ||
|
|
1d962fb932 | ||
|
|
27ce23aa72 | ||
|
|
993652b581 | ||
|
|
9bd9d22db3 | ||
|
|
0593426918 | ||
|
|
8fa5b201a4 | ||
|
|
94c1f57f36 | ||
|
|
d0b97319a5 | ||
|
|
38d5c81051 | ||
|
|
914a16ec5c | ||
|
|
cb2070c93f | ||
|
|
b594d35931 | ||
|
|
00699ac3e5 | ||
|
|
d329e7ee42 | ||
|
|
d4fc22c74e | ||
|
|
b648f45e90 | ||
|
|
2cb5d6c316 | ||
|
|
0e7229cf8d | ||
|
|
9ec6912325 | ||
|
|
7cdf0d03f5 | ||
|
|
91df2f10bc | ||
|
|
1943dfc3d9 | ||
|
|
eb731cd3a5 | ||
|
|
ecc64cace1 | ||
|
|
bc0de24cba | ||
|
|
9f60b151ba | ||
|
|
159a63af97 | ||
|
|
6efabd3418 | ||
|
|
aee847431a | ||
|
|
6609abdd5a | ||
|
|
219c747a24 | ||
|
|
7559b65946 | ||
|
|
c8a33c7180 | ||
|
|
52f2cb5587 | ||
|
|
513ff66fcf | ||
|
|
fca0dc0485 | ||
|
|
cd686316e9 | ||
|
|
b8e9873f64 | ||
|
|
4c305e73f0 | ||
|
|
c8a9326306 | ||
|
|
445d367059 | ||
|
|
fdb8af7ca9 | ||
|
|
a89f19b4e5 | ||
|
|
5bc53dba7c | ||
|
|
b07fbd6271 | ||
|
|
44a2fc392a | ||
|
|
6265a3e7ce | ||
|
|
0afd257dd0 | ||
|
|
d192157ed8 | ||
|
|
6a04f42d0b | ||
|
|
5064d722c3 | ||
|
|
fb80d973c4 | ||
|
|
8363a4debf | ||
|
|
0c5233a650 | ||
|
|
c0666a5137 | ||
|
|
072a08091b | ||
|
|
cbadbe32f9 | ||
|
|
966fa7e906 | ||
|
|
485eae3b10 | ||
|
|
a4c1bd8541 | ||
|
|
8858b19121 | ||
|
|
6360763098 | ||
|
|
ac943e9890 | ||
|
|
0408aa9328 | ||
|
|
874fbfedd5 | ||
|
|
d8d9133912 | ||
|
|
86d9a3f45f | ||
|
|
fb25ff44f1 | ||
|
|
600c10dffb | ||
|
|
9f7c865c9c | ||
|
|
23e94b60c1 | ||
|
|
1955989278 | ||
|
|
7c4ec3b982 | ||
|
|
8d15489ec2 | ||
|
|
3dcdcbc85d | ||
|
|
fe9c12326d | ||
|
|
1a601213eb | ||
|
|
abb9e0b6d5 | ||
|
|
bdd429981c | ||
|
|
6956a77f8c | ||
|
|
1670e35cd8 | ||
|
|
b44fdd3f05 | ||
|
|
b066a2dda3 | ||
|
|
9e9962bc6c | ||
|
|
9ca13c3799 | ||
|
|
318529abaa | ||
|
|
6d0a3af311 | ||
|
|
54d8193972 | ||
|
|
a624251bba | ||
|
|
869f06f1e4 | ||
|
|
7919231df1 | ||
|
|
ea28cbaa59 | ||
|
|
560e0e3d40 | ||
|
|
ed09047699 | ||
|
|
2d1ec22405 | ||
|
|
71599e2fde | ||
|
|
8687994e9f | ||
|
|
8640c16cd4 | ||
|
|
deb4859f19 | ||
|
|
fb2af07583 | ||
|
|
151ed8245f | ||
|
|
09a3c837c3 | ||
|
|
31c1ccf962 | ||
|
|
031cc7c40d | ||
|
|
22764492d2 | ||
|
|
3d313cf837 | ||
|
|
deaf8ee4f3 | ||
|
|
0f7963beb9 | ||
|
|
e6ac874098 | ||
|
|
8ed4d4b6ed | ||
|
|
af7c24cba7 | ||
|
|
804b9ab57c | ||
|
|
26cd550bc0 | ||
|
|
0b4fda7585 | ||
|
|
42ee210ecf | ||
|
|
c073eea5b3 | ||
|
|
979b492233 | ||
|
|
646eb18806 | ||
|
|
b967b55a16 | ||
|
|
1b66dbbd8b | ||
|
|
2a3862b67a | ||
|
|
2092d921cd | ||
|
|
29c75fa1c6 | ||
|
|
0e86fe0b7b | ||
|
|
43ad31d936 | ||
|
|
093d06ab55 | ||
|
|
454d0efe0a | ||
|
|
08596fd05b | ||
|
|
5e48c6973c | ||
|
|
a3a5f3cf4b | ||
|
|
5ff3566f30 | ||
|
|
c4c12ca2c3 | ||
|
|
7f7008fecc | ||
|
|
09d54919e3 | ||
|
|
58cbbf6364 | ||
|
|
7d0f0449ae | ||
|
|
9f51fc0ef0 | ||
|
|
14fe6f1c55 | ||
|
|
4f1623fe9c | ||
|
|
adf3503d4e | ||
|
|
beb53652db | ||
|
|
92785f58da | ||
|
|
25644ac192 | ||
|
|
3bf147580f | ||
|
|
193a0cb68c | ||
|
|
58a0fb1605 | ||
|
|
b62ea00ebf | ||
|
|
349e9f473a | ||
|
|
61faa1079e | ||
|
|
08a3d951d0 | ||
|
|
8171c994df | ||
|
|
f5a0dd5946 | ||
|
|
9aa20f0fbe | ||
|
|
afa6a74178 | ||
|
|
e2e3f71ecf | ||
|
|
346e303084 | ||
|
|
d68da5bbdd | ||
|
|
e2f54d3431 | ||
|
|
f168a3f67f | ||
|
|
7fb89a7b6f | ||
|
|
42644ee26e | ||
|
|
2a9d894c90 | ||
|
|
3729b8bb5b | ||
|
|
531a9fe3ac | ||
|
|
77dd2496d0 | ||
|
|
95e2add65b | ||
|
|
b5cfc854cb | ||
|
|
5662fa777c | ||
|
|
4fa1fb966b | ||
|
|
f2f4b66d77 | ||
|
|
67c808d934 | ||
|
|
882e672bc5 | ||
|
|
1d05cf54f0 | ||
|
|
764e4499b5 | ||
|
|
2c96b70702 | ||
|
|
c475117bee | ||
|
|
d311ac718e | ||
|
|
7c71436f3b | ||
|
|
0299aa8807 | ||
|
|
f418353e44 | ||
|
|
074f0a6555 | ||
|
|
d68dec3b90 | ||
|
|
30e84faa24 | ||
|
|
fd61f8b15d | ||
|
|
db78d3a505 | ||
|
|
73499d9a09 | ||
|
|
7031829897 | ||
|
|
44c8cff78b | ||
|
|
aae5960dce | ||
|
|
691f0cb235 | ||
|
|
951be74dc0 | ||
|
|
1f79a03edf | ||
|
|
bf3fe91a5d | ||
|
|
791175daef | ||
|
|
e62a271faf | ||
|
|
583de3217c | ||
|
|
82565dad78 | ||
|
|
dde6eb3c06 | ||
|
|
a122bad685 | ||
|
|
b54e9ef4ef | ||
|
|
acb015c788 | ||
|
|
ed33d0b56e | ||
|
|
10cffc5032 | ||
|
|
9a0b3fe30c | ||
|
|
c3ecb64b72 | ||
|
|
50a1bd9db0 | ||
|
|
04e14c1f95 | ||
|
|
b19ff9d70a | ||
|
|
526f0454ab | ||
|
|
e77c8f1449 | ||
|
|
79699ba429 | ||
|
|
fa65698362 | ||
|
|
4ae1856b5c | ||
|
|
ef46c352d0 | ||
|
|
a62c42782f | ||
|
|
ba5cb30305 | ||
|
|
39b6c43ab7 | ||
|
|
b0f1501cd4 | ||
|
|
1116056eeb | ||
|
|
60933457e8 | ||
|
|
9e2d78404f | ||
|
|
bf26f5a3be | ||
|
|
91b80b1d1d | ||
|
|
4010987d1f | ||
|
|
281ff563ed | ||
|
|
ff43353de6 | ||
|
|
d6c06a2078 | ||
|
|
8436ad1341 | ||
|
|
c65512357d | ||
|
|
8e46f92703 | ||
|
|
ab0e38753b | ||
|
|
6061586289 | ||
|
|
45ba8b1a0d | ||
|
|
d01e4a6e4d | ||
|
|
938f7e12e8 | ||
|
|
24ac45741d | ||
|
|
a27c701afe | ||
|
|
a48a68ecfd | ||
|
|
db11675622 | ||
|
|
07ac24e42e | ||
|
|
63b84d7f54 | ||
|
|
b397439972 | ||
|
|
8bb455afb9 | ||
|
|
ddbc161121 | ||
|
|
1da4ef1d53 | ||
|
|
d78b64d792 | ||
|
|
e21ad0212d | ||
|
|
47d149f774 | ||
|
|
77775f25a7 | ||
|
|
688cff4ea8 | ||
|
|
a4701a6806 | ||
|
|
b875531c8a | ||
|
|
76a77aff1f | ||
|
|
25590804cb | ||
|
|
7fbfc985ab | ||
|
|
4b682666f1 | ||
|
|
abd2abb33e | ||
|
|
f5a81941ff | ||
|
|
fa819d3f11 | ||
|
|
f98469e5ef | ||
|
|
c330c7ec65 | ||
|
|
2f59c3db77 | ||
|
|
2076da7dc0 | ||
|
|
3c36b6fa0f | ||
|
|
e9be88f212 | ||
|
|
a0a6d7121f | ||
|
|
2e98493010 | ||
|
|
5fb3ecbb50 | ||
|
|
eab3aa29bf | ||
|
|
04f227e9b9 | ||
|
|
25100e7f5e | ||
|
|
ccc2b61719 | ||
|
|
8c7b302916 | ||
|
|
abcc3e884c | ||
|
|
15799b2dd5 | ||
|
|
35af8a48ad |
9
.ansible-lint
Normal file
9
.ansible-lint
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
profile: production
|
||||||
|
|
||||||
|
exclude_paths:
|
||||||
|
- .ansible/
|
||||||
|
- .github/
|
||||||
|
- tests/integration
|
||||||
|
- tests/unit
|
||||||
|
- tests/sanity
|
||||||
6
.ansible-lint-ignore
Normal file
6
.ansible-lint-ignore
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# https://docs.ansible.com/ansible-lint/docs/rules/
|
||||||
|
# no-changed-when is not requried for examples
|
||||||
|
plugins/connection/kubectl.py no-changed-when
|
||||||
|
# false positive result
|
||||||
|
plugins/connection/kubectl.py var-naming[no-reserved]
|
||||||
|
plugins/connection/kubectl.py jinja[invalid]
|
||||||
4
.github/patchback.yml
vendored
Normal file
4
.github/patchback.yml
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
backport_branch_prefix: patchback/backports/
|
||||||
|
backport_label_prefix: backport-
|
||||||
|
target_branch_prefix: stable-
|
||||||
60
.github/stale.yml
vendored
60
.github/stale.yml
vendored
@@ -1,60 +0,0 @@
|
|||||||
---
|
|
||||||
# Configuration for probot-stale - https://github.com/probot/stale
|
|
||||||
|
|
||||||
# Number of days of inactivity before an Issue or Pull Request becomes stale
|
|
||||||
daysUntilStale: 90
|
|
||||||
|
|
||||||
# Number of days of inactivity before an Issue or Pull Request with the stale
|
|
||||||
# label is closed. Set to false to disable. If disabled, issues still need to be
|
|
||||||
# closed manually, but will remain marked as stale.
|
|
||||||
daysUntilClose: 30
|
|
||||||
|
|
||||||
# Only issues or pull requests with all of these labels are check if stale.
|
|
||||||
# Defaults to `[]` (disabled)
|
|
||||||
onlyLabels: []
|
|
||||||
|
|
||||||
# Issues or Pull Requests with these labels will never be considered stale. Set
|
|
||||||
# to `[]` to disable
|
|
||||||
exemptLabels:
|
|
||||||
- security
|
|
||||||
- planned
|
|
||||||
- priority/critical
|
|
||||||
- lifecycle/frozen
|
|
||||||
- verified
|
|
||||||
|
|
||||||
# Set to true to ignore issues in a project (defaults to false)
|
|
||||||
exemptProjects: false
|
|
||||||
|
|
||||||
# Set to true to ignore issues in a milestone (defaults to false)
|
|
||||||
exemptMilestones: true
|
|
||||||
|
|
||||||
# Set to true to ignore issues with an assignee (defaults to false)
|
|
||||||
exemptAssignees: false
|
|
||||||
|
|
||||||
# Label to use when marking as stale
|
|
||||||
staleLabel: lifecycle/stale
|
|
||||||
|
|
||||||
# Limit the number of actions per hour, from 1-30. Default is 30
|
|
||||||
limitPerRun: 30
|
|
||||||
|
|
||||||
pulls:
|
|
||||||
markComment: |-
|
|
||||||
PRs go stale after 90 days of inactivity.
|
|
||||||
If there is no further activity, the PR will be closed in another 30 days.
|
|
||||||
|
|
||||||
unmarkComment: >-
|
|
||||||
This pull request is no longer stale.
|
|
||||||
|
|
||||||
closeComment: >-
|
|
||||||
This pull request has been closed due to inactivity.
|
|
||||||
|
|
||||||
issues:
|
|
||||||
markComment: |-
|
|
||||||
Issues go stale after 90 days of inactivity.
|
|
||||||
If there is no further activity, the issue will be closed in another 30 days.
|
|
||||||
|
|
||||||
unmarkComment: >-
|
|
||||||
This issue is no longer stale.
|
|
||||||
|
|
||||||
closeComment: >-
|
|
||||||
This issue has been closed due to inactivity.
|
|
||||||
21
.github/workflows/changelog.yaml
vendored
Normal file
21
.github/workflows/changelog.yaml
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
name: Changelog
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- reopened
|
||||||
|
- labeled
|
||||||
|
- unlabeled
|
||||||
|
- synchronize
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- stable-*
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
changelog:
|
||||||
|
uses: ansible-network/github_actions/.github/workflows/changelog.yml@main
|
||||||
141
.github/workflows/ci.yml
vendored
141
.github/workflows/ci.yml
vendored
@@ -1,141 +0,0 @@
|
|||||||
---
|
|
||||||
name: CI
|
|
||||||
'on':
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
pull_request:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 6 * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
|
|
||||||
sanity:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
python_version: ['3.7']
|
|
||||||
ansible_version: ['stable-2.11', 'stable-2.10', 'stable-2.9', 'devel']
|
|
||||||
steps:
|
|
||||||
- name: Check out code
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
path: ansible_collections/kubernetes/core
|
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python_version }}
|
|
||||||
uses: actions/setup-python@v1
|
|
||||||
with:
|
|
||||||
python-version: ${{ matrix.python_version }}
|
|
||||||
|
|
||||||
- name: Check ansible version
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
repository: ansible/ansible
|
|
||||||
ref: ${{ matrix.ansible_version }}
|
|
||||||
path: ansible_collections/kubernetes/core/ansible
|
|
||||||
|
|
||||||
- name: Run sanity tests on Python ${{ matrix.python_version }}
|
|
||||||
run: source ./ansible/hacking/env-setup && make test-sanity PYTHON_VERSION=${{ matrix.python_version }}
|
|
||||||
working-directory: ./ansible_collections/kubernetes/core
|
|
||||||
|
|
||||||
integration:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
# Our old integration tests fail under newer Python versions.
|
|
||||||
python_version: ['3.6']
|
|
||||||
steps:
|
|
||||||
- name: Check out code
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
path: ansible_collections/kubernetes/core
|
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python_version }}
|
|
||||||
uses: actions/setup-python@v1
|
|
||||||
with:
|
|
||||||
python-version: ${{ matrix.python_version }}
|
|
||||||
|
|
||||||
- name: Install ansible base (devel branch)
|
|
||||||
run: pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check
|
|
||||||
|
|
||||||
- name: Run integration tests on Python ${{ matrix.python_version }}
|
|
||||||
run: make test-integration PYTHON_VERSION=${{ matrix.python_version }}
|
|
||||||
working-directory: ./ansible_collections/kubernetes/core
|
|
||||||
|
|
||||||
- name: Generate coverage report.
|
|
||||||
run: ansible-test coverage xml -v --requirements --group-by command --group-by version
|
|
||||||
working-directory: ./ansible_collections/kubernetes/core
|
|
||||||
|
|
||||||
- uses: codecov/codecov-action@v1
|
|
||||||
with:
|
|
||||||
fail_ci_if_error: false
|
|
||||||
|
|
||||||
molecule:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
python_version: ['3.7']
|
|
||||||
ansible_version: ['==2.9.*', '==2.10.*', '']
|
|
||||||
steps:
|
|
||||||
- name: Check out code
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
path: ansible_collections/kubernetes/core
|
|
||||||
|
|
||||||
- name: Set up KinD cluster
|
|
||||||
uses: engineerd/setup-kind@v0.5.0
|
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python_version }}
|
|
||||||
uses: actions/setup-python@v1
|
|
||||||
with:
|
|
||||||
python-version: ${{ matrix.python_version }}
|
|
||||||
|
|
||||||
# The 3.3.0 release of molecule introduced a breaking change. See
|
|
||||||
# https://github.com/ansible-community/molecule/issues/3083
|
|
||||||
- name: Install molecule and kubernetes dependencies
|
|
||||||
run: pip install ansible${{ matrix.ansible_version }} "molecule<3.3.0" yamllint kubernetes flake8 jsonpatch
|
|
||||||
|
|
||||||
# The latest release doesn't work with Molecule currently.
|
|
||||||
# See: https://github.com/ansible-community/molecule/issues/2757
|
|
||||||
# - name: Install ansible base, latest release.
|
|
||||||
# run: |
|
|
||||||
# pip uninstall -y ansible
|
|
||||||
# pip install --pre ansible-base
|
|
||||||
|
|
||||||
# The devel branch doesn't work with Molecule currently.
|
|
||||||
# See: https://github.com/ansible-community/molecule/issues/2757
|
|
||||||
# - name: Install ansible base (devel branch)
|
|
||||||
# run: |
|
|
||||||
# pip uninstall -y ansible
|
|
||||||
# pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check
|
|
||||||
- name: Create default collection path symlink
|
|
||||||
run: |
|
|
||||||
mkdir -p /home/runner/.ansible
|
|
||||||
ln -s /home/runner/work/kubernetes/kubernetes /home/runner/.ansible/collections
|
|
||||||
|
|
||||||
- name: Run molecule default test scenario
|
|
||||||
run: make test-molecule
|
|
||||||
working-directory: ./ansible_collections/kubernetes/core
|
|
||||||
|
|
||||||
unit:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
python_version: ['3.7']
|
|
||||||
steps:
|
|
||||||
- name: Check out code
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
path: ansible_collections/kubernetes/core
|
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python_version }}
|
|
||||||
uses: actions/setup-python@v1
|
|
||||||
with:
|
|
||||||
python-version: ${{ matrix.python_version }}
|
|
||||||
|
|
||||||
- name: Install ansible base (devel branch)
|
|
||||||
run: pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check
|
|
||||||
|
|
||||||
- name: Run unit tests on Python ${{ matrix.python_version }}
|
|
||||||
run: make test-unit PYTHON_VERSION=${{ matrix.python_version }}
|
|
||||||
working-directory: ./ansible_collections/kubernetes/core
|
|
||||||
14
.github/workflows/galaxy-import.yaml
vendored
Normal file
14
.github/workflows/galaxy-import.yaml
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
name: galaxy-import
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.head_ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- stable-*
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
galaxy_importer:
|
||||||
|
uses: ansible-network/github_actions/.github/workflows/galaxy_importer.yml@main
|
||||||
161
.github/workflows/integration-tests.yaml
vendored
Normal file
161
.github/workflows/integration-tests.yaml
vendored
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
name: Integration tests
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- reopened
|
||||||
|
- labeled
|
||||||
|
- unlabeled
|
||||||
|
- synchronize
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- stable-*
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
splitter:
|
||||||
|
env:
|
||||||
|
source_dir: "./source"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
test_targets: ${{ steps.splitter.outputs.test_targets }}
|
||||||
|
test_targets_json: ${{ steps.splitter.outputs.test_targets_json }}
|
||||||
|
test_jobs: ${{ steps.splitter.outputs.test_jobs }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout the collection repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
path: ${{ env.source_dir }}
|
||||||
|
fetch-depth: "0"
|
||||||
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
|
||||||
|
- name: list changes for pull request
|
||||||
|
id: splitter
|
||||||
|
uses: ansible-network/github_actions/.github/actions/ansible_test_splitter@main
|
||||||
|
with:
|
||||||
|
collections_to_test: ${{ env.source_dir }}
|
||||||
|
total_jobs: 8
|
||||||
|
|
||||||
|
- name: Display splitter output
|
||||||
|
run: |
|
||||||
|
echo "test_targets=${{ steps.splitter.outputs.test_targets }}"
|
||||||
|
echo "test_targets_json=${{ steps.splitter.outputs.test_targets_json }}"
|
||||||
|
echo "test_jobs=${{ steps.splitter.outputs.test_jobs }}"
|
||||||
|
shell: bash
|
||||||
|
integration:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 60
|
||||||
|
needs:
|
||||||
|
- splitter
|
||||||
|
if: ${{ needs.splitter.outputs.test_targets != '' }}
|
||||||
|
env:
|
||||||
|
source: "./source"
|
||||||
|
cloud_common: "./cloudcommon"
|
||||||
|
ansible_posix: "./ansible_posix"
|
||||||
|
community_general: "./community_general"
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ansible-version:
|
||||||
|
- milestone
|
||||||
|
python-version:
|
||||||
|
- "3.12"
|
||||||
|
enable-turbo-mode:
|
||||||
|
- true
|
||||||
|
- false
|
||||||
|
workflow-id: ${{ fromJson(needs.splitter.outputs.test_jobs) }}
|
||||||
|
name: "integration-py${{ matrix.python-version }}-${{ matrix.ansible-version }}-${{ matrix.workflow-id }}-enable_turbo=${{ matrix.enable-turbo-mode }}"
|
||||||
|
steps:
|
||||||
|
- name: Read target
|
||||||
|
id: read-targets
|
||||||
|
run: |
|
||||||
|
import json, os
|
||||||
|
with open(os.environ.get('GITHUB_OUTPUT'), "a", encoding="utf-8") as fh:
|
||||||
|
fh.write(f'ansible_test_targets={json.loads(os.environ.get("ALL_TEST_TARGETS")).get(os.environ.get("WORKFLOW_ID"))}\n')
|
||||||
|
shell: python
|
||||||
|
env:
|
||||||
|
ALL_TEST_TARGETS: ${{ needs.splitter.outputs.test_targets_json }}
|
||||||
|
WORKFLOW_ID: ${{ matrix.workflow-id }}
|
||||||
|
|
||||||
|
- name: Display ansible test targets
|
||||||
|
run: |
|
||||||
|
echo "ansible_test_targets -> ${{ steps.read-targets.outputs.ansible_test_targets }}"
|
||||||
|
|
||||||
|
- name: Checkout kubernetes.core repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
path: ${{ env.source }}
|
||||||
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
|
||||||
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python-version }}
|
||||||
|
|
||||||
|
# install ansible
|
||||||
|
- name: Install ansible-core (${{ matrix.ansible-version }})
|
||||||
|
run: >-
|
||||||
|
python3 -m pip install
|
||||||
|
https://github.com/ansible/ansible/archive/${{ matrix.ansible-version }}.tar.gz
|
||||||
|
--disable-pip-version-check
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Build and install collection
|
||||||
|
id: install-src
|
||||||
|
uses: ansible-network/github_actions/.github/actions/build_install_collection@main
|
||||||
|
with:
|
||||||
|
install_python_dependencies: true
|
||||||
|
source_path: ${{ env.source }}
|
||||||
|
|
||||||
|
- name: checkout ansible-collections/cloud.common
|
||||||
|
uses: ansible-network/github_actions/.github/actions/checkout_dependency@main
|
||||||
|
with:
|
||||||
|
repository: ansible-collections/cloud.common
|
||||||
|
path: ${{ env.cloud_common }}
|
||||||
|
ref: main
|
||||||
|
|
||||||
|
- name: checkout ansible-collections/ansible.posix
|
||||||
|
uses: ansible-network/github_actions/.github/actions/checkout_dependency@main
|
||||||
|
with:
|
||||||
|
repository: ansible-collections/ansible.posix
|
||||||
|
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:
|
||||||
|
install_python_dependencies: true
|
||||||
|
source_path: ${{ env.cloud_common }}
|
||||||
|
|
||||||
|
- name: install ansible.posix collection
|
||||||
|
uses: ansible-network/github_actions/.github/actions/build_install_collection@main
|
||||||
|
with:
|
||||||
|
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:
|
||||||
|
node_image: "kindest/node:v1.29.2"
|
||||||
|
|
||||||
|
- name: Run integration tests
|
||||||
|
uses: ansible-network/github_actions/.github/actions/ansible_test_integration@main
|
||||||
|
with:
|
||||||
|
collection_path: ${{ steps.install-src.outputs.collection_path }}
|
||||||
|
python_version: ${{ matrix.python-version }}
|
||||||
|
ansible_version: ${{ matrix.ansible-version }}
|
||||||
|
ansible_test_targets: ${{ steps.read-targets.outputs.ansible_test_targets }}
|
||||||
|
ansible_test_environment: |
|
||||||
|
ENABLE_TURBO_MODE=${{ matrix.enable-turbo-mode }}
|
||||||
25
.github/workflows/linters.yaml
vendored
Normal file
25
.github/workflows/linters.yaml
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
name: Linters
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- stable-*
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
linters:
|
||||||
|
uses: ansible-network/github_actions/.github/workflows/tox-linters.yml@main
|
||||||
|
ansible-lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: run-ansible-lint
|
||||||
|
uses: ansible/ansible-lint@main
|
||||||
|
with:
|
||||||
|
gh_action_ref: "v25.5.0"
|
||||||
15
.github/workflows/sanity-tests.yaml
vendored
Normal file
15
.github/workflows/sanity-tests.yaml
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
name: Sanity tests
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- stable-*
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
sanity:
|
||||||
|
uses: ansible-network/github_actions/.github/workflows/sanity.yml@main
|
||||||
14
.github/workflows/unit-tests.yaml
vendored
Normal file
14
.github/workflows/unit-tests.yaml
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
name: Unit tests
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- stable-*
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
unit-source:
|
||||||
|
uses: ansible-network/github_actions/.github/workflows/unit_source.yml@main
|
||||||
11
.gitignore
vendored
11
.gitignore
vendored
@@ -13,3 +13,14 @@ changelogs/.plugin-cache.yaml
|
|||||||
tests/output
|
tests/output
|
||||||
tests/integration/cloud-config-*
|
tests/integration/cloud-config-*
|
||||||
.cache
|
.cache
|
||||||
|
.ansible
|
||||||
|
|
||||||
|
# Helm charts
|
||||||
|
tests/integration/*-chart-*.tgz
|
||||||
|
|
||||||
|
# ansible-test generated file
|
||||||
|
tests/integration/inventory
|
||||||
|
tests/integration/*-*.yml
|
||||||
|
|
||||||
|
# VS Code settings
|
||||||
|
.vscode/
|
||||||
|
|||||||
11
.yamllint
11
.yamllint
@@ -5,14 +5,25 @@ rules:
|
|||||||
braces:
|
braces:
|
||||||
max-spaces-inside: 1
|
max-spaces-inside: 1
|
||||||
level: error
|
level: error
|
||||||
|
|
||||||
brackets:
|
brackets:
|
||||||
max-spaces-inside: 1
|
max-spaces-inside: 1
|
||||||
level: error
|
level: error
|
||||||
|
comments:
|
||||||
|
min-spaces-from-content: 1
|
||||||
|
comments-indentation: false
|
||||||
document-start: disable
|
document-start: disable
|
||||||
line-length: disable
|
line-length: disable
|
||||||
truthy: disable
|
truthy: disable
|
||||||
indentation:
|
indentation:
|
||||||
spaces: 2
|
spaces: 2
|
||||||
indent-sequences: consistent
|
indent-sequences: consistent
|
||||||
|
octal-values:
|
||||||
|
forbid-implicit-octal: true
|
||||||
|
forbid-explicit-octal: true
|
||||||
ignore: |
|
ignore: |
|
||||||
.cache
|
.cache
|
||||||
|
.tox
|
||||||
|
.ansible
|
||||||
|
tests/output
|
||||||
|
plugins/connection/kubectl.py
|
||||||
|
|||||||
513
CHANGELOG.rst
513
CHANGELOG.rst
@@ -4,6 +4,519 @@ Kubernetes Collection Release Notes
|
|||||||
|
|
||||||
.. contents:: Topics
|
.. contents:: Topics
|
||||||
|
|
||||||
|
v6.2.0
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This release adds minor changes and bugfixes, including support of skip-schema-validation in ``helm`` module and removing deprecated ``ansible.module_utils.six`` imports.
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- Add support of skip-schema-validation in ``helm`` module (https://github.com/ansible-collections/kubernetes.core/pull/995)
|
||||||
|
- kustomize - Add support of local environ (https://github.com/ansible-collections/kubernetes.core/pull/786).
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- Remove ``ansible.module_utils.six`` imports to avoid warnings (https://github.com/ansible-collections/kubernetes.core/pull/998).
|
||||||
|
- Update the ``k8s_cp`` module to also work for init containers (https://github.com/ansible-collections/kubernetes.core/pull/971).
|
||||||
|
|
||||||
|
v6.1.0
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This release adds ``plain_http`` and ``take_ownership`` parameters for helm modules, support for ``hidden_fields`` in ``k8s_json_patch``, documented lack of idempotency support in ``helm_registry_auth`` with ``helm ≥ 3.18.0``, and improved ``k8s_rollback`` test coverage.
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- Module helm_registry_auth do not support idempotency with `helm >= 3.18.0` (https://github.com/ansible-collections/kubernetes.core/pull/946)
|
||||||
|
- Module k8s_json_patch - Add support for `hidden_fields` (https://github.com/ansible-collections/kubernetes.core/pull/964).
|
||||||
|
- helm - Parameter plain_http added for working with insecure OCI registries (https://github.com/ansible-collections/kubernetes.core/pull/934).
|
||||||
|
- helm - Parameter take_ownership added (https://github.com/ansible-collections/kubernetes.core/pull/957).
|
||||||
|
- helm_pull - Parameter plain_http added for working with insecure OCI registries (https://github.com/ansible-collections/kubernetes.core/pull/934).
|
||||||
|
- helm_template - Parameter plain_http added for working with insecure OCI registries (https://github.com/ansible-collections/kubernetes.core/pull/934).
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- module_utils/k8s/service - hide fields first before creating diffs (https://github.com/ansible-collections/kubernetes.core/pull/915).
|
||||||
|
|
||||||
|
v6.0.0
|
||||||
|
======
|
||||||
|
|
||||||
|
Breaking Changes / Porting Guide
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
- Remove deprecated ``k8s`` invetory plugin (https://github.com/ansible-collections/kubernetes.core/pull/867).
|
||||||
|
- Remove support for ``ansible-core<2.16`` (https://github.com/ansible-collections/kubernetes.core/pull/867).
|
||||||
|
|
||||||
|
v5.4.1
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This release includes bugfixes for k8s service field handling, k8s_cp init containers support, and removes deprecated ansible.module_utils.six imports.
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- Remove ``ansible.module_utils.six`` imports to avoid warnings (https://github.com/ansible-collections/kubernetes.core/pull/998).
|
||||||
|
- Update the `k8s_cp` module to also work for init containers (https://github.com/ansible-collections/kubernetes.core/pull/971).
|
||||||
|
- module_utils/k8s/service - hide fields first before creating diffs (https://github.com/ansible-collections/kubernetes.core/pull/915).
|
||||||
|
|
||||||
|
v5.4.0
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This release updates the ``helm_registry_auth`` module to match the behavior of ``helm >= 3.18.0`` which reports a successful logout regardless of the current state (i.e., no idempotency).
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- Module ``helm_registry_auth`` does not support idempotency with ``helm >= 3.18.0`` (https://github.com/ansible-collections/kubernetes.core/pull/946)
|
||||||
|
|
||||||
|
v5.3.0
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This release includes minor changes, bug fixes and also bumps ``ansible-lint`` version to ``25.1.2``.
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- Bump version of ``ansible-lint`` to 25.1.2 (https://github.com/ansible-collections/kubernetes.core/pull/919).
|
||||||
|
- action/k8s_info - update templating mechanism with changes from ``ansible-core 2.19`` (https://github.com/ansible-collections/kubernetes.core/pull/888).
|
||||||
|
- helm - add ``reset_then_reuse_values`` support to helm module (https://github.com/ansible-collections/kubernetes.core/issues/803).
|
||||||
|
- helm - add support for ``insecure_skip_tls_verify`` option to helm and helm_repository(https://github.com/ansible-collections/kubernetes.core/issues/694).
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- module_utils/k8s/service - fix issue when trying to delete resource using ``delete_options`` and ``check_mode=true`` (https://github.com/ansible-collections/kubernetes.core/issues/892).
|
||||||
|
|
||||||
|
v5.2.0
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This release adds more functionality to the hidden_fields option and support for waiting on ClusterOperators to reach a ready state.
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- k8s - Extend hidden_fields to allow the expression of more complex field types to be hidden (https://github.com/ansible-collections/kubernetes.core/pull/872)
|
||||||
|
- k8s_info - Extend hidden_fields to allow the expression of more complex field types to be hidden (https://github.com/ansible-collections/kubernetes.core/pull/872)
|
||||||
|
- waiter.py - add ClusterOperator support. The module can now check OpenShift cluster health by verifying ClusterOperator status requiring 'Available: True', 'Degraded: False', and 'Progressing: False' for success. (https://github.com/ansible-collections/kubernetes.core/issues/869)
|
||||||
|
|
||||||
|
v5.1.0
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This release came with new module ``helm_registry_auth``, improvements to the error messages in the k8s_drain module, new parameter ``insecure_registry`` for ``helm_template`` module and several bug fixes.
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- Bump version of ``ansible-lint`` to minimum 24.7.0 (https://github.com/ansible-collections/kubernetes.core/pull/765).
|
||||||
|
- Parameter insecure_registry added to helm_template as equivalent of insecure-skip-tls-verify (https://github.com/ansible-collections/kubernetes.core/pull/805).
|
||||||
|
- k8s_drain - Improve error message for pod disruption budget when draining a node (https://github.com/ansible-collections/kubernetes.core/issues/797).
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- helm - Helm version checks did not support RC versions. They now accept any version tags. (https://github.com/ansible-collections/kubernetes.core/pull/745).
|
||||||
|
- helm_pull - Apply no_log=True to pass_credentials to silence false positive warning. (https://github.com/ansible-collections/kubernetes.core/pull/796).
|
||||||
|
- k8s_drain - Fix k8s_drain does not wait for single pod (https://github.com/ansible-collections/kubernetes.core/issues/769).
|
||||||
|
- k8s_drain - Fix k8s_drain runs into a timeout when evicting a pod which is part of a stateful set (https://github.com/ansible-collections/kubernetes.core/issues/792).
|
||||||
|
- kubeconfig option should not appear in module invocation log (https://github.com/ansible-collections/kubernetes.core/issues/782).
|
||||||
|
- kustomize - kustomize plugin fails with deprecation warnings (https://github.com/ansible-collections/kubernetes.core/issues/639).
|
||||||
|
- waiter - Fix waiting for daemonset when desired number of pods is 0. (https://github.com/ansible-collections/kubernetes.core/pull/756).
|
||||||
|
|
||||||
|
New Modules
|
||||||
|
-----------
|
||||||
|
|
||||||
|
- helm_registry_auth - Helm registry authentication module
|
||||||
|
|
||||||
|
v5.0.0
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This major release drops support for ``ansible-core<2.15``.
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- connection/kubectl.py - Added an example of using the kubectl connection plugin to the documentation (https://github.com/ansible-collections/kubernetes.core/pull/741).
|
||||||
|
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 6.0.0 (https://github.com/ansible-collections/kubernetes.core/pull/734).
|
||||||
|
|
||||||
|
Breaking Changes / Porting Guide
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
- Remove support for ``ansible-core<2.15`` (https://github.com/ansible-collections/kubernetes.core/pull/737).
|
||||||
|
|
||||||
|
v4.0.0
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This major release brings several bug fixes. We have also removed support for ``ansible-core<2.15`` and deprecated functions and class from ``module_utils/common.py``.
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 5.0 (https://github.com/ansible-collections/kubernetes.core/pull/723).
|
||||||
|
- k8s - The module and K8sService were changed so warnings returned by the K8S API are now displayed to the user.
|
||||||
|
|
||||||
|
Removed Features (previously deprecated)
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
- k8s - Support for ``merge_type=json`` has been removed in version 4.0.0. Please use ``kubernetes.core.k8s_json_patch`` instead (https://github.com/ansible-collections/kubernetes.core/pull/722).
|
||||||
|
- k8s_exec - the previously deprecated ``result.return_code`` return value has been removed, consider using ``result.rc`` instead (https://github.com/ansible-collections/kubernetes.core/pull/726).
|
||||||
|
- module_utils/common.py - the previously deprecated ``K8sAnsibleMixin`` class has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
|
||||||
|
- module_utils/common.py - the previously deprecated ``configuration_digest()`` function has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
|
||||||
|
- module_utils/common.py - the previously deprecated ``get_api_client()`` function has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
|
||||||
|
- module_utils/common.py - the previously deprecated ``unique_string()`` function has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- Resolve Collections util resource discovery fails when complex subresources present (https://github.com/ansible-collections/kubernetes.core/pull/676).
|
||||||
|
- align `helmdiff_check()` function commandline rendering with the `deploy()` function (https://github.com/ansible-collections/kubernetes.core/pull/670).
|
||||||
|
- avoid unsafe conditions in integration tests (https://github.com/ansible-collections/kubernetes.core/pull/665).
|
||||||
|
- helm - use ``reuse-values`` when running ``helm diff`` command (https://github.com/ansible-collections/kubernetes.core/issues/680).
|
||||||
|
- integrations test helm_kubeconfig - set helm version to v3.10.3 to avoid incompatability with new bitnami charts (https://github.com/ansible-collections/kubernetes.core/pull/670).
|
||||||
|
|
||||||
|
v3.3.1
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This release fixes the CI issues with the ``linters`` workflow.
|
||||||
|
|
||||||
|
v3.3.0
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This release comes with improvements to the error messages in the k8s_drain module and several bug fixes.
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- k8s_drain - Improve error message for pod disruption budget when draining a node (https://github.com/ansible-collections/kubernetes.core/issues/797).
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- helm - Helm version checks did not support RC versions. They now accept any version tags. (https://github.com/ansible-collections/kubernetes.core/pull/745).
|
||||||
|
- helm_pull - Apply no_log=True to pass_credentials to silence false positive warning. (https://github.com/ansible-collections/kubernetes.core/pull/796).
|
||||||
|
- k8s_drain - Fix k8s_drain does not wait for single pod (https://github.com/ansible-collections/kubernetes.core/issues/769).
|
||||||
|
- k8s_drain - Fix k8s_drain runs into a timeout when evicting a pod which is part of a stateful set (https://github.com/ansible-collections/kubernetes.core/issues/792).
|
||||||
|
- kubeconfig option should not appear in module invocation log (https://github.com/ansible-collections/kubernetes.core/issues/782).
|
||||||
|
- kustomize - kustomize plugin fails with deprecation warnings (https://github.com/ansible-collections/kubernetes.core/issues/639).
|
||||||
|
- waiter - Fix waiting for daemonset when desired number of pods is 0. (https://github.com/ansible-collections/kubernetes.core/pull/756).
|
||||||
|
|
||||||
|
v3.2.0
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This release comes with documentation updates.
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- connection/kubectl.py - Added an example of using the kubectl connection plugin to the documentation (https://github.com/ansible-collections/kubernetes.core/pull/741).
|
||||||
|
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 5.0 (https://github.com/ansible-collections/kubernetes.core/pull/723).
|
||||||
|
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 6.0.0 (https://github.com/ansible-collections/kubernetes.core/pull/734).
|
||||||
|
|
||||||
|
v3.1.0
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This release comes with some bugfixes and documentation updates. It also adds new features to the kubectl connection plugin and the kustomize lookup plugin.
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- kubectl - added support of local enviroment variable that will be used for kubectl and may be requried for establishing connections ifself (https://github.com/ansible-collections/kubernetes.core/pull/702)
|
||||||
|
- kustomize - new parameter added to --enable-helm (https://github.com/ansible-collections/kubernetes.core/issues/568)
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- helm - expand kubeconfig path with user's home directory for consistency with k8s
|
||||||
|
- k8s_json_patch - rename action symlink to ensure k8s action plugin is used (https://github.com/ansible-collections/kubernetes.core/pull/652).
|
||||||
|
|
||||||
|
v3.0.1
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This release fixes issue with resources discovery when complex subresources are present, and fixes issues with `reuse-values` parameter for helm module.
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- Resolve Collections util resource discovery fails when complex subresources present (https://github.com/ansible-collections/kubernetes.core/pull/676).
|
||||||
|
- align `helmdiff_check()` function commandline rendering with the `deploy()` function (https://github.com/ansible-collections/kubernetes.core/pull/670).
|
||||||
|
- 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.0.0
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This major release drops support for ansible-core versions lower than 2.14, Python versions lower than 3.9 and updates python kubernetes library to 24.2.0, helm/kind-action to 1.8.0, kubernetes >= 1.24, along with bug fixes and minor changes.
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- helm - add ``reuse_values`` and ``reset_values`` support to helm module (https://github.com/ansible-collections/kubernetes.core/issues/394).
|
||||||
|
- k8s - add new option ``delete_all`` to support deletion of all resources when state is set to ``absent``. (https://github.com/ansible-collections/kubernetes.core/issues/504)
|
||||||
|
- k8s, k8s_info - add a hidden_fields option to allow fields to be hidden in the results of k8s and k8s_info
|
||||||
|
- k8s_drain - add ability to filter the list of pods to be drained by a pod label selector (https://github.com/ansible-collections/kubernetes.core/issues/474).
|
||||||
|
|
||||||
|
Breaking Changes / Porting Guide
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
- Remove support for ansible-core < 2.14
|
||||||
|
- Update python kubernetes library to 24.2.0, helm/kind-action to 1.8.0, kubernetes >= 1.24.
|
||||||
|
|
||||||
|
Deprecated Features
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
- k8s - the ``k8s`` inventory plugin has been deprecated and will be removed in release 4.0.0 (https://github.com/ansible-collections/kubernetes.core/issues/31).
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- helm - Put the chart_ref into quotes when running ``helm show chart``, ``helm upgrade`` and ``helm dependency update`` commands (https://github.com/ansible-collections/kubernetes.core/issues/653).
|
||||||
|
- helm - delete temporary file created when deploying chart with option ``release_values`` set (https://github.com/ansible-collections/kubernetes.core/issues/530).
|
||||||
|
- helm - fix issue occurring when uninstalling chart with statues others than ``deployed`` (https://github.com/ansible-collections/kubernetes.core/issues/319).
|
||||||
|
- helm - fix post_renderer argument breaking the helm deploy_command (https://github.com/ansible-collections/kubernetes.core/pull/586).
|
||||||
|
- helm - use post_renderer when checking ``changed`` status for a helm release (https://github.com/ansible-collections/kubernetes.core/pull/588).
|
||||||
|
- k8s_scale - clean handling of ResourceTimeout exception (https://github.com/ansible-collections/kubernetes.core/issues/583).
|
||||||
|
- k8s_scale - fix issue when scaling StatefulSets with ``updateStrategy=OnDelete`` (https://github.com/ansible-collections/kubernetes.core/issues/579).
|
||||||
|
|
||||||
|
v2.4.0
|
||||||
|
======
|
||||||
|
|
||||||
|
Major Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- refactor K8sAnsibleMixin into module_utils/k8s/ (https://github.com/ansible-collections/kubernetes.core/pull/481).
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- Adjust k8s_user_impersonation tests to be compatible with Kubernetes 1.24 (https://github.com/ansible-collections/kubernetes.core/pull/520).
|
||||||
|
- add support for dry run with kubernetes client version >=18.20 (https://github.com/ansible-collections/kubernetes.core/pull/245).
|
||||||
|
- added ignore.txt for Ansible 2.14 devel branch.
|
||||||
|
- fixed module_defaults by removing routing hacks from runtime.yml (https://github.com/ansible-collections/kubernetes.core/pull/347).
|
||||||
|
- helm - add support for -set-file, -set-json, -set and -set-string options when running helm install (https://github.com/ansible-collections/kubernetes.core/issues/533).
|
||||||
|
- helm - add support for helm dependency update (https://github.com/ansible-collections/kubernetes.core/pull/208).
|
||||||
|
- helm - add support for post-renderer flag (https://github.com/ansible-collections/kubernetes.core/issues/30).
|
||||||
|
- helm - add support for timeout cli parameter to allow setting Helm timeout independent of wait (https://github.com/ansible-collections/kubernetes.core/issues/67).
|
||||||
|
- helm - add support for wait parameter for helm uninstall command. (https://github.com/ansible-collections/kubernetes/core/issues/33).
|
||||||
|
- helm - support repo location for helm diff (https://github.com/ansible-collections/kubernetes.core/issues/174).
|
||||||
|
- helm - when ansible is executed in check mode, return the diff between what's deployed and what will be deployed.
|
||||||
|
- helm, helm_plugin, helm_info, helm_plugin_info, kubectl - add support for in-memory kubeconfig. (https://github.com/ansible-collections/kubernetes.core/issues/492).
|
||||||
|
- helm_info - add hooks, notes and manifest as part of returned information (https://github.com/ansible-collections/kubernetes.core/pull/546).
|
||||||
|
- helm_info - add release state as a module argument (https://github.com/ansible-collections/kubernetes.core/issues/377).
|
||||||
|
- helm_info - added possibility to get all values by adding get_all_values parameter (https://github.com/ansible-collections/kubernetes.core/pull/531).
|
||||||
|
- helm_plugin - Add plugin_version parameter to the helm_plugin module (https://github.com/ansible-collections/kubernetes.core/issues/157).
|
||||||
|
- helm_plugin - Add support for helm plugin update using state=update.
|
||||||
|
- helm_repository - Ability to replace (overwrite) the repo if it already exists by forcing (https://github.com/ansible-collections/kubernetes.core/issues/491).
|
||||||
|
- helm_repository - add support for pass-credentials cli parameter (https://github.com/ansible-collections/kubernetes.core/pull/282).
|
||||||
|
- helm_repository - added support for ``host``, ``api_key``, ``validate_certs``, and ``ca_cert``.
|
||||||
|
- helm_repository - mark `pass_credentials` as no_log=True to silence false warning (https://github.com/ansible-collections/kubernetes.core/issues/412).
|
||||||
|
- helm_template - add name (NAME of release) and disable_hook as optional module arguments (https://github.com/ansible-collections/kubernetes.core/issues/313).
|
||||||
|
- helm_template - add show_only and release_namespace as module arguments (https://github.com/ansible-collections/kubernetes.core/issues/313).
|
||||||
|
- helm_template - add support for -set-file, -set-json, -set and -set-string options when running helm template (https://github.com/ansible-collections/kubernetes.core/pull/546).
|
||||||
|
- k8s - add no_proxy support to k8s* (https://github.com/ansible-collections/kubernetes.core/pull/272).
|
||||||
|
- k8s - add support for server_side_apply. (https://github.com/ansible-collections/kubernetes.core/issues/87).
|
||||||
|
- k8s - add support for user impersonation. (https://github.com/ansible-collections/kubernetes/core/issues/40).
|
||||||
|
- k8s - allow resource definition using metadata.generateName (https://github.com/ansible-collections/kubernetes.core/issues/35).
|
||||||
|
- k8s lookup plugin - Enable turbo mode via environment variable (https://github.com/ansible-collections/kubernetes.core/issues/291).
|
||||||
|
- k8s, k8s_scale, k8s_service - add support for resource definition as manifest via. (https://github.com/ansible-collections/kubernetes.core/issues/451).
|
||||||
|
- k8s_cp - remove dependency with 'find' executable on remote pod when state=from_pod (https://github.com/ansible-collections/kubernetes.core/issues/486).
|
||||||
|
- k8s_drain - Adds ``delete_emptydir_data`` option to ``k8s_drain.delete_options`` to evict pods with an ``emptyDir`` volume attached (https://github.com/ansible-collections/kubernetes.core/pull/322).
|
||||||
|
- k8s_exec - select first container from the pod if none specified (https://github.com/ansible-collections/kubernetes.core/issues/358).
|
||||||
|
- k8s_exec - update deprecation warning for `return_code` (https://github.com/ansible-collections/kubernetes.core/issues/417).
|
||||||
|
- k8s_json_patch - minor typo fix in the example section (https://github.com/ansible-collections/kubernetes.core/issues/411).
|
||||||
|
- k8s_log - add the ``all_containers`` for retrieving all containers' logs in the pod(s).
|
||||||
|
- k8s_log - added the `previous` parameter for retrieving the previously terminated pod logs (https://github.com/ansible-collections/kubernetes.core/issues/437).
|
||||||
|
- k8s_log - added the `tail_lines` parameter to limit the number of lines to be retrieved from the end of the logs (https://github.com/ansible-collections/kubernetes.core/issues/488).
|
||||||
|
- k8s_rollback - add support for check_mode. (https://github.com/ansible-collections/kubernetes/core/issues/243).
|
||||||
|
- k8s_scale - add support for check_mode. (https://github.com/ansible-collections/kubernetes/core/issues/244).
|
||||||
|
- kubectl - wait for dd command to complete before proceeding (https://github.com/ansible-collections/kubernetes.core/pull/321).
|
||||||
|
- kubectl.py - replace distutils.spawn.find_executable with shutil.which in the kubectl connection plugin (https://github.com/ansible-collections/kubernetes.core/pull/456).
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- Fix dry_run logic - Pass the value dry_run=All instead of dry_run=True to the client, add conditional check on kubernetes client version as this feature is supported only for kubernetes >= 18.20.0 (https://github.com/ansible-collections/kubernetes.core/pull/561).
|
||||||
|
- Fix kubeconfig parameter when multiple config files are provided (https://github.com/ansible-collections/kubernetes.core/issues/435).
|
||||||
|
- Helm - Fix issue with alternative kubeconfig provided with validate_certs=False (https://github.com/ansible-collections/kubernetes.core/issues/538).
|
||||||
|
- Various modules and plugins - use vendored version of ``distutils.version`` instead of the deprecated Python standard library ``distutils`` (https://github.com/ansible-collections/kubernetes.core/pull/314).
|
||||||
|
- add missing documentation for filter plugin kubernetes.core.k8s_config_resource_name (https://github.com/ansible-collections/kubernetes.core/issues/558).
|
||||||
|
- common - Ensure the label_selectors parameter of _wait_for method is optional.
|
||||||
|
- common - handle ``aliases`` passed from inventory and lookup plugins.
|
||||||
|
- helm_template - evaluate release_values after values_files, insuring highest precedence (now same behavior as in helm module). (https://github.com/ansible-collections/kubernetes.core/pull/348)
|
||||||
|
- import exception from ``kubernetes.client.rest``.
|
||||||
|
- k8s - Fix issue with check_mode when using server side apply (https://github.com/ansible-collections/kubernetes.core/issues/547).
|
||||||
|
- k8s - Fix issue with server side apply with kubernetes release '25.3.0' (https://github.com/ansible-collections/kubernetes.core/issues/548).
|
||||||
|
- k8s_cp - add support for check_mode (https://github.com/ansible-collections/kubernetes.core/issues/380).
|
||||||
|
- k8s_drain - fix error caused by accessing an undefined variable when pods have local storage (https://github.com/ansible-collections/kubernetes.core/issues/292).
|
||||||
|
- k8s_info - don't wait on empty List resources (https://github.com/ansible-collections/kubernetes.core/pull/253).
|
||||||
|
- k8s_info - fix issue when module returns successful true after the resource cache has been established during periods where communication to the api-server is not possible (https://github.com/ansible-collections/kubernetes.core/issues/508).
|
||||||
|
- k8s_log - Fix module traceback when no resource found (https://github.com/ansible-collections/kubernetes.core/issues/479).
|
||||||
|
- k8s_log - fix exception raised when the name is not provided for resources requiring. (https://github.com/ansible-collections/kubernetes.core/issues/514)
|
||||||
|
- k8s_scale - fix waiting on statefulset when scaled down to 0 replicas (https://github.com/ansible-collections/kubernetes.core/issues/203).
|
||||||
|
- module_utils.common - change default opening mode to read-bytes to avoid bad interpretation of non ascii characters and strings, often present in 3rd party manifests.
|
||||||
|
- module_utils/k8s/client.py - fix issue when trying to authenticate with host, client_cert and client_key parameters only.
|
||||||
|
- remove binary file from k8s_cp test suite (https://github.com/ansible-collections/kubernetes.core/pull/298).
|
||||||
|
- use resource prefix when finding resource and apiVersion is v1 (https://github.com/ansible-collections/kubernetes.core/issues/351).
|
||||||
|
|
||||||
|
New Modules
|
||||||
|
-----------
|
||||||
|
|
||||||
|
- helm_pull - download a chart from a repository and (optionally) unpack it in local directory.
|
||||||
|
|
||||||
|
v2.3.1
|
||||||
|
======
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- Catch expectation raised when the process is waiting for resources (https://github.com/ansible-collections/kubernetes.core/issues/407).
|
||||||
|
- Remove `omit` placeholder when defining resource using template parameter (https://github.com/ansible-collections/kubernetes.core/issues/431).
|
||||||
|
- k8s - fix the issue when trying to delete resources using label_selectors options (https://github.com/ansible-collections/kubernetes.core/issues/433).
|
||||||
|
- k8s_cp - fix issue when using parameter local_path with file on managed node. (https://github.com/ansible-collections/kubernetes.core/issues/421).
|
||||||
|
- k8s_drain - fix error occurring when trying to drain node with disable_eviction set to yes (https://github.com/ansible-collections/kubernetes.core/issues/416).
|
||||||
|
|
||||||
|
v2.3.0
|
||||||
|
======
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- add support for dry run with kubernetes client version >=18.20 (https://github.com/ansible-collections/kubernetes.core/pull/245).
|
||||||
|
- fixed module_defaults by removing routing hacks from runtime.yml (https://github.com/ansible-collections/kubernetes.core/pull/347).
|
||||||
|
- helm - add support for timeout cli parameter to allow setting Helm timeout independent of wait (https://github.com/ansible-collections/kubernetes.core/issues/67).
|
||||||
|
- helm - add support for wait parameter for helm uninstall command. (https://github.com/ansible-collections/kubernetes/core/issues/33).
|
||||||
|
- helm - support repo location for helm diff (https://github.com/ansible-collections/kubernetes.core/issues/174).
|
||||||
|
- helm - when ansible is executed in check mode, return the diff between what's deployed and what will be deployed.
|
||||||
|
- helm_info - add release state as a module argument (https://github.com/ansible-collections/kubernetes.core/issues/377).
|
||||||
|
- helm_plugin - Add plugin_version parameter to the helm_plugin module (https://github.com/ansible-collections/kubernetes.core/issues/157).
|
||||||
|
- helm_plugin - Add support for helm plugin update using state=update.
|
||||||
|
- helm_repository - add support for pass-credentials cli parameter (https://github.com/ansible-collections/kubernetes.core/pull/282).
|
||||||
|
- helm_repository - added support for ``host``, ``api_key``, ``validate_certs``, and ``ca_cert``.
|
||||||
|
- helm_template - add show_only and release_namespace as module arguments (https://github.com/ansible-collections/kubernetes.core/issues/313).
|
||||||
|
- k8s - add no_proxy support to k8s* (https://github.com/ansible-collections/kubernetes.core/pull/272).
|
||||||
|
- k8s - add support for server_side_apply. (https://github.com/ansible-collections/kubernetes.core/issues/87).
|
||||||
|
- k8s - add support for user impersonation. (https://github.com/ansible-collections/kubernetes/core/issues/40).
|
||||||
|
- k8s - allow resource definition using metadata.generateName (https://github.com/ansible-collections/kubernetes.core/issues/35).
|
||||||
|
- k8s lookup plugin - Enable turbo mode via environment variable (https://github.com/ansible-collections/kubernetes.core/issues/291).
|
||||||
|
- k8s_drain - Adds ``delete_emptydir_data`` option to ``k8s_drain.delete_options`` to evict pods with an ``emptyDir`` volume attached (https://github.com/ansible-collections/kubernetes.core/pull/322).
|
||||||
|
- k8s_exec - select first container from the pod if none specified (https://github.com/ansible-collections/kubernetes.core/issues/358).
|
||||||
|
- k8s_rollback - add support for check_mode. (https://github.com/ansible-collections/kubernetes/core/issues/243).
|
||||||
|
- k8s_scale - add support for check_mode. (https://github.com/ansible-collections/kubernetes/core/issues/244).
|
||||||
|
- kubectl - wait for dd command to complete before proceeding (https://github.com/ansible-collections/kubernetes.core/pull/321).
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- Various modules and plugins - use vendored version of ``distutils.version`` instead of the deprecated Python standard library ``distutils`` (https://github.com/ansible-collections/kubernetes.core/pull/314).
|
||||||
|
- common - Ensure the label_selectors parameter of _wait_for method is optional.
|
||||||
|
- helm_template - evaluate release_values after values_files, insuring highest precedence (now same behavior as in helm module). (https://github.com/ansible-collections/kubernetes.core/pull/348)
|
||||||
|
- import exception from ``kubernetes.client.rest``.
|
||||||
|
- k8s_drain - fix error caused by accessing an undefined variable when pods have local storage (https://github.com/ansible-collections/kubernetes.core/issues/292).
|
||||||
|
- k8s_info - don't wait on empty List resources (https://github.com/ansible-collections/kubernetes.core/pull/253).
|
||||||
|
- k8s_scale - fix waiting on statefulset when scaled down to 0 replicas (https://github.com/ansible-collections/kubernetes.core/issues/203).
|
||||||
|
- module_utils.common - change default opening mode to read-bytes to avoid bad interpretation of non ascii characters and strings, often present in 3rd party manifests.
|
||||||
|
- remove binary file from k8s_cp test suite (https://github.com/ansible-collections/kubernetes.core/pull/298).
|
||||||
|
- use resource prefix when finding resource and apiVersion is v1 (https://github.com/ansible-collections/kubernetes.core/issues/351).
|
||||||
|
|
||||||
|
New Modules
|
||||||
|
-----------
|
||||||
|
|
||||||
|
- k8s_taint - Taint a node in a Kubernetes/OpenShift cluster
|
||||||
|
|
||||||
|
v2.2.0
|
||||||
|
======
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- add support for in-memory kubeconfig in addition to file for k8s modules. (https://github.com/ansible-collections/kubernetes.core/pull/212).
|
||||||
|
- helm - add support for history_max cli parameter (https://github.com/ansible-collections/kubernetes.core/pull/164).
|
||||||
|
- k8s - add support for label_selectors options (https://github.com/ansible-collections/kubernetes.core/issues/43).
|
||||||
|
- k8s - add support for waiting on statefulsets (https://github.com/ansible-collections/kubernetes.core/pull/195).
|
||||||
|
- k8s_log - Add since-seconds parameter to the k8s_log module (https://github.com/ansible-collections/kubernetes.core/pull/142).
|
||||||
|
- new lookup plugin to support kubernetes kustomize feature. (https://github.com/ansible-collections/kubernetes.core/issues/39).
|
||||||
|
- re-enable turbo mode for collection. The default is initially set to off (https://github.com/ansible-collections/kubernetes.core/pull/169).
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- common - import k8sdynamicclient directly to workaround Ansible upstream bug (https://github.com/ansible-collections/kubernetes.core/issues/162).
|
||||||
|
- connection plugin - add arguments information into censored command (https://github.com/ansible-collections/kubernetes.core/pull/196).
|
||||||
|
- fix resource cache not being used (https://github.com/ansible-collections/kubernetes.core/pull/228).
|
||||||
|
- k8s - Fixes a bug where diff was always returned when using apply or modifying an existing object, even when diff=no was specified. The module no longer returns diff unless requested and will now honor diff=no (https://github.com/ansible-collections/kubernetes.core/pull/146).
|
||||||
|
- k8s_cp - fix k8s_cp uploading when target container's WORKDIR is not '/' (https://github.com/ansible-collections/kubernetes.core/issues/222).
|
||||||
|
- k8s_exec - add missing deprecation notice to return_code for k8s_exec (https://github.com/ansible-collections/kubernetes.core/pull/233).
|
||||||
|
- k8s_exec - fix k8s_exec returning rc attribute, to follow ansible's common return values (https://github.com/ansible-collections/kubernetes.core/pull/230).
|
||||||
|
- lookup - recommend query instead of lookup (https://github.com/ansible-collections/kubernetes.core/issues/147).
|
||||||
|
- support the ``template`` param in all collections depending on kubernetes.core (https://github.com/ansible-collections/kubernetes.core/pull/154).
|
||||||
|
|
||||||
|
New Plugins
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Lookup
|
||||||
|
~~~~~~
|
||||||
|
|
||||||
|
- kustomize - Build a set of kubernetes resources using a 'kustomization.yaml' file.
|
||||||
|
|
||||||
|
New Modules
|
||||||
|
-----------
|
||||||
|
|
||||||
|
- k8s_cp - Copy files and directories to and from pod.
|
||||||
|
- k8s_drain - Drain, Cordon, or Uncordon node in k8s cluster
|
||||||
|
|
||||||
|
v2.1.1
|
||||||
|
======
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- check auth params for existence, not whether they are true (https://github.com/ansible-collections/kubernetes.core/pull/151).
|
||||||
|
|
||||||
v2.1.0
|
v2.1.0
|
||||||
======
|
======
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ Where modules have multiple parameters we recommend running through the 4-step m
|
|||||||
|
|
||||||
For general information on running the integration tests see the
|
For general information on running the integration tests see the
|
||||||
[Integration Tests page of the Module Development Guide](https://docs.ansible.com/ansible/devel/dev_guide/testing_integration.html#testing-integration),
|
[Integration Tests page of the Module Development Guide](https://docs.ansible.com/ansible/devel/dev_guide/testing_integration.html#testing-integration),
|
||||||
especially the section on configuration for cloud tests. For questions about writing tests the Ansible Kubernetes community can be found on Libera.Chat IRC as detailed below.
|
especially the section on configuration for cloud tests.
|
||||||
|
|
||||||
### Updating documentation
|
### Updating documentation
|
||||||
|
|
||||||
@@ -70,11 +70,3 @@ Review the changes and create a pull request using updated files.
|
|||||||
The `kubernetes.core` collection follows the Ansible project's
|
The `kubernetes.core` collection follows the Ansible project's
|
||||||
[Code of Conduct](https://docs.ansible.com/ansible/devel/community/code_of_conduct.html).
|
[Code of Conduct](https://docs.ansible.com/ansible/devel/community/code_of_conduct.html).
|
||||||
Please read and familiarize yourself with this document.
|
Please read and familiarize yourself with this document.
|
||||||
|
|
||||||
### IRC
|
|
||||||
Our IRC channels may require you to register your nickname. If you receive an error when you connect, see
|
|
||||||
[Libera.Chat's Nickname Registration guide](https://libera.chat/guides/registration) for instructions.
|
|
||||||
|
|
||||||
The `#ansible-kubernetes` channel on [libera.chat](https://libera.chat/) IRC is the main and official place to discuss use and development of the `kubernetes.core` collection.
|
|
||||||
|
|
||||||
For more information about Ansible's Kubernetes integration, browse the resources in the [Kubernetes Working Group](https://github.com/ansible/community/wiki/Kubernetes) Community wiki page.
|
|
||||||
|
|||||||
9
Makefile
9
Makefile
@@ -1,8 +1,8 @@
|
|||||||
# Also needs to be updated in galaxy.yml
|
# Also needs to be updated in galaxy.yml
|
||||||
VERSION = 2.1.0
|
VERSION = 6.2.0
|
||||||
|
|
||||||
TEST_ARGS ?= ""
|
TEST_ARGS ?= ""
|
||||||
PYTHON_VERSION ?= `python -c 'import platform; print("{0}.{1}".format(platform.python_version_tuple()[0], platform.python_version_tuple()[1]))'`
|
PYTHON_VERSION ?= `python -c 'import platform; print(".".join(platform.python_version_tuple()[0:2]))'`
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f kubernetes-core-${VERSION}.tar.gz
|
rm -f kubernetes-core-${VERSION}.tar.gz
|
||||||
@@ -22,10 +22,7 @@ test-sanity:
|
|||||||
ansible-test sanity --docker -v --color --python $(PYTHON_VERSION) $(?TEST_ARGS)
|
ansible-test sanity --docker -v --color --python $(PYTHON_VERSION) $(?TEST_ARGS)
|
||||||
|
|
||||||
test-integration:
|
test-integration:
|
||||||
ansible-test integration --docker -v --color --retry-on-error --python $(PYTHON_VERSION) --continue-on-error --diff --coverage $(?TEST_ARGS)
|
ansible-test integration --diff --no-temp-workdir --color --skip-tags False --retry-on-error --continue-on-error --python $(PYTHON_VERSION) -v --coverage $(?TEST_ARGS)
|
||||||
|
|
||||||
test-molecule:
|
|
||||||
molecule test
|
|
||||||
|
|
||||||
test-unit:
|
test-unit:
|
||||||
ansible-test units --docker -v --color --python $(PYTHON_VERSION) $(?TEST_ARGS)
|
ansible-test units --docker -v --color --python $(PYTHON_VERSION) $(?TEST_ARGS)
|
||||||
|
|||||||
48
PSF-license.txt
Normal file
48
PSF-license.txt
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
1. This LICENSE AGREEMENT is between the Python Software Foundation
|
||||||
|
("PSF"), and the Individual or Organization ("Licensee") accessing and
|
||||||
|
otherwise using this software ("Python") in source or binary form and
|
||||||
|
its associated documentation.
|
||||||
|
|
||||||
|
2. Subject to the terms and conditions of this License Agreement, PSF hereby
|
||||||
|
grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
|
||||||
|
analyze, test, perform and/or display publicly, prepare derivative works,
|
||||||
|
distribute, and otherwise use Python alone or in any derivative version,
|
||||||
|
provided, however, that PSF's License Agreement and PSF's notice of copyright,
|
||||||
|
i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||||
|
2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Python Software Foundation;
|
||||||
|
All Rights Reserved" are retained in Python alone or in any derivative version
|
||||||
|
prepared by Licensee.
|
||||||
|
|
||||||
|
3. In the event Licensee prepares a derivative work that is based on
|
||||||
|
or incorporates Python or any part thereof, and wants to make
|
||||||
|
the derivative work available to others as provided herein, then
|
||||||
|
Licensee hereby agrees to include in any such work a brief summary of
|
||||||
|
the changes made to Python.
|
||||||
|
|
||||||
|
4. PSF is making Python available to Licensee on an "AS IS"
|
||||||
|
basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||||
|
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
|
||||||
|
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||||
|
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
|
||||||
|
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||||
|
|
||||||
|
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
|
||||||
|
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
|
||||||
|
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
|
||||||
|
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
||||||
|
|
||||||
|
6. This License Agreement will automatically terminate upon a material
|
||||||
|
breach of its terms and conditions.
|
||||||
|
|
||||||
|
7. Nothing in this License Agreement shall be deemed to create any
|
||||||
|
relationship of agency, partnership, or joint venture between PSF and
|
||||||
|
Licensee. This License Agreement does not grant permission to use PSF
|
||||||
|
trademarks or trade name in a trademark sense to endorse or promote
|
||||||
|
products or services of Licensee, or any third party.
|
||||||
|
|
||||||
|
8. By copying, installing or otherwise using Python, Licensee
|
||||||
|
agrees to be bound by the terms and conditions of this License
|
||||||
|
Agreement.
|
||||||
102
README.md
102
README.md
@@ -1,28 +1,46 @@
|
|||||||
# Kubernetes Collection for Ansible
|
# Kubernetes Collection for Ansible
|
||||||
|
|
||||||
[](https://github.com/ansible-collections/kubernetes.core/actions) [](https://codecov.io/gh/ansible-collections/kubernetes.core)
|
This repository hosts the `kubernetes.core` (formerly known as `community.kubernetes`) Ansible Collection.
|
||||||
|
|
||||||
This repo hosts the `kubernetes.core` (formerly known as `community.kubernetes`) Ansible Collection.
|
## Description
|
||||||
|
|
||||||
The collection includes a variety of Ansible content to help automate the management of applications in Kubernetes and OpenShift clusters, as well as the provisioning and maintenance of clusters themselves.
|
The collection includes a variety of Ansible content to help automate the management of applications in Kubernetes and OpenShift clusters, as well as the provisioning and maintenance of clusters themselves.
|
||||||
|
|
||||||
|
## Communication
|
||||||
|
|
||||||
|
* Join the Ansible forum:
|
||||||
|
* [Get Help](https://forum.ansible.com/c/help/6): get help or help others.
|
||||||
|
* [Posts tagged with 'kubernetes'](https://forum.ansible.com/tag/kubernetes): subscribe to participate in collection-related conversations.
|
||||||
|
* [Social Spaces](https://forum.ansible.com/c/chat/4): gather and interact with fellow enthusiasts.
|
||||||
|
* [News & Announcements](https://forum.ansible.com/c/news/5): track project-wide announcements including social events.
|
||||||
|
|
||||||
|
* The Ansible [Bullhorn newsletter](https://docs.ansible.com/ansible/devel/community/communication.html#the-bullhorn): used to announce releases and important changes.
|
||||||
|
|
||||||
|
For more information about communication, see the [Ansible communication guide](https://docs.ansible.com/ansible/devel/community/communication.html).
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
<!--start requires_ansible-->
|
<!--start requires_ansible-->
|
||||||
## Ansible version compatibility
|
## Ansible version compatibility
|
||||||
|
|
||||||
This collection has been tested against following Ansible versions: **>=2.9.17**.
|
This collection has been tested against the following Ansible versions: **>=2.16.0**.
|
||||||
|
|
||||||
Plugins and modules within a collection may be tested with only specific Ansible versions.
|
Plugins and modules within a collection may be tested with only specific Ansible versions.
|
||||||
A collection may contain metadata that identifies these versions.
|
A collection may contain metadata that identifies these versions.
|
||||||
PEP440 is the schema used to describe the versions of Ansible.
|
PEP440 is the schema used to describe the versions of Ansible.
|
||||||
<!--end requires_ansible-->
|
<!--end requires_ansible-->
|
||||||
|
|
||||||
## Python Support
|
### Python Support
|
||||||
|
|
||||||
* Collection supports 3.6+
|
* Collection supports 3.9+
|
||||||
|
|
||||||
Note: Python2 is deprecated from [1st January 2020](https://www.python.org/doc/sunset-python-2/). Please switch to Python3.
|
Note: Python2 is deprecated from [1st January 2020](https://www.python.org/doc/sunset-python-2/). Please switch to Python3.
|
||||||
|
|
||||||
## Included content
|
### Kubernetes Version Support
|
||||||
|
|
||||||
|
This collection supports Kubernetes versions >= 1.24.
|
||||||
|
|
||||||
|
### Included Content
|
||||||
|
|
||||||
Click on the name of a plugin or module to view that content's documentation:
|
Click on the name of a plugin or module to view that content's documentation:
|
||||||
|
|
||||||
@@ -37,15 +55,11 @@ Name | Description
|
|||||||
--- | ---
|
--- | ---
|
||||||
kubernetes.core.k8s_config_resource_name|Generate resource name for the given resource of type ConfigMap, Secret
|
kubernetes.core.k8s_config_resource_name|Generate resource name for the given resource of type ConfigMap, Secret
|
||||||
|
|
||||||
### Inventory plugins
|
|
||||||
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
|
Name | Description
|
||||||
--- | ---
|
--- | ---
|
||||||
[kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_lookup.rst)|Query the K8s API
|
[kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_lookup.rst)|Query the K8s API
|
||||||
|
[kubernetes.core.kustomize](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.kustomize_lookup.rst)|Build a set of kubernetes resources using a 'kustomization.yaml' file.
|
||||||
|
|
||||||
### Modules
|
### Modules
|
||||||
Name | Description
|
Name | Description
|
||||||
@@ -54,10 +68,14 @@ Name | Description
|
|||||||
[kubernetes.core.helm_info](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_info_module.rst)|Get information from Helm package deployed inside the cluster
|
[kubernetes.core.helm_info](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_info_module.rst)|Get information from Helm package deployed inside the cluster
|
||||||
[kubernetes.core.helm_plugin](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_plugin_module.rst)|Manage Helm plugins
|
[kubernetes.core.helm_plugin](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_plugin_module.rst)|Manage Helm plugins
|
||||||
[kubernetes.core.helm_plugin_info](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_plugin_info_module.rst)|Gather information about Helm plugins
|
[kubernetes.core.helm_plugin_info](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_plugin_info_module.rst)|Gather information about Helm plugins
|
||||||
|
[kubernetes.core.helm_pull](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_pull_module.rst)|download a chart from a repository and (optionally) unpack it in local directory.
|
||||||
|
[kubernetes.core.helm_registry_auth](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_registry_auth_module.rst)|Helm registry authentication module
|
||||||
[kubernetes.core.helm_repository](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_repository_module.rst)|Manage Helm repositories.
|
[kubernetes.core.helm_repository](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_repository_module.rst)|Manage Helm repositories.
|
||||||
[kubernetes.core.helm_template](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_template_module.rst)|Render chart templates
|
[kubernetes.core.helm_template](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.helm_template_module.rst)|Render chart templates
|
||||||
[kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_module.rst)|Manage Kubernetes (K8s) objects
|
[kubernetes.core.k8s](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_module.rst)|Manage Kubernetes (K8s) objects
|
||||||
[kubernetes.core.k8s_cluster_info](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_cluster_info_module.rst)|Describe Kubernetes (K8s) cluster, APIs available and their respective versions
|
[kubernetes.core.k8s_cluster_info](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_cluster_info_module.rst)|Describe Kubernetes (K8s) cluster, APIs available and their respective versions
|
||||||
|
[kubernetes.core.k8s_cp](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_cp_module.rst)|Copy files and directories to and from pod.
|
||||||
|
[kubernetes.core.k8s_drain](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_drain_module.rst)|Drain, Cordon, or Uncordon node in k8s cluster
|
||||||
[kubernetes.core.k8s_exec](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_exec_module.rst)|Execute command in Pod
|
[kubernetes.core.k8s_exec](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_exec_module.rst)|Execute command in Pod
|
||||||
[kubernetes.core.k8s_info](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_info_module.rst)|Describe Kubernetes (K8s) objects
|
[kubernetes.core.k8s_info](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_info_module.rst)|Describe Kubernetes (K8s) objects
|
||||||
[kubernetes.core.k8s_json_patch](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_json_patch_module.rst)|Apply JSON patch operations to existing objects
|
[kubernetes.core.k8s_json_patch](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_json_patch_module.rst)|Apply JSON patch operations to existing objects
|
||||||
@@ -65,12 +83,11 @@ Name | Description
|
|||||||
[kubernetes.core.k8s_rollback](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_rollback_module.rst)|Rollback Kubernetes (K8S) Deployments and DaemonSets
|
[kubernetes.core.k8s_rollback](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_rollback_module.rst)|Rollback Kubernetes (K8S) Deployments and DaemonSets
|
||||||
[kubernetes.core.k8s_scale](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_scale_module.rst)|Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job.
|
[kubernetes.core.k8s_scale](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_scale_module.rst)|Set a new size for a Deployment, ReplicaSet, Replication Controller, or Job.
|
||||||
[kubernetes.core.k8s_service](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_service_module.rst)|Manage Services on Kubernetes
|
[kubernetes.core.k8s_service](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_service_module.rst)|Manage Services on Kubernetes
|
||||||
|
[kubernetes.core.k8s_taint](https://github.com/ansible-collections/kubernetes.core/blob/main/docs/kubernetes.core.k8s_taint_module.rst)|Taint a node in a Kubernetes/OpenShift cluster
|
||||||
|
|
||||||
<!--end collection content-->
|
<!--end collection content-->
|
||||||
|
|
||||||
## Installation and Usage
|
## Installation
|
||||||
|
|
||||||
### Installing the Collection from Ansible Galaxy
|
|
||||||
|
|
||||||
Before using the Kubernetes collection, you need to install it with the Ansible Galaxy CLI:
|
Before using the Kubernetes collection, you need to install it with the Ansible Galaxy CLI:
|
||||||
|
|
||||||
@@ -82,7 +99,7 @@ You can also include it in a `requirements.yml` file and install it via `ansible
|
|||||||
---
|
---
|
||||||
collections:
|
collections:
|
||||||
- name: kubernetes.core
|
- name: kubernetes.core
|
||||||
version: 2.1.0
|
version: 6.2.0
|
||||||
```
|
```
|
||||||
|
|
||||||
### Installing the Kubernetes Python Library
|
### Installing the Kubernetes Python Library
|
||||||
@@ -91,7 +108,7 @@ Content in this collection requires the [Kubernetes Python client](https://pypi.
|
|||||||
|
|
||||||
pip3 install kubernetes
|
pip3 install kubernetes
|
||||||
|
|
||||||
### Using modules from the Kubernetes Collection in your playbooks
|
## Use Cases
|
||||||
|
|
||||||
It's preferable to use content in this collection using their Fully Qualified Collection Namespace (FQCN), for example `kubernetes.core.k8s_info`:
|
It's preferable to use content in this collection using their Fully Qualified Collection Namespace (FQCN), for example `kubernetes.core.k8s_info`:
|
||||||
|
|
||||||
@@ -159,12 +176,35 @@ If upgrading older playbooks which were built prior to Ansible 2.10 and this col
|
|||||||
|
|
||||||
For documentation on how to use individual modules and other content included in this collection, please see the links in the 'Included content' section earlier in this README.
|
For documentation on how to use individual modules and other content included in this collection, please see the links in the 'Included content' section earlier in this README.
|
||||||
|
|
||||||
## Testing and Development
|
## Ansible Turbo Mode Tech Preview
|
||||||
|
|
||||||
|
|
||||||
|
The ``kubernetes.core`` collection supports Ansible Turbo mode as a tech preview via the ``cloud.common`` collection. By default, this feature is disabled. To enable Turbo mode for modules, set the environment variable `ENABLE_TURBO_MODE=1` on the managed node. For example:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
- hosts: remote
|
||||||
|
environment:
|
||||||
|
ENABLE_TURBO_MODE: 1
|
||||||
|
tasks:
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
To enable Turbo mode for k8s lookup plugin, set the environment variable `ENABLE_TURBO_MODE=1` on the managed node. This is not working when
|
||||||
|
defined in the playbook using `environment` keyword as above, you must set it using `export ENABLE_TURBO_MODE=1`.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
If you want to develop new content for this collection or improve what's already here, the easiest way to work on the collection is to clone it into one of the configured [`COLLECTIONS_PATHS`](https://docs.ansible.com/ansible/latest/reference_appendices/config.html#collections-paths), and work on it there.
|
If you want to develop new content for this collection or improve what's already here, the easiest way to work on the collection is to clone it into one of the configured [`COLLECTIONS_PATHS`](https://docs.ansible.com/ansible/latest/reference_appendices/config.html#collections-paths), and work on it there.
|
||||||
|
|
||||||
See [Contributing to kubernetes.core](CONTRIBUTING.md).
|
See [Contributing to kubernetes.core](CONTRIBUTING.md).
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
[](https://github.com/ansible-collections/kubernetes.core/actions/workflows/linters.yaml) [](https://github.com/ansible-collections/kubernetes.core/actions/workflows/integration-tests.yaml) [](https://github.com/ansible-collections/kubernetes.core/actions/workflows/sanity-tests.yaml) [](https://github.com/ansible-collections/kubernetes.core/actions/workflows/unit-tests.yaml) [](https://app.codecov.io/gh/ansible-collections/kubernetes.core)
|
||||||
|
|
||||||
### Testing with `ansible-test`
|
### Testing with `ansible-test`
|
||||||
|
|
||||||
The `tests` directory contains configuration for running sanity and integration tests using [`ansible-test`](https://docs.ansible.com/ansible/latest/dev_guide/testing_integration.html).
|
The `tests` directory contains configuration for running sanity and integration tests using [`ansible-test`](https://docs.ansible.com/ansible/latest/dev_guide/testing_integration.html).
|
||||||
@@ -201,9 +241,33 @@ After the version is published, verify it exists on the [Kubernetes Collection G
|
|||||||
|
|
||||||
The process for uploading a supported release to Automation Hub is documented separately.
|
The process for uploading a supported release to Automation Hub is documented separately.
|
||||||
|
|
||||||
## More Information
|
## Support
|
||||||
|
|
||||||
|
<!--List available communication channels. In addition to channels specific to your collection, we also recommend to use the following ones.-->
|
||||||
|
|
||||||
|
> **Note:** The `stable-4` branch, which handles all `4.x.y` releases of this collection, is no longer supported. This means that no backports nor releases will be performed on the `stable-4` branch.
|
||||||
|
|
||||||
|
We announce releases and important changes through Ansible's [The Bullhorn newsletter](https://github.com/ansible/community/wiki/News#the-bullhorn). Be sure you are [subscribed](https://eepurl.com/gZmiEP).
|
||||||
|
|
||||||
|
We take part in the global quarterly [Ansible Contributor Summit](https://github.com/ansible/community/wiki/Contributor-Summit) virtually or in-person. Track [The Bullhorn newsletter](https://eepurl.com/gZmiEP) and join us.
|
||||||
|
|
||||||
|
For more information about communication, refer to the [Ansible Communication guide](https://docs.ansible.com/ansible/devel/community/communication.html).
|
||||||
|
|
||||||
|
For the latest supported versions, refer to the release notes below.
|
||||||
|
|
||||||
|
If you encounter issues or have questions, you can submit a support request through the following channels:
|
||||||
|
- GitHub Issues: Report bugs, request features, or ask questions by opening an issue in the [GitHub repository]((https://github.com/ansible-collections/kubernetes.core/).
|
||||||
|
|
||||||
|
## Release Notes
|
||||||
|
|
||||||
|
See the [raw generated changelog](https://github.com/ansible-collections/kubernetes.core/blob/main/CHANGELOG.rst).
|
||||||
|
|
||||||
|
## Code of Conduct
|
||||||
|
|
||||||
|
We follow the [Ansible Code of Conduct](https://docs.ansible.com/ansible/devel/community/code_of_conduct.html) in all our interactions within this project.
|
||||||
|
|
||||||
|
If you encounter abusive behavior, please refer to the [policy violations](https://docs.ansible.com/ansible/devel/community/code_of_conduct.html#policy-violations) section of the Code for information on how to raise a complaint.
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
kubernetes-client [platform:fedora]
|
kubernetes-client [platform:fedora]
|
||||||
|
openshift-clients [platform:rhel-8]
|
||||||
|
openshift-clients [platform:rhel-9]
|
||||||
|
|||||||
@@ -422,3 +422,708 @@ releases:
|
|||||||
- 148-remove-cloud-common-dependency.yaml
|
- 148-remove-cloud-common-dependency.yaml
|
||||||
- 149-disable-turbo-mode.yaml
|
- 149-disable-turbo-mode.yaml
|
||||||
release_date: '2021-06-23'
|
release_date: '2021-06-23'
|
||||||
|
2.1.1:
|
||||||
|
changes:
|
||||||
|
bugfixes:
|
||||||
|
- check auth params for existence, not whether they are true (https://github.com/ansible-collections/kubernetes.core/pull/151).
|
||||||
|
fragments:
|
||||||
|
- 151-check-auth-params-for-existence.yaml
|
||||||
|
release_date: '2021-06-24'
|
||||||
|
2.2.0:
|
||||||
|
changes:
|
||||||
|
bugfixes:
|
||||||
|
- common - import k8sdynamicclient directly to workaround Ansible upstream bug
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/issues/162).
|
||||||
|
- connection plugin - add arguments information into censored command (https://github.com/ansible-collections/kubernetes.core/pull/196).
|
||||||
|
- fix resource cache not being used (https://github.com/ansible-collections/kubernetes.core/pull/228).
|
||||||
|
- k8s - Fixes a bug where diff was always returned when using apply or modifying
|
||||||
|
an existing object, even when diff=no was specified. The module no longer
|
||||||
|
returns diff unless requested and will now honor diff=no (https://github.com/ansible-collections/kubernetes.core/pull/146).
|
||||||
|
- k8s_cp - fix k8s_cp uploading when target container's WORKDIR is not '/' (https://github.com/ansible-collections/kubernetes.core/issues/222).
|
||||||
|
- k8s_exec - add missing deprecation notice to return_code for k8s_exec (https://github.com/ansible-collections/kubernetes.core/pull/233).
|
||||||
|
- k8s_exec - fix k8s_exec returning rc attribute, to follow ansible's common
|
||||||
|
return values (https://github.com/ansible-collections/kubernetes.core/pull/230).
|
||||||
|
- lookup - recommend query instead of lookup (https://github.com/ansible-collections/kubernetes.core/issues/147).
|
||||||
|
- support the ``template`` param in all collections depending on kubernetes.core
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/pull/154).
|
||||||
|
minor_changes:
|
||||||
|
- add support for in-memory kubeconfig in addition to file for k8s modules.
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/pull/212).
|
||||||
|
- helm - add support for history_max cli parameter (https://github.com/ansible-collections/kubernetes.core/pull/164).
|
||||||
|
- k8s - add support for label_selectors options (https://github.com/ansible-collections/kubernetes.core/issues/43).
|
||||||
|
- k8s - add support for waiting on statefulsets (https://github.com/ansible-collections/kubernetes.core/pull/195).
|
||||||
|
- k8s_log - Add since-seconds parameter to the k8s_log module (https://github.com/ansible-collections/kubernetes.core/pull/142).
|
||||||
|
- new lookup plugin to support kubernetes kustomize feature. (https://github.com/ansible-collections/kubernetes.core/issues/39).
|
||||||
|
- re-enable turbo mode for collection. The default is initially set to off (https://github.com/ansible-collections/kubernetes.core/pull/169).
|
||||||
|
fragments:
|
||||||
|
- 142-add-sinceseconds-param-for-logs.yaml
|
||||||
|
- 146-k8s-add-support-diff-mode.yml
|
||||||
|
- 147_lookup.yml
|
||||||
|
- 154-template-param-support.yaml
|
||||||
|
- 158-k8s-add-support-label_selectors.yml
|
||||||
|
- 162_import_error.yml
|
||||||
|
- 164-add-history-max.yaml
|
||||||
|
- 169-reenable-turbo-mode.yaml
|
||||||
|
- 195-k8s-add-wait-statefulsets.yml
|
||||||
|
- 196_kubectl.yaml
|
||||||
|
- 212-in-memory-kubeconfig.yml
|
||||||
|
- 223-add-deprecation-notice.yaml
|
||||||
|
- 223-k8s-cp-uploading.yaml
|
||||||
|
- 225-kustomize-lookup-plugin.yml
|
||||||
|
- 228-fix-resource-cache.yml
|
||||||
|
- 230-k8sexec-has-new-returnvalue.yml
|
||||||
|
modules:
|
||||||
|
- description: Copy files and directories to and from pod.
|
||||||
|
name: k8s_cp
|
||||||
|
namespace: ''
|
||||||
|
- description: Drain, Cordon, or Uncordon node in k8s cluster
|
||||||
|
name: k8s_drain
|
||||||
|
namespace: ''
|
||||||
|
plugins:
|
||||||
|
lookup:
|
||||||
|
- description: Build a set of kubernetes resources using a 'kustomization.yaml'
|
||||||
|
file.
|
||||||
|
name: kustomize
|
||||||
|
namespace: null
|
||||||
|
release_date: '2021-09-15'
|
||||||
|
2.3.0:
|
||||||
|
changes:
|
||||||
|
bugfixes:
|
||||||
|
- Various modules and plugins - use vendored version of ``distutils.version``
|
||||||
|
instead of the deprecated Python standard library ``distutils`` (https://github.com/ansible-collections/kubernetes.core/pull/314).
|
||||||
|
- common - Ensure the label_selectors parameter of _wait_for method is optional.
|
||||||
|
- helm_template - evaluate release_values after values_files, insuring highest
|
||||||
|
precedence (now same behavior as in helm module). (https://github.com/ansible-collections/kubernetes.core/pull/348)
|
||||||
|
- import exception from ``kubernetes.client.rest``.
|
||||||
|
- k8s_drain - fix error caused by accessing an undefined variable when pods
|
||||||
|
have local storage (https://github.com/ansible-collections/kubernetes.core/issues/292).
|
||||||
|
- k8s_info - don't wait on empty List resources (https://github.com/ansible-collections/kubernetes.core/pull/253).
|
||||||
|
- k8s_scale - fix waiting on statefulset when scaled down to 0 replicas (https://github.com/ansible-collections/kubernetes.core/issues/203).
|
||||||
|
- module_utils.common - change default opening mode to read-bytes to avoid bad
|
||||||
|
interpretation of non ascii characters and strings, often present in 3rd party
|
||||||
|
manifests.
|
||||||
|
- remove binary file from k8s_cp test suite (https://github.com/ansible-collections/kubernetes.core/pull/298).
|
||||||
|
- use resource prefix when finding resource and apiVersion is v1 (https://github.com/ansible-collections/kubernetes.core/issues/351).
|
||||||
|
minor_changes:
|
||||||
|
- add support for dry run with kubernetes client version >=18.20 (https://github.com/ansible-collections/kubernetes.core/pull/245).
|
||||||
|
- fixed module_defaults by removing routing hacks from runtime.yml (https://github.com/ansible-collections/kubernetes.core/pull/347).
|
||||||
|
- helm - add support for timeout cli parameter to allow setting Helm timeout
|
||||||
|
independent of wait (https://github.com/ansible-collections/kubernetes.core/issues/67).
|
||||||
|
- helm - add support for wait parameter for helm uninstall command. (https://github.com/ansible-collections/kubernetes/core/issues/33).
|
||||||
|
- helm - support repo location for helm diff (https://github.com/ansible-collections/kubernetes.core/issues/174).
|
||||||
|
- helm - when ansible is executed in check mode, return the diff between what's
|
||||||
|
deployed and what will be deployed.
|
||||||
|
- helm_info - add release state as a module argument (https://github.com/ansible-collections/kubernetes.core/issues/377).
|
||||||
|
- helm_plugin - Add plugin_version parameter to the helm_plugin module (https://github.com/ansible-collections/kubernetes.core/issues/157).
|
||||||
|
- helm_plugin - Add support for helm plugin update using state=update.
|
||||||
|
- helm_repository - add support for pass-credentials cli parameter (https://github.com/ansible-collections/kubernetes.core/pull/282).
|
||||||
|
- helm_repository - added support for ``host``, ``api_key``, ``validate_certs``,
|
||||||
|
and ``ca_cert``.
|
||||||
|
- helm_template - add show_only and release_namespace as module arguments (https://github.com/ansible-collections/kubernetes.core/issues/313).
|
||||||
|
- k8s - add no_proxy support to k8s* (https://github.com/ansible-collections/kubernetes.core/pull/272).
|
||||||
|
- k8s - add support for server_side_apply. (https://github.com/ansible-collections/kubernetes.core/issues/87).
|
||||||
|
- k8s - add support for user impersonation. (https://github.com/ansible-collections/kubernetes/core/issues/40).
|
||||||
|
- k8s - allow resource definition using metadata.generateName (https://github.com/ansible-collections/kubernetes.core/issues/35).
|
||||||
|
- k8s lookup plugin - Enable turbo mode via environment variable (https://github.com/ansible-collections/kubernetes.core/issues/291).
|
||||||
|
- k8s_drain - Adds ``delete_emptydir_data`` option to ``k8s_drain.delete_options``
|
||||||
|
to evict pods with an ``emptyDir`` volume attached (https://github.com/ansible-collections/kubernetes.core/pull/322).
|
||||||
|
- k8s_exec - select first container from the pod if none specified (https://github.com/ansible-collections/kubernetes.core/issues/358).
|
||||||
|
- k8s_rollback - add support for check_mode. (https://github.com/ansible-collections/kubernetes/core/issues/243).
|
||||||
|
- k8s_scale - add support for check_mode. (https://github.com/ansible-collections/kubernetes/core/issues/244).
|
||||||
|
- kubectl - wait for dd command to complete before proceeding (https://github.com/ansible-collections/kubernetes.core/pull/321).
|
||||||
|
fragments:
|
||||||
|
- 0-copy_ignore_txt.yml
|
||||||
|
- 226-add-version-parameter-to-helm_plugin.yml
|
||||||
|
- 231-helm-add-timeout-parameter.yaml
|
||||||
|
- 238-helm-add-support-for-helm-uninstall-wait.yaml
|
||||||
|
- 238-k8s-add-support-for-generate_name.yml
|
||||||
|
- 245-add-dry-run.yaml
|
||||||
|
- 250-k8s-add-support-for-impersonation.yaml
|
||||||
|
- 253-dont-wait-on-list-resources.yaml
|
||||||
|
- 255-k8s_scale-k8s_rollback-add-support-for-check_mode.yml
|
||||||
|
- 260-k8s-add-support-for-server_side_apply.yml
|
||||||
|
- 272-k8s-add-support-no_proxy.yaml
|
||||||
|
- 282-helm-repository-add-pass-credentials.yaml
|
||||||
|
- 290-returns-diff-in-check-mode.yaml
|
||||||
|
- 295-fix-k8s-drain-variable-declaration.yaml
|
||||||
|
- 298-remove-binary-file.yaml
|
||||||
|
- 308-fix-for-common-non-ascii-characters-in-resources.yaml
|
||||||
|
- 313-helm-template-add-support-for-show-only-and-release-namespace.yml
|
||||||
|
- 321-kubectl_sleep.yml
|
||||||
|
- 322-Add-delete_emptydir_data-to-drain-delete_options.yaml
|
||||||
|
- 335-k8s-lookup-add-support-for-turbo-mode.yml
|
||||||
|
- 347-routing.yml
|
||||||
|
- 348-helm_template-fix-precedence-of-release-values-over-values-files.yaml
|
||||||
|
- 358-k8s_exec.yml
|
||||||
|
- 364-use-resource-prefix.yaml
|
||||||
|
- 377-helm-info-state.yml
|
||||||
|
- 389-helm-add-support-chart_repo_url-on-helm_diff.yml
|
||||||
|
- 391-fix-statefulset-wait.yaml
|
||||||
|
- _wait_for_label_selector_optional.yaml
|
||||||
|
- disutils.version.yml
|
||||||
|
- exception.yml
|
||||||
|
- helm_repository.yml
|
||||||
|
modules:
|
||||||
|
- description: Taint a node in a Kubernetes/OpenShift cluster
|
||||||
|
name: k8s_taint
|
||||||
|
namespace: ''
|
||||||
|
release_date: '2022-03-11'
|
||||||
|
2.3.1:
|
||||||
|
changes:
|
||||||
|
bugfixes:
|
||||||
|
- Catch expectation raised when the process is waiting for resources (https://github.com/ansible-collections/kubernetes.core/issues/407).
|
||||||
|
- Remove `omit` placeholder when defining resource using template parameter
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/issues/431).
|
||||||
|
- k8s - fix the issue when trying to delete resources using label_selectors
|
||||||
|
options (https://github.com/ansible-collections/kubernetes.core/issues/433).
|
||||||
|
- k8s_cp - fix issue when using parameter local_path with file on managed node.
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/issues/421).
|
||||||
|
- k8s_drain - fix error occurring when trying to drain node with disable_eviction
|
||||||
|
set to yes (https://github.com/ansible-collections/kubernetes.core/issues/416).
|
||||||
|
fragments:
|
||||||
|
- 408-fix-wait-on-exception.yml
|
||||||
|
- 417-fix-k8s-drain-delete-options.yaml
|
||||||
|
- 422-k8s_cp-fix-issue-when-issue-local_path.yaml
|
||||||
|
- 432-fix-issue-when-using-template-parameter.yaml
|
||||||
|
- 434-fix-k8s-delete-using-label_selector.yaml
|
||||||
|
release_date: '2022-05-02'
|
||||||
|
2.4.0:
|
||||||
|
changes:
|
||||||
|
bugfixes:
|
||||||
|
- Fix dry_run logic - Pass the value dry_run=All instead of dry_run=True to
|
||||||
|
the client, add conditional check on kubernetes client version as this feature
|
||||||
|
is supported only for kubernetes >= 18.20.0 (https://github.com/ansible-collections/kubernetes.core/pull/561).
|
||||||
|
- Fix kubeconfig parameter when multiple config files are provided (https://github.com/ansible-collections/kubernetes.core/issues/435).
|
||||||
|
- Helm - Fix issue with alternative kubeconfig provided with validate_certs=False
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/issues/538).
|
||||||
|
- Various modules and plugins - use vendored version of ``distutils.version``
|
||||||
|
instead of the deprecated Python standard library ``distutils`` (https://github.com/ansible-collections/kubernetes.core/pull/314).
|
||||||
|
- add missing documentation for filter plugin kubernetes.core.k8s_config_resource_name
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/issues/558).
|
||||||
|
- common - Ensure the label_selectors parameter of _wait_for method is optional.
|
||||||
|
- common - handle ``aliases`` passed from inventory and lookup plugins.
|
||||||
|
- helm_template - evaluate release_values after values_files, insuring highest
|
||||||
|
precedence (now same behavior as in helm module). (https://github.com/ansible-collections/kubernetes.core/pull/348)
|
||||||
|
- import exception from ``kubernetes.client.rest``.
|
||||||
|
- k8s - Fix issue with check_mode when using server side apply (https://github.com/ansible-collections/kubernetes.core/issues/547).
|
||||||
|
- k8s - Fix issue with server side apply with kubernetes release '25.3.0' (https://github.com/ansible-collections/kubernetes.core/issues/548).
|
||||||
|
- k8s_cp - add support for check_mode (https://github.com/ansible-collections/kubernetes.core/issues/380).
|
||||||
|
- k8s_drain - fix error caused by accessing an undefined variable when pods
|
||||||
|
have local storage (https://github.com/ansible-collections/kubernetes.core/issues/292).
|
||||||
|
- k8s_info - don't wait on empty List resources (https://github.com/ansible-collections/kubernetes.core/pull/253).
|
||||||
|
- k8s_info - fix issue when module returns successful true after the resource
|
||||||
|
cache has been established during periods where communication to the api-server
|
||||||
|
is not possible (https://github.com/ansible-collections/kubernetes.core/issues/508).
|
||||||
|
- k8s_log - Fix module traceback when no resource found (https://github.com/ansible-collections/kubernetes.core/issues/479).
|
||||||
|
- k8s_log - fix exception raised when the name is not provided for resources
|
||||||
|
requiring. (https://github.com/ansible-collections/kubernetes.core/issues/514)
|
||||||
|
- k8s_scale - fix waiting on statefulset when scaled down to 0 replicas (https://github.com/ansible-collections/kubernetes.core/issues/203).
|
||||||
|
- module_utils.common - change default opening mode to read-bytes to avoid bad
|
||||||
|
interpretation of non ascii characters and strings, often present in 3rd party
|
||||||
|
manifests.
|
||||||
|
- module_utils/k8s/client.py - fix issue when trying to authenticate with host,
|
||||||
|
client_cert and client_key parameters only.
|
||||||
|
- remove binary file from k8s_cp test suite (https://github.com/ansible-collections/kubernetes.core/pull/298).
|
||||||
|
- use resource prefix when finding resource and apiVersion is v1 (https://github.com/ansible-collections/kubernetes.core/issues/351).
|
||||||
|
major_changes:
|
||||||
|
- refactor K8sAnsibleMixin into module_utils/k8s/ (https://github.com/ansible-collections/kubernetes.core/pull/481).
|
||||||
|
minor_changes:
|
||||||
|
- Adjust k8s_user_impersonation tests to be compatible with Kubernetes 1.24
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/pull/520).
|
||||||
|
- add support for dry run with kubernetes client version >=18.20 (https://github.com/ansible-collections/kubernetes.core/pull/245).
|
||||||
|
- added ignore.txt for Ansible 2.14 devel branch.
|
||||||
|
- fixed module_defaults by removing routing hacks from runtime.yml (https://github.com/ansible-collections/kubernetes.core/pull/347).
|
||||||
|
- helm - add support for -set-file, -set-json, -set and -set-string options
|
||||||
|
when running helm install (https://github.com/ansible-collections/kubernetes.core/issues/533).
|
||||||
|
- helm - add support for helm dependency update (https://github.com/ansible-collections/kubernetes.core/pull/208).
|
||||||
|
- helm - add support for post-renderer flag (https://github.com/ansible-collections/kubernetes.core/issues/30).
|
||||||
|
- helm - add support for timeout cli parameter to allow setting Helm timeout
|
||||||
|
independent of wait (https://github.com/ansible-collections/kubernetes.core/issues/67).
|
||||||
|
- helm - add support for wait parameter for helm uninstall command. (https://github.com/ansible-collections/kubernetes/core/issues/33).
|
||||||
|
- helm - support repo location for helm diff (https://github.com/ansible-collections/kubernetes.core/issues/174).
|
||||||
|
- helm - when ansible is executed in check mode, return the diff between what's
|
||||||
|
deployed and what will be deployed.
|
||||||
|
- helm, helm_plugin, helm_info, helm_plugin_info, kubectl - add support for
|
||||||
|
in-memory kubeconfig. (https://github.com/ansible-collections/kubernetes.core/issues/492).
|
||||||
|
- helm_info - add hooks, notes and manifest as part of returned information
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/pull/546).
|
||||||
|
- helm_info - add release state as a module argument (https://github.com/ansible-collections/kubernetes.core/issues/377).
|
||||||
|
- helm_info - added possibility to get all values by adding get_all_values parameter
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/pull/531).
|
||||||
|
- helm_plugin - Add plugin_version parameter to the helm_plugin module (https://github.com/ansible-collections/kubernetes.core/issues/157).
|
||||||
|
- helm_plugin - Add support for helm plugin update using state=update.
|
||||||
|
- helm_repository - Ability to replace (overwrite) the repo if it already exists
|
||||||
|
by forcing (https://github.com/ansible-collections/kubernetes.core/issues/491).
|
||||||
|
- helm_repository - add support for pass-credentials cli parameter (https://github.com/ansible-collections/kubernetes.core/pull/282).
|
||||||
|
- helm_repository - added support for ``host``, ``api_key``, ``validate_certs``,
|
||||||
|
and ``ca_cert``.
|
||||||
|
- helm_repository - mark `pass_credentials` as no_log=True to silence false
|
||||||
|
warning (https://github.com/ansible-collections/kubernetes.core/issues/412).
|
||||||
|
- helm_template - add name (NAME of release) and disable_hook as optional module
|
||||||
|
arguments (https://github.com/ansible-collections/kubernetes.core/issues/313).
|
||||||
|
- helm_template - add show_only and release_namespace as module arguments (https://github.com/ansible-collections/kubernetes.core/issues/313).
|
||||||
|
- helm_template - add support for -set-file, -set-json, -set and -set-string
|
||||||
|
options when running helm template (https://github.com/ansible-collections/kubernetes.core/pull/546).
|
||||||
|
- k8s - add no_proxy support to k8s* (https://github.com/ansible-collections/kubernetes.core/pull/272).
|
||||||
|
- k8s - add support for server_side_apply. (https://github.com/ansible-collections/kubernetes.core/issues/87).
|
||||||
|
- k8s - add support for user impersonation. (https://github.com/ansible-collections/kubernetes/core/issues/40).
|
||||||
|
- k8s - allow resource definition using metadata.generateName (https://github.com/ansible-collections/kubernetes.core/issues/35).
|
||||||
|
- k8s lookup plugin - Enable turbo mode via environment variable (https://github.com/ansible-collections/kubernetes.core/issues/291).
|
||||||
|
- k8s, k8s_scale, k8s_service - add support for resource definition as manifest
|
||||||
|
via. (https://github.com/ansible-collections/kubernetes.core/issues/451).
|
||||||
|
- k8s_cp - remove dependency with 'find' executable on remote pod when state=from_pod
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/issues/486).
|
||||||
|
- k8s_drain - Adds ``delete_emptydir_data`` option to ``k8s_drain.delete_options``
|
||||||
|
to evict pods with an ``emptyDir`` volume attached (https://github.com/ansible-collections/kubernetes.core/pull/322).
|
||||||
|
- k8s_exec - select first container from the pod if none specified (https://github.com/ansible-collections/kubernetes.core/issues/358).
|
||||||
|
- k8s_exec - update deprecation warning for `return_code` (https://github.com/ansible-collections/kubernetes.core/issues/417).
|
||||||
|
- k8s_json_patch - minor typo fix in the example section (https://github.com/ansible-collections/kubernetes.core/issues/411).
|
||||||
|
- k8s_log - add the ``all_containers`` for retrieving all containers' logs in
|
||||||
|
the pod(s).
|
||||||
|
- k8s_log - added the `previous` parameter for retrieving the previously terminated
|
||||||
|
pod logs (https://github.com/ansible-collections/kubernetes.core/issues/437).
|
||||||
|
- k8s_log - added the `tail_lines` parameter to limit the number of lines to
|
||||||
|
be retrieved from the end of the logs (https://github.com/ansible-collections/kubernetes.core/issues/488).
|
||||||
|
- k8s_rollback - add support for check_mode. (https://github.com/ansible-collections/kubernetes/core/issues/243).
|
||||||
|
- k8s_scale - add support for check_mode. (https://github.com/ansible-collections/kubernetes/core/issues/244).
|
||||||
|
- kubectl - wait for dd command to complete before proceeding (https://github.com/ansible-collections/kubernetes.core/pull/321).
|
||||||
|
- kubectl.py - replace distutils.spawn.find_executable with shutil.which in
|
||||||
|
the kubectl connection plugin (https://github.com/ansible-collections/kubernetes.core/pull/456).
|
||||||
|
fragments:
|
||||||
|
- 0-copy_ignore_txt.yml
|
||||||
|
- 208-add-dependency-update.yaml
|
||||||
|
- 226-add-version-parameter-to-helm_plugin.yml
|
||||||
|
- 231-helm-add-timeout-parameter.yaml
|
||||||
|
- 238-helm-add-support-for-helm-uninstall-wait.yaml
|
||||||
|
- 238-k8s-add-support-for-generate_name.yml
|
||||||
|
- 245-add-dry-run.yaml
|
||||||
|
- 250-k8s-add-support-for-impersonation.yaml
|
||||||
|
- 253-dont-wait-on-list-resources.yaml
|
||||||
|
- 255-k8s_scale-k8s_rollback-add-support-for-check_mode.yml
|
||||||
|
- 260-k8s-add-support-for-server_side_apply.yml
|
||||||
|
- 272-k8s-add-support-no_proxy.yaml
|
||||||
|
- 282-helm-repository-add-pass-credentials.yaml
|
||||||
|
- 290-returns-diff-in-check-mode.yaml
|
||||||
|
- 295-fix-k8s-drain-variable-declaration.yaml
|
||||||
|
- 298-remove-binary-file.yaml
|
||||||
|
- 30-helm-add-post-renderer-support.yml
|
||||||
|
- 308-fix-for-common-non-ascii-characters-in-resources.yaml
|
||||||
|
- 313-helm-template-add-support-for-name-and-disablehook.yml
|
||||||
|
- 313-helm-template-add-support-for-show-only-and-release-namespace.yml
|
||||||
|
- 321-kubectl_sleep.yml
|
||||||
|
- 322-Add-delete_emptydir_data-to-drain-delete_options.yaml
|
||||||
|
- 335-k8s-lookup-add-support-for-turbo-mode.yml
|
||||||
|
- 347-routing.yml
|
||||||
|
- 348-helm_template-fix-precedence-of-release-values-over-values-files.yaml
|
||||||
|
- 358-k8s_exec.yml
|
||||||
|
- 364-use-resource-prefix.yaml
|
||||||
|
- 377-helm-info-state.yml
|
||||||
|
- 389-helm-add-support-chart_repo_url-on-helm_diff.yml
|
||||||
|
- 391-fix-statefulset-wait.yaml
|
||||||
|
- 411_k8s_json_patch.yml
|
||||||
|
- 412_pass_creds.yml
|
||||||
|
- 417_deprecation.yml
|
||||||
|
- 428-fix-kubeconfig-parameter-with-multiple-config-files.yaml
|
||||||
|
- 437-k8s-add-support-for-previous-logs.yaml
|
||||||
|
- 456-replace-distutils.yml
|
||||||
|
- 478-add-support-for-manifest-url.yaml
|
||||||
|
- 481-refactor-common.yml
|
||||||
|
- 488-add-support-for-tail-logs.yaml
|
||||||
|
- 493-k8s_log-fix-module-when-pod-does-exist.yaml
|
||||||
|
- 497-helm-add-support-for-in-memory-kubeconfig.yml
|
||||||
|
- 498-k8s-honor-aliases.yaml
|
||||||
|
- 505-add-from-yaml-all-example.yml
|
||||||
|
- 509-helm-repo-add-force_update-argument.yaml
|
||||||
|
- 512-k8s_cp-add-support-for-check_mode-update-command-for-listing-files-into-pod.yaml
|
||||||
|
- 515-update-sanity-for-2-15.yml
|
||||||
|
- 522-fix-helm-tests.yml
|
||||||
|
- 523-helm_info-get-all-values.yaml
|
||||||
|
- 528-k8s_log-support-all_containers-options.yml
|
||||||
|
- 532-k8s_crd-fix-integration-test.yml
|
||||||
|
- 546-helm-install-add-support-for-set-options.yaml
|
||||||
|
- 549-fix-server-side-apply.yaml
|
||||||
|
- 552-k8s_cp-fix-issue-when-copying-item-with-space-in-its-name.yml
|
||||||
|
- 561-fix-dry-run.yml
|
||||||
|
- 562-helm-fix-issue-when-alternative-kubeconfig-is-provided.yaml
|
||||||
|
- 571-k8s_info-fix-issue-with-api-server.yaml
|
||||||
|
- _wait_for_label_selector_optional.yaml
|
||||||
|
- disutils.version.yml
|
||||||
|
- exception.yml
|
||||||
|
- fix-ci-unit-tests.yaml
|
||||||
|
- helm_repository.yml
|
||||||
|
- ignore_2.14.yml
|
||||||
|
- k8s_config_resource_name-add-missing-documentation.yml
|
||||||
|
- k8s_rollback_reduce_tmeouts.yaml
|
||||||
|
- k8s_user_impersonation_k8s_1_24.yaml
|
||||||
|
- minor-tests-duration.yaml
|
||||||
|
modules:
|
||||||
|
- description: download a chart from a repository and (optionally) unpack it in
|
||||||
|
local directory.
|
||||||
|
name: helm_pull
|
||||||
|
namespace: ''
|
||||||
|
release_date: '2023-01-24'
|
||||||
|
3.0.0:
|
||||||
|
changes:
|
||||||
|
breaking_changes:
|
||||||
|
- Remove support for ansible-core < 2.14
|
||||||
|
- Update python kubernetes library to 24.2.0, helm/kind-action to 1.8.0, kubernetes
|
||||||
|
>= 1.24.
|
||||||
|
bugfixes:
|
||||||
|
- helm - Put the chart_ref into quotes when running ``helm show chart``, ``helm
|
||||||
|
upgrade`` and ``helm dependency update`` commands (https://github.com/ansible-collections/kubernetes.core/issues/653).
|
||||||
|
- helm - delete temporary file created when deploying chart with option ``release_values``
|
||||||
|
set (https://github.com/ansible-collections/kubernetes.core/issues/530).
|
||||||
|
- helm - fix issue occurring when uninstalling chart with statues others than
|
||||||
|
``deployed`` (https://github.com/ansible-collections/kubernetes.core/issues/319).
|
||||||
|
- helm - fix post_renderer argument breaking the helm deploy_command (https://github.com/ansible-collections/kubernetes.core/pull/586).
|
||||||
|
- helm - use post_renderer when checking ``changed`` status for a helm release
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/pull/588).
|
||||||
|
- k8s_scale - clean handling of ResourceTimeout exception (https://github.com/ansible-collections/kubernetes.core/issues/583).
|
||||||
|
- k8s_scale - fix issue when scaling StatefulSets with ``updateStrategy=OnDelete``
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/issues/579).
|
||||||
|
deprecated_features:
|
||||||
|
- k8s - the ``k8s`` inventory plugin has been deprecated and will be removed
|
||||||
|
in release 4.0.0 (https://github.com/ansible-collections/kubernetes.core/issues/31).
|
||||||
|
minor_changes:
|
||||||
|
- helm - add ``reuse_values`` and ``reset_values`` support to helm module (https://github.com/ansible-collections/kubernetes.core/issues/394).
|
||||||
|
- k8s - add new option ``delete_all`` to support deletion of all resources when
|
||||||
|
state is set to ``absent``. (https://github.com/ansible-collections/kubernetes.core/issues/504)
|
||||||
|
- k8s, k8s_info - add a hidden_fields option to allow fields to be hidden in
|
||||||
|
the results of k8s and k8s_info
|
||||||
|
- k8s_drain - add ability to filter the list of pods to be drained by a pod
|
||||||
|
label selector (https://github.com/ansible-collections/kubernetes.core/issues/474).
|
||||||
|
release_summary: This major release drops support for ansible-core versions
|
||||||
|
lower than 2.14, Python versions lower than 3.9 and updates python kubernetes
|
||||||
|
library to 24.2.0, helm/kind-action to 1.8.0, kubernetes >= 1.24, along with
|
||||||
|
bug fixes and minor changes.
|
||||||
|
fragments:
|
||||||
|
- 20230206-deprecate-k8s-inventory.yml
|
||||||
|
- 20231110-helm-quote-ref.yaml
|
||||||
|
- 517-k8s-make-name-optional.yaml
|
||||||
|
- 575-helm-add-support-for-reuse_values-and-reset_values.yml
|
||||||
|
- 579-k8s_scale-fix-issue-with-scaling-statefulsets.yml
|
||||||
|
- 583-k8s_scale-clean-handling-of-ResourceTimeout-exception.yaml
|
||||||
|
- 586-helm-fix-post-renderer-arg.yml
|
||||||
|
- 588-helm-use-post-renderer-for-helmdiff.yml
|
||||||
|
- 589-helm-uninstall-chart-releases-with-statuses-different-than-deployed.yaml
|
||||||
|
- 606-k8s_drain-add-pod_selectors-parameter.yaml
|
||||||
|
- 612-fix-helm-tests.yaml
|
||||||
|
- 629-add-hidden-fields-option.yaml
|
||||||
|
- gha-sanity-fixes.yaml
|
||||||
|
- helm-delete-temporary-file-created-when-using-option-release_values.yaml
|
||||||
|
- remove_ansible_2_13.yaml
|
||||||
|
- update_supported_versions.yaml
|
||||||
|
release_date: '2023-11-17'
|
||||||
|
3.0.1:
|
||||||
|
changes:
|
||||||
|
bugfixes:
|
||||||
|
- Resolve Collections util resource discovery fails when complex subresources
|
||||||
|
present (https://github.com/ansible-collections/kubernetes.core/pull/676).
|
||||||
|
- align `helmdiff_check()` function commandline rendering with the `deploy()`
|
||||||
|
function (https://github.com/ansible-collections/kubernetes.core/pull/670).
|
||||||
|
- 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).
|
||||||
|
release_summary: This release fixes issue with resources discovery when complex
|
||||||
|
subresources are present, and fixes issues with `reuse-values` parameter for
|
||||||
|
helm module.
|
||||||
|
fragments:
|
||||||
|
- 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
|
||||||
|
- 3.0.1.yml
|
||||||
|
release_date: '2024-03-01'
|
||||||
|
3.1.0:
|
||||||
|
changes:
|
||||||
|
bugfixes:
|
||||||
|
- helm - expand kubeconfig path with user's home directory for consistency with
|
||||||
|
k8s
|
||||||
|
- k8s_json_patch - rename action symlink to ensure k8s action plugin is used
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/pull/652).
|
||||||
|
minor_changes:
|
||||||
|
- kubectl - added support of local enviroment variable that will be used for
|
||||||
|
kubectl and may be requried for establishing connections ifself (https://github.com/ansible-collections/kubernetes.core/pull/702)
|
||||||
|
- kustomize - new parameter added to --enable-helm (https://github.com/ansible-collections/kubernetes.core/issues/568)
|
||||||
|
release_summary: This release comes with some bugfixes and documentation updates.
|
||||||
|
It also adds new features to the kubectl connection plugin and the kustomize
|
||||||
|
lookup plugin.
|
||||||
|
fragments:
|
||||||
|
- 20240426-add-support-of-kubectl-local-env-vars-for-connection-plugin.yml
|
||||||
|
- 3.1.0.yml
|
||||||
|
- 592-kustomize-helm-support.yml
|
||||||
|
- 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:
|
||||||
|
changes:
|
||||||
|
bugfixes:
|
||||||
|
- helm - Helm version checks did not support RC versions. They now accept any
|
||||||
|
version tags. (https://github.com/ansible-collections/kubernetes.core/pull/745).
|
||||||
|
- helm_pull - Apply no_log=True to pass_credentials to silence false positive
|
||||||
|
warning. (https://github.com/ansible-collections/kubernetes.core/pull/796).
|
||||||
|
- k8s_drain - Fix k8s_drain does not wait for single pod (https://github.com/ansible-collections/kubernetes.core/issues/769).
|
||||||
|
- k8s_drain - Fix k8s_drain runs into a timeout when evicting a pod which is
|
||||||
|
part of a stateful set (https://github.com/ansible-collections/kubernetes.core/issues/792).
|
||||||
|
- kubeconfig option should not appear in module invocation log (https://github.com/ansible-collections/kubernetes.core/issues/782).
|
||||||
|
- kustomize - kustomize plugin fails with deprecation warnings (https://github.com/ansible-collections/kubernetes.core/issues/639).
|
||||||
|
- waiter - Fix waiting for daemonset when desired number of pods is 0. (https://github.com/ansible-collections/kubernetes.core/pull/756).
|
||||||
|
minor_changes:
|
||||||
|
- k8s_drain - Improve error message for pod disruption budget when draining
|
||||||
|
a node (https://github.com/ansible-collections/kubernetes.core/issues/797).
|
||||||
|
release_summary: This release comes with improvements to the error messages
|
||||||
|
in the k8s_drain module and several bug fixes.
|
||||||
|
fragments:
|
||||||
|
- 20240530-ansible-core-support-update.yaml
|
||||||
|
- 20240611-helm-rc-version.yaml
|
||||||
|
- 20240620-fix-kustomize-plugin-fails-with-deprecation-warnings.yml
|
||||||
|
- 20241102-fix-ci-post-2.18-issue.yaml
|
||||||
|
- 20241213-kubeconfig-set-no_log-true.yaml
|
||||||
|
- 756-fix-daemonset-waiting.yaml
|
||||||
|
- 770-fix-k8s-drain-doesnt-wait-for-single-pod.yaml
|
||||||
|
- 793-fix-k8s-drain-runs-into-timeout.yaml
|
||||||
|
- 796-false-positive-helmull.yaml
|
||||||
|
- 798-drain-pdb-error-message.yaml
|
||||||
|
- readme_template_update.yml
|
||||||
|
release_date: '2025-01-20'
|
||||||
|
3.3.1:
|
||||||
|
changes:
|
||||||
|
release_summary: This release fixes the CI issues with the ``linters`` workflow.
|
||||||
|
fragments:
|
||||||
|
- release_summary.yml
|
||||||
|
release_date: '2025-03-26'
|
||||||
|
4.0.0:
|
||||||
|
changes:
|
||||||
|
bugfixes:
|
||||||
|
- Resolve Collections util resource discovery fails when complex subresources
|
||||||
|
present (https://github.com/ansible-collections/kubernetes.core/pull/676).
|
||||||
|
- align `helmdiff_check()` function commandline rendering with the `deploy()`
|
||||||
|
function (https://github.com/ansible-collections/kubernetes.core/pull/670).
|
||||||
|
- avoid unsafe conditions in integration tests (https://github.com/ansible-collections/kubernetes.core/pull/665).
|
||||||
|
- helm - use ``reuse-values`` when running ``helm diff`` command (https://github.com/ansible-collections/kubernetes.core/issues/680).
|
||||||
|
- integrations test helm_kubeconfig - set helm version to v3.10.3 to avoid incompatability
|
||||||
|
with new bitnami charts (https://github.com/ansible-collections/kubernetes.core/pull/670).
|
||||||
|
minor_changes:
|
||||||
|
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 5.0 (https://github.com/ansible-collections/kubernetes.core/pull/723).
|
||||||
|
- k8s - The module and K8sService were changed so warnings returned by the K8S
|
||||||
|
API are now displayed to the user.
|
||||||
|
release_summary: This major release brings several bug fixes. We have also removed
|
||||||
|
support for ``ansible-core<2.15`` and deprecated functions and class from
|
||||||
|
``module_utils/common.py``.
|
||||||
|
removed_features:
|
||||||
|
- k8s - Support for ``merge_type=json`` has been removed in version 4.0.0. Please
|
||||||
|
use ``kubernetes.core.k8s_json_patch`` instead (https://github.com/ansible-collections/kubernetes.core/pull/722).
|
||||||
|
- k8s_exec - the previously deprecated ``result.return_code`` return value has
|
||||||
|
been removed, consider using ``result.rc`` instead (https://github.com/ansible-collections/kubernetes.core/pull/726).
|
||||||
|
- module_utils/common.py - the previously deprecated ``K8sAnsibleMixin`` class
|
||||||
|
has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
|
||||||
|
- module_utils/common.py - the previously deprecated ``configuration_digest()``
|
||||||
|
function has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
|
||||||
|
- module_utils/common.py - the previously deprecated ``get_api_client()`` function
|
||||||
|
has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
|
||||||
|
- module_utils/common.py - the previously deprecated ``unique_string()`` function
|
||||||
|
has been removed (https://github.com/ansible-collections/kubernetes.core/pull/726).
|
||||||
|
fragments:
|
||||||
|
- 20231206-fix-unsafe-condition-in-integration.yml
|
||||||
|
- 20240117-fix-helm-diff-cmd-line-rendering.yml
|
||||||
|
- 20240222-Collections-util-resource-discovery-fails-when-complex-subresources-present.yml
|
||||||
|
- 20240228-fix-helm-diff-with-reuse-values.yml
|
||||||
|
- 20240423-k8s-display-warnings-to-users.yml
|
||||||
|
- 4.0.0.yaml
|
||||||
|
- inventory-update_removal_date.yml
|
||||||
|
- k8s-merge_type-removed.yml
|
||||||
|
- module_utils-common-remove-deprecated-functions-and-class.yaml
|
||||||
|
release_date: '2024-05-24'
|
||||||
|
5.0.0:
|
||||||
|
changes:
|
||||||
|
breaking_changes:
|
||||||
|
- Remove support for ``ansible-core<2.15`` (https://github.com/ansible-collections/kubernetes.core/pull/737).
|
||||||
|
minor_changes:
|
||||||
|
- connection/kubectl.py - Added an example of using the kubectl connection plugin
|
||||||
|
to the documentation (https://github.com/ansible-collections/kubernetes.core/pull/741).
|
||||||
|
- inventory/k8s.py - Defer removal of k8s inventory plugin to version 6.0.0
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/pull/734).
|
||||||
|
release_summary: This major release drops support for ``ansible-core<2.15``.
|
||||||
|
fragments:
|
||||||
|
- 20240530-ansible-core-support-update.yaml
|
||||||
|
- 20240530-defer-removal-and-ansible-core-support-update.yaml
|
||||||
|
- 5.0.0.yml
|
||||||
|
release_date: '2024-05-31'
|
||||||
|
5.1.0:
|
||||||
|
changes:
|
||||||
|
bugfixes:
|
||||||
|
- helm - Helm version checks did not support RC versions. They now accept any
|
||||||
|
version tags. (https://github.com/ansible-collections/kubernetes.core/pull/745).
|
||||||
|
- helm_pull - Apply no_log=True to pass_credentials to silence false positive
|
||||||
|
warning. (https://github.com/ansible-collections/kubernetes.core/pull/796).
|
||||||
|
- k8s_drain - Fix k8s_drain does not wait for single pod (https://github.com/ansible-collections/kubernetes.core/issues/769).
|
||||||
|
- k8s_drain - Fix k8s_drain runs into a timeout when evicting a pod which is
|
||||||
|
part of a stateful set (https://github.com/ansible-collections/kubernetes.core/issues/792).
|
||||||
|
- kubeconfig option should not appear in module invocation log (https://github.com/ansible-collections/kubernetes.core/issues/782).
|
||||||
|
- kustomize - kustomize plugin fails with deprecation warnings (https://github.com/ansible-collections/kubernetes.core/issues/639).
|
||||||
|
- waiter - Fix waiting for daemonset when desired number of pods is 0. (https://github.com/ansible-collections/kubernetes.core/pull/756).
|
||||||
|
minor_changes:
|
||||||
|
- Bump version of ``ansible-lint`` to minimum 24.7.0 (https://github.com/ansible-collections/kubernetes.core/pull/765).
|
||||||
|
- Parameter insecure_registry added to helm_template as equivalent of insecure-skip-tls-verify
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/pull/805).
|
||||||
|
- k8s_drain - Improve error message for pod disruption budget when draining
|
||||||
|
a node (https://github.com/ansible-collections/kubernetes.core/issues/797).
|
||||||
|
release_summary: This release came with new module ``helm_registry_auth``, improvements
|
||||||
|
to the error messages in the k8s_drain module, new parameter ``insecure_registry``
|
||||||
|
for ``helm_template`` module and several bug fixes.
|
||||||
|
fragments:
|
||||||
|
- 0-readme.yml
|
||||||
|
- 20240601-doc-example-of-using-kubectl.yaml
|
||||||
|
- 20240611-helm-rc-version.yaml
|
||||||
|
- 20240620-fix-kustomize-plugin-fails-with-deprecation-warnings.yml
|
||||||
|
- 20241102-fix-ci-post-2.18-issue.yaml
|
||||||
|
- 20241103-completly-remove-obsolate-communication-channel.yaml
|
||||||
|
- 20241207-add-insecure-skip-tls-verify-to-helm-template.yaml
|
||||||
|
- 20241213-kubeconfig-set-no_log-true.yaml
|
||||||
|
- 756-fix-daemonset-waiting.yaml
|
||||||
|
- 765-bump-ansible-lint-version.yml
|
||||||
|
- 770-fix-k8s-drain-doesnt-wait-for-single-pod.yaml
|
||||||
|
- 793-fix-k8s-drain-runs-into-timeout.yaml
|
||||||
|
- 796-false-positive-helmull.yaml
|
||||||
|
- 798-drain-pdb-error-message.yaml
|
||||||
|
- readme_template_update.yml
|
||||||
|
modules:
|
||||||
|
- description: Helm registry authentication module
|
||||||
|
name: helm_registry_auth
|
||||||
|
namespace: ''
|
||||||
|
release_date: '2025-01-20'
|
||||||
|
5.2.0:
|
||||||
|
changes:
|
||||||
|
minor_changes:
|
||||||
|
- k8s - Extend hidden_fields to allow the expression of more complex field types
|
||||||
|
to be hidden (https://github.com/ansible-collections/kubernetes.core/pull/872)
|
||||||
|
- k8s_info - Extend hidden_fields to allow the expression of more complex field
|
||||||
|
types to be hidden (https://github.com/ansible-collections/kubernetes.core/pull/872)
|
||||||
|
- 'waiter.py - add ClusterOperator support. The module can now check OpenShift
|
||||||
|
cluster health by verifying ClusterOperator status requiring ''Available:
|
||||||
|
True'', ''Degraded: False'', and ''Progressing: False'' for success. (https://github.com/ansible-collections/kubernetes.core/issues/869)'
|
||||||
|
release_summary: This release adds more functionality to the hidden_fields option
|
||||||
|
and support for waiting on ClusterOperators to reach a ready state.
|
||||||
|
fragments:
|
||||||
|
- 5.2.0.yml
|
||||||
|
- 643-extend-hidden-fields.yaml
|
||||||
|
- 879-clusteroperator-waiter.py.yaml
|
||||||
|
release_date: '2025-03-27'
|
||||||
|
5.3.0:
|
||||||
|
changes:
|
||||||
|
bugfixes:
|
||||||
|
- module_utils/k8s/service - fix issue when trying to delete resource using
|
||||||
|
`delete_options` and `check_mode=true` (https://github.com/ansible-collections/kubernetes.core/issues/892).
|
||||||
|
minor_changes:
|
||||||
|
- Bump version of ansible-lint to 25.1.2 (https://github.com/ansible-collections/kubernetes.core/pull/919).
|
||||||
|
- action/k8s_info - update templating mechanism with changes from ``ansible-core
|
||||||
|
2.19`` (https://github.com/ansible-collections/kubernetes.core/pull/888).
|
||||||
|
- helm - add reset_then_reuse_values support to helm module (https://github.com/ansible-collections/kubernetes.core/issues/803).
|
||||||
|
- helm - add support for ``insecure_skip_tls_verify`` option to helm and helm_repository(https://github.com/ansible-collections/kubernetes.core/issues/694).
|
||||||
|
release_summary: This release includes minor changes, bug fixes and also bumps
|
||||||
|
ansible-lint version to ``25.1.2``.
|
||||||
|
fragments:
|
||||||
|
- 20250324-k8s_info-templating.yaml
|
||||||
|
- 5.3.0.yml
|
||||||
|
- 694-add-insecure-skip-tls-verify.yml
|
||||||
|
- 800-helm-add-reset_then_reuse_values-support.yml
|
||||||
|
- 898-k8s-dont-delete-in-check-mode.yaml
|
||||||
|
- 919-update-ansible-lint-version.yaml
|
||||||
|
release_date: '2025-05-16'
|
||||||
|
5.4.0:
|
||||||
|
changes:
|
||||||
|
minor_changes:
|
||||||
|
- Module ``helm_registry_auth`` does not support idempotency with ``helm >= 3.18.0``
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/pull/946).
|
||||||
|
release_summary: This release updates the ``helm_registry_auth`` module to match the behavior of ``helm >= 3.18.0`` which reports a successful logout regardless of the current state (i.e., no idempotency).
|
||||||
|
fragments:
|
||||||
|
- 20250411-kubeconfig-no_log-revert.yaml
|
||||||
|
- 20250503-fix-unit-tests.yml
|
||||||
|
- 20250605-fix-helm_registry_auth-integration_test.yaml
|
||||||
|
- 5.4.0.yml
|
||||||
|
release_date: '2025-08-12'
|
||||||
|
5.4.1:
|
||||||
|
changes:
|
||||||
|
bugfixes:
|
||||||
|
- Remove ``ansible.module_utils.six`` imports to avoid warnings (https://github.com/ansible-collections/kubernetes.core/pull/998).
|
||||||
|
- Update the `k8s_cp` module to also work for init containers (https://github.com/ansible-collections/kubernetes.core/pull/971).
|
||||||
|
- module_utils/k8s/service - hide fields first before creating diffs (https://github.com/ansible-collections/kubernetes.core/pull/915).
|
||||||
|
release_summary: This release includes bugfixes for k8s service field handling,
|
||||||
|
k8s_cp init containers support, and removes deprecated ansible.module_utils.six
|
||||||
|
imports.
|
||||||
|
fragments:
|
||||||
|
- 20250428-k8s-service-hide-fields-first.yaml
|
||||||
|
- 20250731-fix-k8s_cp-initcontainers.yaml
|
||||||
|
- 20250922-remove-ansible-six-imports.yaml
|
||||||
|
- 5.4.1.yml
|
||||||
|
release_date: '2025-10-07'
|
||||||
|
6.0.0:
|
||||||
|
changes:
|
||||||
|
breaking_changes:
|
||||||
|
- Remove deprecated ``k8s`` invetory plugin (https://github.com/ansible-collections/kubernetes.core/pull/867).
|
||||||
|
- Remove support for ``ansible-core<2.16`` (https://github.com/ansible-collections/kubernetes.core/pull/867).
|
||||||
|
fragments:
|
||||||
|
- 20250121-breaking-changes-6.0.0.yml
|
||||||
|
release_date: '2025-05-19'
|
||||||
|
6.1.0:
|
||||||
|
changes:
|
||||||
|
bugfixes:
|
||||||
|
- module_utils/k8s/service - hide fields first before creating diffs (https://github.com/ansible-collections/kubernetes.core/pull/915).
|
||||||
|
minor_changes:
|
||||||
|
- Module helm_registry_auth do not support idempotency with `helm >= 3.18.0`
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/pull/946)
|
||||||
|
- Module k8s_json_patch - Add support for `hidden_fields` (https://github.com/ansible-collections/kubernetes.core/pull/964).
|
||||||
|
- helm - Parameter plain_http added for working with insecure OCI registries
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/pull/934).
|
||||||
|
- helm - Parameter take_ownership added (https://github.com/ansible-collections/kubernetes.core/pull/957).
|
||||||
|
- helm_pull - Parameter plain_http added for working with insecure OCI registries
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/pull/934).
|
||||||
|
- helm_template - Parameter plain_http added for working with insecure OCI registries
|
||||||
|
(https://github.com/ansible-collections/kubernetes.core/pull/934).
|
||||||
|
release_summary: "This release adds ``plain_http`` and ``take_ownership`` parameters
|
||||||
|
for helm modules, support for ``hidden_fields`` in ``k8s_json_patch``, documented
|
||||||
|
lack of idempotency support in ``helm_registry_auth`` with ``helm \u2265 3.18.0``,
|
||||||
|
and improved ``k8s_rollback`` test coverage."
|
||||||
|
fragments:
|
||||||
|
- 20250411-kubeconfig-no_log-revert.yaml
|
||||||
|
- 20250428-k8s-service-hide-fields-first.yaml
|
||||||
|
- 20250522-add-plain-http-for-oci-registries.yaml
|
||||||
|
- 20250605-fix-helm_registry_auth-integration_test.yaml
|
||||||
|
- 20250704-k8s-rollback-integration-test-coverage.yaml
|
||||||
|
- 20250720-k8s-patch-add-hidden-fields.yaml
|
||||||
|
- 20250911-add-support-helm-take-ownership.yaml
|
||||||
|
- release_summary.yml
|
||||||
|
release_date: '2025-08-12'
|
||||||
|
6.2.0:
|
||||||
|
changes:
|
||||||
|
bugfixes:
|
||||||
|
- Remove ``ansible.module_utils.six`` imports to avoid warnings (https://github.com/ansible-collections/kubernetes.core/pull/998).
|
||||||
|
- Update the `k8s_cp` module to also work for init containers (https://github.com/ansible-collections/kubernetes.core/pull/971).
|
||||||
|
minor_changes:
|
||||||
|
- Add support of skip-schema-validation in ``helm`` module (https://github.com/ansible-collections/kubernetes.core/pull/995)
|
||||||
|
- kustomize - Add support of local environ (https://github.com/ansible-collections/kubernetes.core/pull/786).
|
||||||
|
release_summary: This release adds minor changes and bugfixes, including support
|
||||||
|
of skip-schema-validation in ``helm`` module and removing deprecated
|
||||||
|
``ansible.module_utils.six`` imports.
|
||||||
|
|
||||||
|
fragments:
|
||||||
|
- 20241030-support-of-evrion-for-kustomize-lookup-plugin.yaml
|
||||||
|
- 20250731-fix-k8s_cp-initcontainers.yaml
|
||||||
|
- 20250916-skip-schema-validation.yaml
|
||||||
|
- 20250922-remove-ansible-six-imports.yaml
|
||||||
|
- 6_2_0.yml
|
||||||
|
release_date: '2025-10-07'
|
||||||
|
|||||||
@@ -1,138 +0,0 @@
|
|||||||
.. _ansible_turbo_mode:
|
|
||||||
|
|
||||||
|
|
||||||
******************
|
|
||||||
Ansible Turbo mode
|
|
||||||
******************
|
|
||||||
|
|
||||||
Following document provides overview of Ansible Turbo mode in ``kubernetes.core`` collection.
|
|
||||||
|
|
||||||
.. contents::
|
|
||||||
:local:
|
|
||||||
:depth: 1
|
|
||||||
|
|
||||||
|
|
||||||
Synopsis
|
|
||||||
--------
|
|
||||||
- A brief introduction about Ansible Turbo mode in ``kuberentes.core`` collection.
|
|
||||||
- Ansible Turbo mode is an optional performance optimization. It can be enabled by simply installing the cloud.common collection.
|
|
||||||
|
|
||||||
Requirements
|
|
||||||
------------
|
|
||||||
|
|
||||||
The following requirement is needed on the host that executes this module.
|
|
||||||
|
|
||||||
- The ``cloud.common`` collection (https://github.com/ansible-collections/cloud.common)
|
|
||||||
|
|
||||||
|
|
||||||
Installation
|
|
||||||
------------
|
|
||||||
|
|
||||||
You can install ``cloud.common`` collection using following command::
|
|
||||||
|
|
||||||
# ansible-galaxy collection install cloud.common
|
|
||||||
|
|
||||||
|
|
||||||
Current situation without Ansible Turbo mode
|
|
||||||
============================================
|
|
||||||
|
|
||||||
The traditional execution flow of an Ansible module includes the following steps:
|
|
||||||
|
|
||||||
- Upload of a ZIP archive with the module and its dependencies
|
|
||||||
- Execution of the module
|
|
||||||
- Ansible collects the results once the script is finished
|
|
||||||
|
|
||||||
These steps happen for each task of a playbook, and on every host.
|
|
||||||
|
|
||||||
Most of the time, the execution of a module is fast enough for
|
|
||||||
the user. However, sometime the module requires significant amount of time,
|
|
||||||
just to initialize itself. This is a common situation with the API based modules.
|
|
||||||
|
|
||||||
A classic initialization involves the following steps:
|
|
||||||
|
|
||||||
- Load a Python library to access the remote resource (via SDK)
|
|
||||||
- Open a client
|
|
||||||
- Load a bunch of Python modules.
|
|
||||||
- Request a new TCP connection.
|
|
||||||
- Create a session.
|
|
||||||
- Authenticate the client.
|
|
||||||
|
|
||||||
All these steps are time consuming and the same operations will be running again and again.
|
|
||||||
|
|
||||||
For instance, here:
|
|
||||||
|
|
||||||
- ``import openstack``: takes 0.569s
|
|
||||||
- ``client = openstack.connect()``: takes 0.065s
|
|
||||||
- ``client.authorize()``: takes 1.360s,
|
|
||||||
|
|
||||||
These numbers are from test running against VexxHost public cloud.
|
|
||||||
|
|
||||||
In this case, it's a 2s-ish overhead per task. If the playbook
|
|
||||||
comes with 10 tasks, the execution time cannot go below 20s.
|
|
||||||
|
|
||||||
How Ansible Turbo Module improve the situation
|
|
||||||
==============================================
|
|
||||||
|
|
||||||
``AnsibleTurboModule`` is actually a class that inherites from
|
|
||||||
the standard ``AnsibleModule`` class that your modules probably
|
|
||||||
already use.
|
|
||||||
The big difference is that when a module starts, it also spawns
|
|
||||||
a little Python daemon. If a daemon already exists, it will just
|
|
||||||
reuse it.
|
|
||||||
All the module logic is run inside this Python daemon. This means:
|
|
||||||
|
|
||||||
- Python modules are actually loaded one time
|
|
||||||
- Ansible module can reuse an existing authenticated session.
|
|
||||||
|
|
||||||
The background service
|
|
||||||
======================
|
|
||||||
|
|
||||||
The daemon kills itself after 15s, and communication are done
|
|
||||||
through an Unix socket.
|
|
||||||
It runs in one single process and uses ``asyncio`` internally.
|
|
||||||
Consequently you can use the ``sync`` keyword in your Ansible module.
|
|
||||||
This will be handy if you interact with a lot of remote systems
|
|
||||||
at the same time.
|
|
||||||
|
|
||||||
Security impact
|
|
||||||
===============
|
|
||||||
|
|
||||||
``ansible_module.turbo`` open an Unix socket to interact with the background service.
|
|
||||||
We use this service to open the connection toward the different target systems.
|
|
||||||
|
|
||||||
This is similar to what SSH does with the sockets.
|
|
||||||
|
|
||||||
Keep in mind that:
|
|
||||||
|
|
||||||
- All the modules can access the same cache. Soon an isolation will be done at the collection level (https://github.com/ansible-collections/cloud.common/pull/17)
|
|
||||||
- A task can load a different version of a library and impact the next tasks.
|
|
||||||
- If the same user runs two ``ansible-playbook`` at the same time, they will have access to the same cache.
|
|
||||||
|
|
||||||
When a module stores a session in a cache, it's a good idea to use a hash of the authentication information to identify the session.
|
|
||||||
|
|
||||||
Error management
|
|
||||||
================
|
|
||||||
|
|
||||||
``ansible_module.turbo`` uses exceptions to communicate a result back to the module.
|
|
||||||
|
|
||||||
- ``EmbeddedModuleFailure`` is raised when ``json_fail()`` is called.
|
|
||||||
- ``EmbeddedModuleSuccess`` is raised in case of success and returns the result to the origin module process.
|
|
||||||
|
|
||||||
These exceptions are defined in ``ansible_collections.cloud.common.plugins.module_utils.turbo.exceptions``.
|
|
||||||
You can raise ``EmbeddedModuleFailure`` exception yourself, for instance from a module in ``module_utils``.
|
|
||||||
|
|
||||||
.. note:: Be careful with the ``except Exception:`` blocks.
|
|
||||||
Not only they are bad practice, but also may interface with this
|
|
||||||
mechanism.
|
|
||||||
|
|
||||||
|
|
||||||
Troubleshooting
|
|
||||||
===============
|
|
||||||
|
|
||||||
You may want to manually start the server. This can be done with the following command:
|
|
||||||
|
|
||||||
.. code-block:: shell
|
|
||||||
|
|
||||||
PYTHONPATH=$HOME/.ansible/collections python -m ansible_collections.cloud.common.plugins.module_utils.turbo.server --socket-path $HOME/.ansible/tmp/turbo_mode.kubernetes.core.socket
|
|
||||||
|
|
||||||
You can use the ``--help`` argument to get a list of the optional parameters.
|
|
||||||
5
docs/docsite/extra-docs.yml
Normal file
5
docs/docsite/extra-docs.yml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
sections:
|
||||||
|
- title: Scenario Guide
|
||||||
|
toctree:
|
||||||
|
- scenario_guide
|
||||||
51
docs/docsite/rst/kubernetes_scenarios/k8s_intro.rst
Normal file
51
docs/docsite/rst/kubernetes_scenarios/k8s_intro.rst
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
.. _ansible_collections.kubernetes.core.docsite.k8s_ansible_intro:
|
||||||
|
|
||||||
|
**************************************
|
||||||
|
Introduction to Ansible for Kubernetes
|
||||||
|
**************************************
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:local:
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
============
|
||||||
|
|
||||||
|
The `kubernetes.core collection <https://galaxy.ansible.com/kubernetes/core>`_ offers several modules and plugins for orchestrating Kubernetes.
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
============
|
||||||
|
|
||||||
|
To use the modules, you'll need the following:
|
||||||
|
|
||||||
|
- Ansible 2.16.0 or latest installed
|
||||||
|
- `Kubernetes Python client <https://pypi.org/project/kubernetes/>`_ installed on the host that will execute the modules.
|
||||||
|
|
||||||
|
|
||||||
|
Installation
|
||||||
|
============
|
||||||
|
|
||||||
|
The Kubernetes modules are part of the Ansible Kubernetes collection.
|
||||||
|
|
||||||
|
To install the collection, run the following:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ ansible-galaxy collection install kubernetes.core
|
||||||
|
|
||||||
|
|
||||||
|
Authenticating with the API
|
||||||
|
===========================
|
||||||
|
|
||||||
|
By default the Kubernetes Rest Client will look for ``~/.kube/config``, and if found, connect using the active context. You can override the location of the file using the ``kubeconfig`` parameter, and the context, using the ``context`` parameter.
|
||||||
|
|
||||||
|
Basic authentication is also supported using the ``username`` and ``password`` options. You can override the URL using the ``host`` parameter. Certificate authentication works through the ``ssl_ca_cert``, ``cert_file``, and ``key_file`` parameters, and for token authentication, use the ``api_key`` parameter.
|
||||||
|
|
||||||
|
To disable SSL certificate verification, set ``verify_ssl`` to false.
|
||||||
|
|
||||||
|
Reporting an issue
|
||||||
|
==================
|
||||||
|
|
||||||
|
- If you find a bug or have a suggestion regarding modules or plugins, please file issues at `Ansible Kubernetes collection <https://github.com/ansible-collections/kubernetes.core/issues>`_.
|
||||||
|
- If you find a bug regarding Kubernetes Python client, please file issues at `Kubernetes Client issues <https://github.com/kubernetes-client/python/issues>`_.
|
||||||
|
- If you find a bug regarding Kubectl binary, please file issues at `Kubectl issue tracker <https://github.com/kubernetes/kubectl/issues>`_
|
||||||
|
- If you find a bug regarding Helm binary, please file issues at `Helm issue tracker <https://github.com/helm/helm/issues>`_.
|
||||||
12
docs/docsite/rst/kubernetes_scenarios/k8s_scenarios.rst
Normal file
12
docs/docsite/rst/kubernetes_scenarios/k8s_scenarios.rst
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
.. _ansible_collections.kubernetes.core.docsite.k8s_scenarios:
|
||||||
|
|
||||||
|
********************************
|
||||||
|
Ansible for Kubernetes Scenarios
|
||||||
|
********************************
|
||||||
|
|
||||||
|
These scenarios teach you how to accomplish common Kubernetes tasks using Ansible. To get started, please select the task you want to accomplish.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
scenario_k8s_object
|
||||||
175
docs/docsite/rst/kubernetes_scenarios/scenario_k8s_object.rst
Normal file
175
docs/docsite/rst/kubernetes_scenarios/scenario_k8s_object.rst
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
.. _ansible_collections.kubernetes.core.docsite.k8s_object_template:
|
||||||
|
|
||||||
|
*******************
|
||||||
|
Creating K8S object
|
||||||
|
*******************
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:local:
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
============
|
||||||
|
|
||||||
|
This guide will show you how to utilize Ansible to create Kubernetes objects such as Pods, Deployments, and Secrets.
|
||||||
|
|
||||||
|
Scenario Requirements
|
||||||
|
=====================
|
||||||
|
|
||||||
|
* Software
|
||||||
|
|
||||||
|
* Ansible 2.9.17 or later must be installed
|
||||||
|
|
||||||
|
* The Python module ``kubernetes`` must be installed on the Ansible controller (or Target host if not executing against localhost)
|
||||||
|
|
||||||
|
* Kubernetes Cluster
|
||||||
|
|
||||||
|
* Kubectl binary installed on the Ansible controller
|
||||||
|
|
||||||
|
|
||||||
|
* Access / Credentials
|
||||||
|
|
||||||
|
* Kubeconfig configured with the given Kubernetes cluster
|
||||||
|
|
||||||
|
|
||||||
|
Assumptions
|
||||||
|
===========
|
||||||
|
|
||||||
|
- User has required level of authorization to create, delete and update resources on the given Kubernetes cluster.
|
||||||
|
|
||||||
|
Caveats
|
||||||
|
=======
|
||||||
|
|
||||||
|
- community.kubernetes 2.0.0 has been renamed to `kubernetes.core <https://github.com/ansible-collections/kubernetes.core>`_
|
||||||
|
|
||||||
|
Example Description
|
||||||
|
===================
|
||||||
|
|
||||||
|
In this use case / example, we will create a Pod in the given Kubernetes Cluster. The following Ansible playbook showcases the basic parameters that are needed for this.
|
||||||
|
|
||||||
|
.. code:: yaml
|
||||||
|
|
||||||
|
---
|
||||||
|
- hosts: localhost
|
||||||
|
collections:
|
||||||
|
- kubernetes.core
|
||||||
|
tasks:
|
||||||
|
- name: Create a pod
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
state: present
|
||||||
|
definition:
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
metadata:
|
||||||
|
name: "utilitypod-1"
|
||||||
|
namespace: default
|
||||||
|
labels:
|
||||||
|
app: galaxy
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: utilitypod
|
||||||
|
image: busybox
|
||||||
|
|
||||||
|
Since Ansible utilizes the Kubernetes API to perform actions, in this use case we will be connecting directly to the Kubernetes cluster.
|
||||||
|
|
||||||
|
To begin, there are a few bits of information we will need. Here you are using Kubeconfig which is pre-configured in your machine. The Kubeconfig is generally located at ``~/.kube/config``. It is highly recommended to store sensitive information such as password, user certificates in a more secure fashion using :ref:`ansible-vault` or using `Ansible Tower credentials <https://docs.ansible.com/ansible-tower/latest/html/userguide/credentials.html>`_.
|
||||||
|
|
||||||
|
Now you need to supply the information about the Pod which will be created. Using ``definition`` parameter of the ``kubernetes.core.k8s`` module, you specify `PodTemplate <https://kubernetes.io/docs/concepts/workloads/pods/#pod-templates>`_. This PodTemplate is identical to what you provide to the ``kubectl`` command.
|
||||||
|
|
||||||
|
What to expect
|
||||||
|
--------------
|
||||||
|
|
||||||
|
- You will see a bit of JSON output after this playbook completes. This output shows various parameters that are returned from the module and from cluster about the newly created Pod.
|
||||||
|
|
||||||
|
.. code:: json
|
||||||
|
|
||||||
|
{
|
||||||
|
"changed": true,
|
||||||
|
"method": "create",
|
||||||
|
"result": {
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "Pod",
|
||||||
|
"metadata": {
|
||||||
|
"creationTimestamp": "2020-10-03T15:36:25Z",
|
||||||
|
"labels": {
|
||||||
|
"app": "galaxy"
|
||||||
|
},
|
||||||
|
"name": "utilitypod-1",
|
||||||
|
"namespace": "default",
|
||||||
|
"resourceVersion": "4511073",
|
||||||
|
"selfLink": "/api/v1/namespaces/default/pods/utilitypod-1",
|
||||||
|
"uid": "c7dec819-09df-4efd-9d78-67cf010b4f4e"
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"containers": [{
|
||||||
|
"image": "busybox",
|
||||||
|
"imagePullPolicy": "Always",
|
||||||
|
"name": "utilitypod",
|
||||||
|
"resources": {},
|
||||||
|
"terminationMessagePath": "/dev/termination-log",
|
||||||
|
"terminationMessagePolicy": "File",
|
||||||
|
"volumeMounts": [{
|
||||||
|
"mountPath": "/var/run/secrets/kubernetes.io/serviceaccount",
|
||||||
|
"name": "default-token-6j842",
|
||||||
|
"readOnly": true
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
"dnsPolicy": "ClusterFirst",
|
||||||
|
"enableServiceLinks": true,
|
||||||
|
"priority": 0,
|
||||||
|
"restartPolicy": "Always",
|
||||||
|
"schedulerName": "default-scheduler",
|
||||||
|
"securityContext": {},
|
||||||
|
"serviceAccount": "default",
|
||||||
|
"serviceAccountName": "default",
|
||||||
|
"terminationGracePeriodSeconds": 30,
|
||||||
|
"tolerations": [{
|
||||||
|
"effect": "NoExecute",
|
||||||
|
"key": "node.kubernetes.io/not-ready",
|
||||||
|
"operator": "Exists",
|
||||||
|
"tolerationSeconds": 300
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"effect": "NoExecute",
|
||||||
|
"key": "node.kubernetes.io/unreachable",
|
||||||
|
"operator": "Exists",
|
||||||
|
"tolerationSeconds": 300
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"volumes": [{
|
||||||
|
"name": "default-token-6j842",
|
||||||
|
"secret": {
|
||||||
|
"defaultMode": 420,
|
||||||
|
"secretName": "default-token-6j842"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"phase": "Pending",
|
||||||
|
"qosClass": "BestEffort"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- In the above example, 'changed' is ``True`` which notifies that the Pod creation started on the given cluster. This can take some time depending on your environment.
|
||||||
|
|
||||||
|
|
||||||
|
Troubleshooting
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Things to inspect
|
||||||
|
|
||||||
|
- Check if the values provided for username and password are correct
|
||||||
|
- Check if the Kubeconfig is populated with correct values
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
`Kubernetes Python client <https://github.com/kubernetes-client/python>`_
|
||||||
|
The GitHub Page of Kubernetes Python client
|
||||||
|
`Kubernetes Python client - Issue Tracker <https://github.com/kubernetes-client/python/issues>`_
|
||||||
|
The issue tracker for Kubernetes Python client
|
||||||
|
`Kubectl installation <https://kubernetes.io/docs/tasks/tools/install-kubectl/>`_
|
||||||
|
Installation guide for installing Kubectl
|
||||||
|
:ref:`working_with_playbooks`
|
||||||
|
An introduction to playbooks
|
||||||
|
:ref:`playbooks_vault`
|
||||||
|
Using Vault in playbooks
|
||||||
17
docs/docsite/rst/scenario_guide.rst
Normal file
17
docs/docsite/rst/scenario_guide.rst
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
.. _ansible_collections.kubernetes.core.docsite.scenario_guide:
|
||||||
|
|
||||||
|
Kubernetes Guide
|
||||||
|
================
|
||||||
|
|
||||||
|
Welcome to the Ansible for Kubernetes Guide!
|
||||||
|
|
||||||
|
The purpose of this guide is to teach you everything you need to know about using Ansible with Kubernetes.
|
||||||
|
|
||||||
|
To get started, please select one of the following topics.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
kubernetes_scenarios/k8s_intro
|
||||||
|
kubernetes_scenarios/k8s_scenarios
|
||||||
|
|
||||||
@@ -105,6 +105,27 @@ Parameters
|
|||||||
<div style="font-size: small; color: darkgreen"><br/>aliases: kube_context</div>
|
<div style="font-size: small; color: darkgreen"><br/>aliases: kube_context</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>get_all_values</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.4.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Set to <code>True</code> if you want to get all (computed) values of the release.</div>
|
||||||
|
<div>When <code>False</code> (default), only user supplied values are returned.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="1">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -127,7 +148,7 @@ Parameters
|
|||||||
<b>kubeconfig</b>
|
<b>kubeconfig</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">path</span>
|
<span style="color: purple">raw</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -135,6 +156,7 @@ Parameters
|
|||||||
<td>
|
<td>
|
||||||
<div>Helm option to specify kubeconfig path to use.</div>
|
<div>Helm option to specify kubeconfig path to use.</div>
|
||||||
<div>If the value is not specified in the task, the value of environment variable <code>K8S_AUTH_KUBECONFIG</code> will be used instead.</div>
|
<div>If the value is not specified in the task, the value of environment variable <code>K8S_AUTH_KUBECONFIG</code> will be used instead.</div>
|
||||||
|
<div>The configuration can be provided as dictionary. Added in version 2.4.0.</div>
|
||||||
<div style="font-size: small; color: darkgreen"><br/>aliases: kubeconfig_path</div>
|
<div style="font-size: small; color: darkgreen"><br/>aliases: kubeconfig_path</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -172,6 +194,32 @@ Parameters
|
|||||||
<div style="font-size: small; color: darkgreen"><br/>aliases: namespace</div>
|
<div style="font-size: small; color: darkgreen"><br/>aliases: namespace</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>release_state</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<b>Default:</b><br/><div style="color: blue">[]</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Show releases as per their states.</div>
|
||||||
|
<div>Default value is <code>deployed</code> and <code>failed</code>.</div>
|
||||||
|
<div>If set to <code>all</code>, show all releases without any filter applied.</div>
|
||||||
|
<div>If set to <code>deployed</code>, show deployed releases.</div>
|
||||||
|
<div>If set to <code>failed</code>, show failed releases.</div>
|
||||||
|
<div>If set to <code>pending</code>, show pending releases.</div>
|
||||||
|
<div>If set to <code>superseded</code>, show superseded releases.</div>
|
||||||
|
<div>If set to <code>uninstalled</code>, show uninstalled releases, if <code>helm uninstall --keep-history</code> was used.</div>
|
||||||
|
<div>If set to <code>uninstalling</code>, show releases that are currently being uninstalled.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="1">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -204,11 +252,18 @@ Examples
|
|||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
||||||
- name: Deploy latest version of Grafana chart inside monitoring namespace
|
- name: Gather information of Grafana chart inside monitoring namespace
|
||||||
kubernetes.core.helm_info:
|
kubernetes.core.helm_info:
|
||||||
name: test
|
name: test
|
||||||
release_namespace: monitoring
|
release_namespace: monitoring
|
||||||
|
|
||||||
|
- name: Gather information about test-chart with pending state
|
||||||
|
kubernetes.core.helm_info:
|
||||||
|
name: test-chart
|
||||||
|
release_namespace: testenv
|
||||||
|
release_state:
|
||||||
|
- pending
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Return Values
|
Return Values
|
||||||
@@ -270,6 +325,42 @@ Common return values are documented `here <https://docs.ansible.com/ansible/late
|
|||||||
<br/>
|
<br/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>hooks</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=dictionary</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.4.0</div>
|
||||||
|
</td>
|
||||||
|
<td>always</td>
|
||||||
|
<td>
|
||||||
|
<div>Hooks of the release</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>manifest</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=dictionary</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.4.0</div>
|
||||||
|
</td>
|
||||||
|
<td>always</td>
|
||||||
|
<td>
|
||||||
|
<div>Manifest of the release</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="elbow-placeholder"> </td>
|
<td class="elbow-placeholder"> </td>
|
||||||
<td colspan="1">
|
<td colspan="1">
|
||||||
@@ -302,6 +393,23 @@ Common return values are documented `here <https://docs.ansible.com/ansible/late
|
|||||||
<br/>
|
<br/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>notes</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.4.0</div>
|
||||||
|
</td>
|
||||||
|
<td>always</td>
|
||||||
|
<td>
|
||||||
|
<div>Notes of the release</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="elbow-placeholder"> </td>
|
<td class="elbow-placeholder"> </td>
|
||||||
<td colspan="1">
|
<td colspan="1">
|
||||||
|
|||||||
@@ -36,12 +36,12 @@ Parameters
|
|||||||
|
|
||||||
<table border=0 cellpadding=0 class="documentation-table">
|
<table border=0 cellpadding=0 class="documentation-table">
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="1">Parameter</th>
|
<th colspan="2">Parameter</th>
|
||||||
<th>Choices/<font color="blue">Defaults</font></th>
|
<th>Choices/<font color="blue">Defaults</font></th>
|
||||||
<th width="100%">Comments</th>
|
<th width="100%">Comments</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>api_key</b>
|
<b>api_key</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -57,7 +57,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>atomic</b>
|
<b>atomic</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -76,7 +76,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>binary_path</b>
|
<b>binary_path</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -91,7 +91,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>ca_cert</b>
|
<b>ca_cert</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -108,7 +108,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>chart_ref</b>
|
<b>chart_ref</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -127,7 +127,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>chart_repo_url</b>
|
<b>chart_repo_url</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -142,7 +142,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>chart_version</b>
|
<b>chart_version</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -157,7 +157,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>context</b>
|
<b>context</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -174,7 +174,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>create_namespace</b>
|
<b>create_namespace</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -194,7 +194,32 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>dependency_update</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.4.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Run standalone <code>helm dependency update CHART</code> before the operation.</div>
|
||||||
|
<div>Run inline <code>--dependency-update</code> with <code>helm install</code> command. This feature is not supported yet with the <code>helm upgrade</code> command.</div>
|
||||||
|
<div>So we should consider to use <em>dependency_update</em> options with <em>replace</em> option enabled when specifying <em>chart_repo_url</em>.</div>
|
||||||
|
<div>The <em>dependency_update</em> option require the add of <code>dependencies</code> block in <code>Chart.yaml/requirements.yaml</code> file.</div>
|
||||||
|
<div>For more information please visit <a href='https://helm.sh/docs/helm/helm_dependency/'>https://helm.sh/docs/helm/helm_dependency/</a></div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: dep_up</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>disable_hook</b>
|
<b>disable_hook</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -213,7 +238,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>force</b>
|
<b>force</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -232,7 +257,24 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>history_max</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">integer</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.2.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Limit the maximum number of revisions saved per release.</div>
|
||||||
|
<div>mutually exclusive with with <code>replace</code>.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>host</b>
|
<b>host</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -248,12 +290,35 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>insecure_skip_tls_verify</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 5.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Skip tls certificate checks for the chart download.</div>
|
||||||
|
<div>Do not confuse with the <code>validate_certs</code> option.</div>
|
||||||
|
<div>This option is only available for helm >= 3.16.0.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: skip_tls_certs_check</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>kubeconfig</b>
|
<b>kubeconfig</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">path</span>
|
<span style="color: purple">raw</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -261,11 +326,49 @@ Parameters
|
|||||||
<td>
|
<td>
|
||||||
<div>Helm option to specify kubeconfig path to use.</div>
|
<div>Helm option to specify kubeconfig path to use.</div>
|
||||||
<div>If the value is not specified in the task, the value of environment variable <code>K8S_AUTH_KUBECONFIG</code> will be used instead.</div>
|
<div>If the value is not specified in the task, the value of environment variable <code>K8S_AUTH_KUBECONFIG</code> will be used instead.</div>
|
||||||
|
<div>The configuration can be provided as dictionary. Added in version 2.4.0.</div>
|
||||||
<div style="font-size: small; color: darkgreen"><br/>aliases: kubeconfig_path</div>
|
<div style="font-size: small; color: darkgreen"><br/>aliases: kubeconfig_path</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>plain_http</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.1.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Use HTTP instead of HTTPS when working with OCI registries</div>
|
||||||
|
<div>Requires Helm >= 3.13.0</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>post_renderer</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.4.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Path to an executable to be used for post rendering.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>purge</b>
|
<b>purge</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -284,7 +387,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>release_name</b>
|
<b>release_name</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -301,7 +404,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>release_namespace</b>
|
<b>release_namespace</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -318,7 +421,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>release_state</b>
|
<b>release_state</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -338,7 +441,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>release_values</b>
|
<b>release_values</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -355,7 +458,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>replace</b>
|
<b>replace</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -373,10 +476,134 @@ Parameters
|
|||||||
<td>
|
<td>
|
||||||
<div>Reuse the given name, only if that name is a deleted release which remains in the history.</div>
|
<div>Reuse the given name, only if that name is a deleted release which remains in the history.</div>
|
||||||
<div>This is unsafe in production environment.</div>
|
<div>This is unsafe in production environment.</div>
|
||||||
|
<div>mutually exclusive with with <code>history_max</code>.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>reset_then_reuse_values</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.0.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>When upgrading package, reset the values to the ones built into the chart, apply the last release's values and merge in any overrides from parameters O(release_values), O(values_files) or O(set_values).</div>
|
||||||
|
<div>If O(reset_values) or O(reuse_values) is set to V(True), this is ignored.</div>
|
||||||
|
<div>This feature requires helm diff >= 3.9.12.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>reset_values</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li>no</li>
|
||||||
|
<li><div style="color: blue"><b>yes</b> ←</div></li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>When upgrading package, reset the values to the ones built into the chart.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>reuse_values</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li>no</li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>When upgrading package, specifies wether to reuse the last release's values and merge in any overrides from parameters <em>release_values</em>, <em>values_files</em> or <em>set_values</em>.</div>
|
||||||
|
<div>If <em>reset_values</em> is set to <code>True</code>, this is ignored.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>set_values</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=dictionary</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.4.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Values to pass to chart configuration</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
<td colspan="1">
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>value</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
/ <span style="color: red">required</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Value to pass to chart configuration (e.g phase=prod).</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>value_type</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">-</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>raw</b> ←</div></li>
|
||||||
|
<li>string</li>
|
||||||
|
<li>json</li>
|
||||||
|
<li>file</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Use <code>raw</code> set individual value.</div>
|
||||||
|
<div>Use <code>string</code> to force a string for an individual value.</div>
|
||||||
|
<div>Use <code>file</code> to set individual values from a file when the value itself is too long for the command line or is dynamically generated.</div>
|
||||||
|
<div>Use <code>json</code> to set json values (scalars/objects/arrays). This feature requires helm>=3.10.0.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>skip_crds</b>
|
<b>skip_crds</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -396,7 +623,67 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>skip_schema_validation</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.2.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Disables JSON schema validation for Chart and values.</div>
|
||||||
|
<div>This feature requires helm >= 3.16.0</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>take_ownership</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.1.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>When upgrading, Helm will ignore the check for helm annotations and take ownership of the existing resources</div>
|
||||||
|
<div>This feature requires helm >= 3.17.0</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>timeout</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>A Go duration (described here <em>https://pkg.go.dev/time#ParseDuration</em>) value to wait for Kubernetes commands to complete. This defaults to 5m0s.</div>
|
||||||
|
<div>similar to <code>wait_timeout</code> but does not required <code>wait</code> to be activated.</div>
|
||||||
|
<div>Mutually exclusive with <code>wait_timeout</code>.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>update_repo_cache</b>
|
<b>update_repo_cache</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -411,11 +698,11 @@ Parameters
|
|||||||
</ul>
|
</ul>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Run <code>helm repo update</code> before the operation. Can be run as part of the package installation or as a separate step.</div>
|
<div>Run <code>helm repo update</code> before the operation. Can be run as part of the package installation or as a separate step (see Examples).</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>validate_certs</b>
|
<b>validate_certs</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -436,7 +723,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>values_files</b>
|
<b>values_files</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -457,7 +744,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>wait</b>
|
<b>wait</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -472,11 +759,12 @@ Parameters
|
|||||||
</ul>
|
</ul>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful.</div>
|
<div>When <em>release_state</em> is set to <code>present</code>, wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful.</div>
|
||||||
|
<div>When <em>release_state</em> is set to <code>absent</code>, will wait until all the resources are deleted before returning. It will wait for as long as <em>wait_timeout</em>. This feature requires helm>=3.7.0. Added in version 2.3.0.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>wait_timeout</b>
|
<b>wait_timeout</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -488,12 +776,19 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Timeout when wait option is enabled (helm2 is a number of seconds, helm3 is a duration).</div>
|
<div>Timeout when wait option is enabled (helm2 is a number of seconds, helm3 is a duration).</div>
|
||||||
|
<div>The use of <em>wait_timeout</em> to wait for kubernetes commands to complete has been deprecated and will be removed after 2022-12-01.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
|
Notes
|
||||||
|
-----
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
- The default idempotency check can fail to report changes when ``release_state`` is set to ``present`` and ``chart_repo_url`` is defined. Install helm diff >= 3.4.1 for better results.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
@@ -543,6 +838,22 @@ Examples
|
|||||||
state: absent
|
state: absent
|
||||||
wait: true
|
wait: true
|
||||||
|
|
||||||
|
- name: Separately update the repository cache
|
||||||
|
kubernetes.core.helm:
|
||||||
|
name: dummy
|
||||||
|
namespace: kube-system
|
||||||
|
state: absent
|
||||||
|
update_repo_cache: true
|
||||||
|
|
||||||
|
- name: Deploy Grafana chart using set values on target
|
||||||
|
kubernetes.core.helm:
|
||||||
|
name: test
|
||||||
|
chart_ref: stable/grafana
|
||||||
|
release_namespace: monitoring
|
||||||
|
set_values:
|
||||||
|
- value: phase=prod
|
||||||
|
value_type: string
|
||||||
|
|
||||||
# From git
|
# From git
|
||||||
- name: Git clone stable repo on HEAD
|
- name: Git clone stable repo on HEAD
|
||||||
ansible.builtin.git:
|
ansible.builtin.git:
|
||||||
@@ -562,6 +873,12 @@ Examples
|
|||||||
chart_ref: "https://github.com/grafana/helm-charts/releases/download/grafana-5.6.0/grafana-5.6.0.tgz"
|
chart_ref: "https://github.com/grafana/helm-charts/releases/download/grafana-5.6.0/grafana-5.6.0.tgz"
|
||||||
release_namespace: monitoring
|
release_namespace: monitoring
|
||||||
|
|
||||||
|
- name: Deploy Bitnami's MongoDB latest chart from OCI registry
|
||||||
|
kubernetes.core.helm:
|
||||||
|
name: test
|
||||||
|
chart_ref: "oci://registry-1.docker.io/bitnamicharts/mongodb"
|
||||||
|
release_namespace: database
|
||||||
|
|
||||||
# Using complex Values
|
# Using complex Values
|
||||||
- name: Deploy new-relic client chart
|
- name: Deploy new-relic client chart
|
||||||
kubernetes.core.helm:
|
kubernetes.core.helm:
|
||||||
@@ -588,6 +905,17 @@ Examples
|
|||||||
logging:
|
logging:
|
||||||
enabled: True
|
enabled: True
|
||||||
|
|
||||||
|
# Deploy latest version
|
||||||
|
- name: Deploy latest version of Grafana chart using reuse_values
|
||||||
|
kubernetes.core.helm:
|
||||||
|
name: test
|
||||||
|
chart_ref: stable/grafana
|
||||||
|
release_namespace: monitoring
|
||||||
|
reuse_values: true
|
||||||
|
values:
|
||||||
|
replicas: 2
|
||||||
|
version: 3e8ec0b2dffa40fb97d5342e4af887de95faa8c61a62480dd7f8aa03dffcf533
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Return Values
|
Return Values
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ Parameters
|
|||||||
<b>kubeconfig</b>
|
<b>kubeconfig</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">path</span>
|
<span style="color: purple">raw</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -134,6 +134,7 @@ Parameters
|
|||||||
<td>
|
<td>
|
||||||
<div>Helm option to specify kubeconfig path to use.</div>
|
<div>Helm option to specify kubeconfig path to use.</div>
|
||||||
<div>If the value is not specified in the task, the value of environment variable <code>K8S_AUTH_KUBECONFIG</code> will be used instead.</div>
|
<div>If the value is not specified in the task, the value of environment variable <code>K8S_AUTH_KUBECONFIG</code> will be used instead.</div>
|
||||||
|
<div>The configuration can be provided as dictionary. Added in version 2.4.0.</div>
|
||||||
<div style="font-size: small; color: darkgreen"><br/>aliases: kubeconfig_path</div>
|
<div style="font-size: small; color: darkgreen"><br/>aliases: kubeconfig_path</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ Parameters
|
|||||||
<b>kubeconfig</b>
|
<b>kubeconfig</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">path</span>
|
<span style="color: purple">raw</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -134,6 +134,7 @@ Parameters
|
|||||||
<td>
|
<td>
|
||||||
<div>Helm option to specify kubeconfig path to use.</div>
|
<div>Helm option to specify kubeconfig path to use.</div>
|
||||||
<div>If the value is not specified in the task, the value of environment variable <code>K8S_AUTH_KUBECONFIG</code> will be used instead.</div>
|
<div>If the value is not specified in the task, the value of environment variable <code>K8S_AUTH_KUBECONFIG</code> will be used instead.</div>
|
||||||
|
<div>The configuration can be provided as dictionary. Added in version 2.4.0.</div>
|
||||||
<div style="font-size: small; color: darkgreen"><br/>aliases: kubeconfig_path</div>
|
<div style="font-size: small; color: darkgreen"><br/>aliases: kubeconfig_path</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -150,7 +151,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Name of Helm plugin.</div>
|
<div>Name of Helm plugin.</div>
|
||||||
<div>Required only if <code>state=absent</code>.</div>
|
<div>Required only if <code>state=absent</code> or <code>state=latest</code>.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -170,6 +171,23 @@ Parameters
|
|||||||
<div>Required only if <code>state=present</code>.</div>
|
<div>Required only if <code>state=present</code>.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>plugin_version</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Plugin version to install. If this is not specified, the latest version is installed.</div>
|
||||||
|
<div>Ignored when <code>state=absent</code> or <code>state=latest</code>.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="1">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -183,10 +201,12 @@ Parameters
|
|||||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
<li>absent</li>
|
<li>absent</li>
|
||||||
<li><div style="color: blue"><b>present</b> ←</div></li>
|
<li><div style="color: blue"><b>present</b> ←</div></li>
|
||||||
|
<li>latest</li>
|
||||||
</ul>
|
</ul>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>If <code>state=present</code> the Helm plugin will be installed.</div>
|
<div>If <code>state=present</code> the Helm plugin will be installed.</div>
|
||||||
|
<div>If <code>state=latest</code> the Helm plugin will be updated. Added in version 2.3.0.</div>
|
||||||
<div>If <code>state=absent</code> the Helm plugin will be removed.</div>
|
<div>If <code>state=absent</code> the Helm plugin will be removed.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -237,6 +257,17 @@ Examples
|
|||||||
plugin_name: env
|
plugin_name: env
|
||||||
state: absent
|
state: absent
|
||||||
|
|
||||||
|
- name: Install Helm plugin with a specific version
|
||||||
|
kubernetes.core.helm_plugin:
|
||||||
|
plugin_version: 2.0.1
|
||||||
|
plugin_path: https://domain/path/to/plugin.tar.gz
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Update Helm plugin
|
||||||
|
kubernetes.core.helm_plugin:
|
||||||
|
plugin_name: secrets
|
||||||
|
state: latest
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Return Values
|
Return Values
|
||||||
|
|||||||
489
docs/kubernetes.core.helm_pull_module.rst
Normal file
489
docs/kubernetes.core.helm_pull_module.rst
Normal file
@@ -0,0 +1,489 @@
|
|||||||
|
.. _kubernetes.core.helm_pull_module:
|
||||||
|
|
||||||
|
|
||||||
|
*************************
|
||||||
|
kubernetes.core.helm_pull
|
||||||
|
*************************
|
||||||
|
|
||||||
|
**download a chart from a repository and (optionally) unpack it in local directory.**
|
||||||
|
|
||||||
|
|
||||||
|
Version added: 2.4.0
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:local:
|
||||||
|
:depth: 1
|
||||||
|
|
||||||
|
|
||||||
|
Synopsis
|
||||||
|
--------
|
||||||
|
- Retrieve a package from a package repository, and download it locally.
|
||||||
|
- It can also be used to perform cryptographic verification of a chart without installing the chart.
|
||||||
|
- There are options for unpacking the chart after download.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
The below requirements are needed on the host that executes this module.
|
||||||
|
|
||||||
|
- helm >= 3.0 (https://github.com/helm/helm/releases)
|
||||||
|
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<table border=0 cellpadding=0 class="documentation-table">
|
||||||
|
<tr>
|
||||||
|
<th colspan="1">Parameter</th>
|
||||||
|
<th>Choices/<font color="blue">Defaults</font></th>
|
||||||
|
<th width="100%">Comments</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>binary_path</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The path of a helm binary to use.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>chart_ca_cert</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Verify certificates of HTTPS-enabled servers using this CA bundle.</div>
|
||||||
|
<div>Requires helm >= 3.1.0.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>chart_devel</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li>no</li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Use development versions, too. Equivalent to version '>0.0.0-0'.</div>
|
||||||
|
<div>Mutually exclusive with <code>chart_version</code>.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>chart_ref</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
/ <span style="color: red">required</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>chart name on chart repository.</div>
|
||||||
|
<div>absolute URL.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>chart_ssl_cert_file</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Identify HTTPS client using this SSL certificate file.</div>
|
||||||
|
<div>Requires helm >= 3.1.0.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>chart_ssl_key_file</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Identify HTTPS client using this SSL key file</div>
|
||||||
|
<div>Requires helm >= 3.1.0.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>chart_version</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Specify a version constraint for the chart version to use.</div>
|
||||||
|
<div>This constraint can be a specific tag (e.g. 1.1.1) or it may reference a valid range (e.g. ^2.0.0).</div>
|
||||||
|
<div>Mutually exclusive with <code>chart_devel</code>.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>destination</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
/ <span style="color: red">required</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>location to write the chart.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>pass_credentials</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Pass credentials to all domains.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>plain_http</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.1.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Use HTTP instead of HTTPS when working with OCI registries</div>
|
||||||
|
<div>Requires Helm >= 3.13.0</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>provenance</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Fetch the provenance file, but don't perform verification.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>repo_password</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Chart repository password where to locate the requested chart.</div>
|
||||||
|
<div>Required if <code>repo_username</code> is specified.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: password, chart_repo_password</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>repo_url</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>chart repository url where to locate the requested chart.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: url, chart_repo_url</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>repo_username</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Chart repository username where to locate the requested chart.</div>
|
||||||
|
<div>Required if <code>repo_password</code> is specified.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: username, chart_repo_username</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>skip_tls_certs_check</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Whether or not to check tls certificate for the chart download.</div>
|
||||||
|
<div>Requires helm >= 3.3.0. Alias <code>insecure_skip_tls_verify</code> added in 5.3.0.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: insecure_skip_tls_verify</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>untar_chart</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>if set to true, will untar the chart after downloading it.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>verify_chart</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Verify the package before using it.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>verify_chart_keyring</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>location of public keys used for verification.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
- name: Download chart using chart url
|
||||||
|
kubernetes.core.helm_pull:
|
||||||
|
chart_ref: https://github.com/grafana/helm-charts/releases/download/grafana-5.6.0/grafana-5.6.0.tgz
|
||||||
|
destination: /path/to/chart
|
||||||
|
|
||||||
|
- name: Download Chart using chart_name and repo_url
|
||||||
|
kubernetes.core.helm_pull:
|
||||||
|
chart_ref: redis
|
||||||
|
repo_url: https://charts.bitnami.com/bitnami
|
||||||
|
untar_chart: yes
|
||||||
|
destination: /path/to/chart
|
||||||
|
|
||||||
|
- name: Download Chart (skip tls certificate check)
|
||||||
|
kubernetes.core.helm_pull:
|
||||||
|
chart_ref: redis
|
||||||
|
repo_url: https://charts.bitnami.com/bitnami
|
||||||
|
untar_chart: yes
|
||||||
|
destination: /path/to/chart
|
||||||
|
skip_tls_certs_check: yes
|
||||||
|
|
||||||
|
- name: Download Chart using chart registry credentials
|
||||||
|
kubernetes.core.helm_pull:
|
||||||
|
chart_ref: redis
|
||||||
|
repo_url: https://charts.bitnami.com/bitnami
|
||||||
|
untar_chart: yes
|
||||||
|
destination: /path/to/chart
|
||||||
|
username: myuser
|
||||||
|
password: mypassword123
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Return Values
|
||||||
|
-------------
|
||||||
|
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<table border=0 cellpadding=0 class="documentation-table">
|
||||||
|
<tr>
|
||||||
|
<th colspan="1">Key</th>
|
||||||
|
<th>Returned</th>
|
||||||
|
<th width="100%">Description</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>command</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>always</td>
|
||||||
|
<td>
|
||||||
|
<div>Full `helm pull` command built by this module, in case you want to re-run the command outside the module or debug a problem.</div>
|
||||||
|
<br/>
|
||||||
|
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||||
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">helm pull --repo test ...</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>rc</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">integer</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>always</td>
|
||||||
|
<td>
|
||||||
|
<div>Helm pull command return code</div>
|
||||||
|
<br/>
|
||||||
|
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||||
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">1</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>stderr</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>always</td>
|
||||||
|
<td>
|
||||||
|
<div>Full `helm pull` command stderr, in case you want to display it or examine the event log</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>stdout</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>always</td>
|
||||||
|
<td>
|
||||||
|
<div>Full `helm pull` command stdout, in case you want to display it or examine the event log</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<br/><br/>
|
||||||
|
|
||||||
|
|
||||||
|
Status
|
||||||
|
------
|
||||||
|
|
||||||
|
|
||||||
|
Authors
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
- Aubin Bikouo (@abikouo)
|
||||||
333
docs/kubernetes.core.helm_registry_auth_module.rst
Normal file
333
docs/kubernetes.core.helm_registry_auth_module.rst
Normal file
@@ -0,0 +1,333 @@
|
|||||||
|
.. _kubernetes.core.helm_registry_auth_module:
|
||||||
|
|
||||||
|
|
||||||
|
**********************************
|
||||||
|
kubernetes.core.helm_registry_auth
|
||||||
|
**********************************
|
||||||
|
|
||||||
|
**Helm registry authentication module**
|
||||||
|
|
||||||
|
|
||||||
|
Version added: 5.1.0
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:local:
|
||||||
|
:depth: 1
|
||||||
|
|
||||||
|
|
||||||
|
Synopsis
|
||||||
|
--------
|
||||||
|
- Helm registry authentication module allows you to login ``helm registry login`` and logout ``helm registry logout`` from a Helm registry.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
The below requirements are needed on the host that executes this module.
|
||||||
|
|
||||||
|
- helm (https://github.com/helm/helm/releases) => 3.8.0
|
||||||
|
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<table border=0 cellpadding=0 class="documentation-table">
|
||||||
|
<tr>
|
||||||
|
<th colspan="1">Parameter</th>
|
||||||
|
<th>Choices/<font color="blue">Defaults</font></th>
|
||||||
|
<th width="100%">Comments</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>binary_path</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The path of a helm binary to use.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>ca_file</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Path to the CA certificate SSL file for verify registry server certificate.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>cert_file</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Path to the client certificate SSL file for identify registry client using this certificate file.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>host</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
/ <span style="color: red">required</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Provide a URL for accessing the registry.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: registry_url</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>insecure</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Allow connections to SSL sites without certs.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>key_file</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Path to the client key SSL file for identify registry client using this key file.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>password</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Password for the registry.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: repo_password</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>state</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>present</b> ←</div></li>
|
||||||
|
<li>absent</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Desired state of the registry.</div>
|
||||||
|
<div>If set to V(present) attempt to log in to the remote registry server using the URL specified in O(host).</div>
|
||||||
|
<div>If set to V(absent) attempt to log out from the remote registry server using the URL specified in O(host).</div>
|
||||||
|
<div>As helm >= 3.18.0 reports successful logout even if the user is not logged in, this module will report a change regardless of the current state.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>username</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Username for the registry.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: repo_username</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
- name: Login to remote registry
|
||||||
|
kubernetes.core.helm_registry_auth:
|
||||||
|
username: admin
|
||||||
|
password: "sample_password"
|
||||||
|
host: localhost:5000
|
||||||
|
|
||||||
|
- name: Logout from remote registry
|
||||||
|
kubernetes.core.helm_registry_auth:
|
||||||
|
state: absent
|
||||||
|
host: localhost:5000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Return Values
|
||||||
|
-------------
|
||||||
|
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<table border=0 cellpadding=0 class="documentation-table">
|
||||||
|
<tr>
|
||||||
|
<th colspan="1">Key</th>
|
||||||
|
<th>Returned</th>
|
||||||
|
<th width="100%">Description</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>command</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>always</td>
|
||||||
|
<td>
|
||||||
|
<div>Full <code>helm</code> command executed</div>
|
||||||
|
<br/>
|
||||||
|
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||||
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">/usr/local/bin/helm registry login oci-registry.domain.example --username=admin --password-stdin --insecure</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>failed</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>always</td>
|
||||||
|
<td>
|
||||||
|
<div>Indicate if the <code>helm</code> command failed</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>stderr</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>always</td>
|
||||||
|
<td>
|
||||||
|
<div>Full <code>helm</code> command stderr, in case you want to display it or examine the event log. Please be note that helm binnary may print messages to stderr even if the command is successful.</div>
|
||||||
|
<br/>
|
||||||
|
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||||
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">Login Succeeded\n</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>stderr_lines</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>always</td>
|
||||||
|
<td>
|
||||||
|
<div>Full <code>helm</code> command stderr, in case you want to display it or examine the event log</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>stdout</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>always</td>
|
||||||
|
<td>
|
||||||
|
<div>Full <code>helm</code> command stdout, in case you want to display it or examine the event log</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>stout_lines</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>always</td>
|
||||||
|
<td>
|
||||||
|
<div>Full <code>helm</code> command stdout, in case you want to display it or examine the event log</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<br/><br/>
|
||||||
|
|
||||||
|
|
||||||
|
Status
|
||||||
|
------
|
||||||
|
|
||||||
|
|
||||||
|
Authors
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
- Yuriy Novostavskiy (@yurnov)
|
||||||
@@ -40,6 +40,22 @@ Parameters
|
|||||||
<th>Choices/<font color="blue">Defaults</font></th>
|
<th>Choices/<font color="blue">Defaults</font></th>
|
||||||
<th width="100%">Comments</th>
|
<th width="100%">Comments</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>api_key</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Token used to authenticate with the API. Can also be specified via <code>K8S_AUTH_API_KEY</code> environment variable.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="1">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -55,6 +71,138 @@ Parameters
|
|||||||
<div>The path of a helm binary to use.</div>
|
<div>The path of a helm binary to use.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>ca_cert</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Path to a CA certificate used to authenticate with the API. The full certificate chain must be provided to avoid certificate validation errors. Can also be specified via <code>K8S_AUTH_SSL_CA_CERT</code> environment variable.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: ssl_ca_cert</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>context</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.4.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Helm option to specify which kubeconfig context to use.</div>
|
||||||
|
<div>If the value is not specified in the task, the value of environment variable <code>K8S_AUTH_CONTEXT</code> will be used instead.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: kube_context</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>force_update</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.4.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Whether or not to replace (overwrite) the repo if it already exists.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: force</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>host</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Provide a URL for accessing the API. Can also be specified via <code>K8S_AUTH_HOST</code> environment variable.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>insecure_skip_tls_verify</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 5.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Skip tls certificate checks for the repository url.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: skip_tls_certs_check</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>kubeconfig</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">raw</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.4.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Helm option to specify kubeconfig path to use.</div>
|
||||||
|
<div>If the value is not specified in the task, the value of environment variable <code>K8S_AUTH_KUBECONFIG</code> will be used instead.</div>
|
||||||
|
<div>The configuration can be provided as dictionary.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: kubeconfig_path</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>pass_credentials</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Pass credentials to all domains.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="1">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -142,6 +290,27 @@ Parameters
|
|||||||
<div style="font-size: small; color: darkgreen"><br/>aliases: username</div>
|
<div style="font-size: small; color: darkgreen"><br/>aliases: username</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>validate_certs</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li>no</li>
|
||||||
|
<li><div style="color: blue"><b>yes</b> ←</div></li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Whether or not to verify the API server's SSL certificates. Can also be specified via <code>K8S_AUTH_VERIFY_SSL</code> environment variable.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: verify_ssl</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
|
|||||||
@@ -28,12 +28,12 @@ Parameters
|
|||||||
|
|
||||||
<table border=0 cellpadding=0 class="documentation-table">
|
<table border=0 cellpadding=0 class="documentation-table">
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="1">Parameter</th>
|
<th colspan="2">Parameter</th>
|
||||||
<th>Choices/<font color="blue">Defaults</font></th>
|
<th>Choices/<font color="blue">Defaults</font></th>
|
||||||
<th width="100%">Comments</th>
|
<th width="100%">Comments</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>binary_path</b>
|
<b>binary_path</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -48,7 +48,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>chart_ref</b>
|
<b>chart_ref</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -67,7 +67,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>chart_repo_url</b>
|
<b>chart_repo_url</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -82,7 +82,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>chart_version</b>
|
<b>chart_version</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -97,7 +97,50 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>dependency_update</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.4.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Run helm dependency update before the operation.</div>
|
||||||
|
<div>The <em>dependency_update</em> option require the add of <code>dependencies</code> block in <code>Chart.yaml/requirements.yaml</code> file.</div>
|
||||||
|
<div>For more information please visit <a href='https://helm.sh/docs/helm/helm_dependency/'>https://helm.sh/docs/helm/helm_dependency/</a></div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: dep_up</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>disable_hook</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.4.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Prevent hooks from running during install.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>include_crds</b>
|
<b>include_crds</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -116,7 +159,27 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>insecure_registry</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 5.1.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Skip TLS certificate checks for the chart download</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>output_dir</b>
|
<b>output_dir</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -132,7 +195,61 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>plain_http</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.1.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Use HTTP instead of HTTPS when working with OCI registries</div>
|
||||||
|
<div>Requires Helm >= 3.13.0</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>release_name</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.4.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Release name to use in rendered templates.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: name</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>release_namespace</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.4.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>namespace scope for this request.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>release_values</b>
|
<b>release_values</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -149,7 +266,85 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>set_values</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=dictionary</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.4.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Values to pass to chart configuration.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
<td colspan="1">
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>value</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
/ <span style="color: red">required</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Value to pass to chart configuration (e.g phase=prod).</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>value_type</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">-</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>raw</b> ←</div></li>
|
||||||
|
<li>string</li>
|
||||||
|
<li>json</li>
|
||||||
|
<li>file</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Use <code>raw</code> set individual value.</div>
|
||||||
|
<div>Use <code>string</code> to force a string for an individual value.</div>
|
||||||
|
<div>Use <code>file</code> to set individual values from a file when the value itself is too long for the command line or is dynamically generated.</div>
|
||||||
|
<div>Use <code>json</code> to set json values (scalars/objects/arrays). This feature requires helm>=3.10.0.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>show_only</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.4.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<b>Default:</b><br/><div style="color: blue">[]</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Only show manifests rendered from the given templates.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>update_repo_cache</b>
|
<b>update_repo_cache</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -168,7 +363,7 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>values_files</b>
|
<b>values_files</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
@@ -213,6 +408,24 @@ Examples
|
|||||||
dest: myfile.yaml
|
dest: myfile.yaml
|
||||||
content: "{{ result.stdout }}"
|
content: "{{ result.stdout }}"
|
||||||
|
|
||||||
|
- name: Render MutatingWebhooksConfiguration for revision tag "canary", rev "1-13-0"
|
||||||
|
kubernetes.core.helm_template:
|
||||||
|
chart_ref: istio/istiod
|
||||||
|
chart_version: "1.13.0"
|
||||||
|
release_namespace: "istio-system"
|
||||||
|
show_only:
|
||||||
|
- "templates/revision-tags.yaml"
|
||||||
|
release_values:
|
||||||
|
revision: "1-13-0"
|
||||||
|
revisionTags:
|
||||||
|
- "canary"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Write templates to file
|
||||||
|
copy:
|
||||||
|
dest: myfile.yaml
|
||||||
|
content: "{{ result.stdout }}"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Return Values
|
Return Values
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ Requirements
|
|||||||
------------
|
------------
|
||||||
The below requirements are needed on the host that executes this module.
|
The below requirements are needed on the host that executes this module.
|
||||||
|
|
||||||
- python >= 3.6
|
- python >= 3.9
|
||||||
- kubernetes >= 12.0.0
|
- kubernetes >= 24.2.0
|
||||||
- PyYAML >= 3.11
|
- PyYAML >= 3.11
|
||||||
|
|
||||||
|
|
||||||
@@ -136,6 +136,41 @@ Parameters
|
|||||||
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_groups</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Group(s) to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_GROUPS environment. Example: Group1,Group2</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_user</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Username to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_USER environment.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -161,13 +196,34 @@ Parameters
|
|||||||
<b>kubeconfig</b>
|
<b>kubeconfig</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">path</span>
|
<span style="color: purple">raw</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
||||||
|
<div>Multiple Kubernetes config file can be provided using separator ';' for Windows platform or ':' for others platforms.</div>
|
||||||
|
<div>The kubernetes configuration can be provided as dictionary. This feature requires a python kubernetes client version >= 17.17.0. Added in version 2.2.0.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>no_proxy</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The comma separated list of hosts/domains/IP/CIDR that shouldn't go through proxy. Can also be specified via K8S_AUTH_NO_PROXY environment variable.</div>
|
||||||
|
<div>Please note that this module does not pick up typical proxy settings from the environment (e.g. NO_PROXY).</div>
|
||||||
|
<div>This feature requires kubernetes>=19.15.0. When kubernetes library is less than 19.15.0, it fails even no_proxy set in correct.</div>
|
||||||
|
<div>example value is "localhost,.local,.example.com,127.0.0.1,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
610
docs/kubernetes.core.k8s_cp_module.rst
Normal file
610
docs/kubernetes.core.k8s_cp_module.rst
Normal file
@@ -0,0 +1,610 @@
|
|||||||
|
.. _kubernetes.core.k8s_cp_module:
|
||||||
|
|
||||||
|
|
||||||
|
**********************
|
||||||
|
kubernetes.core.k8s_cp
|
||||||
|
**********************
|
||||||
|
|
||||||
|
**Copy files and directories to and from pod.**
|
||||||
|
|
||||||
|
|
||||||
|
Version added: 2.2.0
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:local:
|
||||||
|
:depth: 1
|
||||||
|
|
||||||
|
|
||||||
|
Synopsis
|
||||||
|
--------
|
||||||
|
- Use the Kubernetes Python client to copy files and directories to and from containers inside a pod.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
The below requirements are needed on the host that executes this module.
|
||||||
|
|
||||||
|
- python >= 3.9
|
||||||
|
- kubernetes >= 24.2.0
|
||||||
|
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<table border=0 cellpadding=0 class="documentation-table">
|
||||||
|
<tr>
|
||||||
|
<th colspan="2">Parameter</th>
|
||||||
|
<th>Choices/<font color="blue">Defaults</font></th>
|
||||||
|
<th width="100%">Comments</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>api_key</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Token used to authenticate with the API. Can also be specified via K8S_AUTH_API_KEY environment variable.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>ca_cert</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Path to a CA certificate used to authenticate with the API. The full certificate chain must be provided to avoid certificate validation errors. Can also be specified via K8S_AUTH_SSL_CA_CERT environment variable.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: ssl_ca_cert</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>client_cert</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Path to a certificate used to authenticate with the API. Can also be specified via K8S_AUTH_CERT_FILE environment variable.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: cert_file</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>client_key</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Path to a key file used to authenticate with the API. Can also be specified via K8S_AUTH_KEY_FILE environment variable.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: key_file</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>container</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The name of the container in the pod to copy files/directories from/to.</div>
|
||||||
|
<div>Defaults to the only container if there is only one container in the pod.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>content</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>When used instead of <em>local_path</em>, sets the contents of a local file directly to the specified value.</div>
|
||||||
|
<div>Works only when <em>remote_path</em> is a file. Creates the file if it does not exist.</div>
|
||||||
|
<div>For advanced formatting or if the content contains a variable, use the <span class='module'>ansible.builtin.template</span> module.</div>
|
||||||
|
<div>Mutually exclusive with <em>local_path</em>.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>context</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The name of a context found in the config file. Can also be specified via K8S_AUTH_CONTEXT environment variable.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>host</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_groups</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Group(s) to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_GROUPS environment. Example: Group1,Group2</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_user</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Username to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_USER environment.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>kubeconfig</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">raw</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
||||||
|
<div>Multiple Kubernetes config file can be provided using separator ';' for Windows platform or ':' for others platforms.</div>
|
||||||
|
<div>The kubernetes configuration can be provided as dictionary. This feature requires a python kubernetes client version >= 17.17.0. Added in version 2.2.0.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>local_path</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Path of the local file or directory.</div>
|
||||||
|
<div>Required when <em>state</em> is set to <code>from_pod</code>.</div>
|
||||||
|
<div>Mutually exclusive with <em>content</em>.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>namespace</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
/ <span style="color: red">required</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The pod namespace name.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>no_preserve</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The copied file/directory's ownership and permissions will not be preserved in the container.</div>
|
||||||
|
<div>This option is ignored when <em>content</em> is set or when <em>state</em> is set to <code>from_pod</code>.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>no_proxy</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The comma separated list of hosts/domains/IP/CIDR that shouldn't go through proxy. Can also be specified via K8S_AUTH_NO_PROXY environment variable.</div>
|
||||||
|
<div>Please note that this module does not pick up typical proxy settings from the environment (e.g. NO_PROXY).</div>
|
||||||
|
<div>This feature requires kubernetes>=19.15.0. When kubernetes library is less than 19.15.0, it fails even no_proxy set in correct.</div>
|
||||||
|
<div>example value is "localhost,.local,.example.com,127.0.0.1,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>password</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Provide a password for authenticating with the API. Can also be specified via K8S_AUTH_PASSWORD environment variable.</div>
|
||||||
|
<div>Please read the description of the <code>username</code> option for a discussion of when this option is applicable.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>persist_config</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li>no</li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Whether or not to save the kube config refresh tokens. Can also be specified via K8S_AUTH_PERSIST_CONFIG environment variable.</div>
|
||||||
|
<div>When the k8s context is using a user credentials with refresh tokens (like oidc or gke/gcloud auth), the token is refreshed by the k8s python client library but not saved by default. So the old refresh token can expire and the next auth might fail. Setting this flag to true will tell the k8s python client to save the new refresh token to the kube config file.</div>
|
||||||
|
<div>Default to false.</div>
|
||||||
|
<div>Please note that the current version of the k8s python client library does not support setting this flag to True yet.</div>
|
||||||
|
<div>The fix for this k8s python library is here: https://github.com/kubernetes-client/python-base/pull/169</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>pod</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
/ <span style="color: red">required</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The pod name.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>proxy</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The URL of an HTTP proxy to use for the connection. Can also be specified via K8S_AUTH_PROXY environment variable.</div>
|
||||||
|
<div>Please note that this module does not pick up typical proxy settings from the environment (e.g. HTTP_PROXY).</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>proxy_headers</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">dictionary</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.0.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The Header used for the HTTP proxy.</div>
|
||||||
|
<div>Documentation can be found here <a href='https://urllib3.readthedocs.io/en/latest/reference/urllib3.util.html?highlight=proxy_headers#urllib3.util.make_headers'>https://urllib3.readthedocs.io/en/latest/reference/urllib3.util.html?highlight=proxy_headers#urllib3.util.make_headers</a>.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>basic_auth</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Colon-separated username:password for basic authentication header.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_PROXY_HEADERS_BASIC_AUTH environment.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>proxy_basic_auth</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Colon-separated username:password for proxy basic authentication header.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_PROXY_HEADERS_PROXY_BASIC_AUTH environment.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>user_agent</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>String representing the user-agent you want, such as foo/1.0.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_PROXY_HEADERS_USER_AGENT environment.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>remote_path</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
/ <span style="color: red">required</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Path of the file or directory to copy.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>state</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>to_pod</b> ←</div></li>
|
||||||
|
<li>from_pod</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>When set to <code>to_pod</code>, the local <em>local_path</em> file or directory will be copied to <em>remote_path</em> into the pod.</div>
|
||||||
|
<div>When set to <code>from_pod</code>, the remote file or directory <em>remote_path</em> from pod will be copied locally to <em>local_path</em>.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>username</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Provide a username for authenticating with the API. Can also be specified via K8S_AUTH_USERNAME environment variable.</div>
|
||||||
|
<div>Please note that this only works with clusters configured to use HTTP Basic Auth. If your cluster has a different form of authentication (e.g. OAuth2 in OpenShift), this option will not work as expected and you should look into the <span class='module'>community.okd.k8s_auth</span> module, as that might do what you need.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>validate_certs</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li>no</li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Whether or not to verify the API server's SSL certificates. Can also be specified via K8S_AUTH_VERIFY_SSL environment variable.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: verify_ssl</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
|
Notes
|
||||||
|
-----
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
- the tar binary is required on the container when copying from local filesystem to pod.
|
||||||
|
- the (init) container has to be started before you copy files or directories to it.
|
||||||
|
- To avoid SSL certificate validation errors when ``validate_certs`` is *True*, the full certificate chain for the API server must be provided via ``ca_cert`` or in the kubeconfig file.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
# kubectl cp /tmp/foo some-namespace/some-pod:/tmp/bar
|
||||||
|
- name: Copy /tmp/foo local file to /tmp/bar in a remote pod
|
||||||
|
kubernetes.core.k8s_cp:
|
||||||
|
namespace: some-namespace
|
||||||
|
pod: some-pod
|
||||||
|
remote_path: /tmp/bar
|
||||||
|
local_path: /tmp/foo
|
||||||
|
|
||||||
|
# kubectl cp /tmp/foo_dir some-namespace/some-pod:/tmp/bar_dir
|
||||||
|
- name: Copy /tmp/foo_dir local directory to /tmp/bar_dir in a remote pod
|
||||||
|
kubernetes.core.k8s_cp:
|
||||||
|
namespace: some-namespace
|
||||||
|
pod: some-pod
|
||||||
|
remote_path: /tmp/bar_dir
|
||||||
|
local_path: /tmp/foo_dir
|
||||||
|
|
||||||
|
# kubectl cp /tmp/foo some-namespace/some-pod:/tmp/bar -c some-container
|
||||||
|
- name: Copy /tmp/foo local file to /tmp/bar in a remote pod in a specific container
|
||||||
|
kubernetes.core.k8s_cp:
|
||||||
|
namespace: some-namespace
|
||||||
|
pod: some-pod
|
||||||
|
container: some-container
|
||||||
|
remote_path: /tmp/bar
|
||||||
|
local_path: /tmp/foo
|
||||||
|
no_preserve: True
|
||||||
|
state: to_pod
|
||||||
|
|
||||||
|
# kubectl cp some-namespace/some-pod:/tmp/foo /tmp/bar
|
||||||
|
- name: Copy /tmp/foo from a remote pod to /tmp/bar locally
|
||||||
|
kubernetes.core.k8s_cp:
|
||||||
|
namespace: some-namespace
|
||||||
|
pod: some-pod
|
||||||
|
remote_path: /tmp/foo
|
||||||
|
local_path: /tmp/bar
|
||||||
|
state: from_pod
|
||||||
|
|
||||||
|
# copy content into a file in the remote pod
|
||||||
|
- name: Copy content into a file in the remote pod
|
||||||
|
kubernetes.core.k8s_cp:
|
||||||
|
state: to_pod
|
||||||
|
namespace: some-namespace
|
||||||
|
pod: some-pod
|
||||||
|
remote_path: /tmp/foo.txt
|
||||||
|
content: "This content will be copied into remote file"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Return Values
|
||||||
|
-------------
|
||||||
|
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<table border=0 cellpadding=0 class="documentation-table">
|
||||||
|
<tr>
|
||||||
|
<th colspan="1">Key</th>
|
||||||
|
<th>Returned</th>
|
||||||
|
<th width="100%">Description</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>result</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>message describing the copy operation successfully done.</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<br/><br/>
|
||||||
|
|
||||||
|
|
||||||
|
Status
|
||||||
|
------
|
||||||
|
|
||||||
|
|
||||||
|
Authors
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
- Aubin Bikouo (@abikouo)
|
||||||
666
docs/kubernetes.core.k8s_drain_module.rst
Normal file
666
docs/kubernetes.core.k8s_drain_module.rst
Normal file
@@ -0,0 +1,666 @@
|
|||||||
|
.. _kubernetes.core.k8s_drain_module:
|
||||||
|
|
||||||
|
|
||||||
|
*************************
|
||||||
|
kubernetes.core.k8s_drain
|
||||||
|
*************************
|
||||||
|
|
||||||
|
**Drain, Cordon, or Uncordon node in k8s cluster**
|
||||||
|
|
||||||
|
|
||||||
|
Version added: 2.2.0
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:local:
|
||||||
|
:depth: 1
|
||||||
|
|
||||||
|
|
||||||
|
Synopsis
|
||||||
|
--------
|
||||||
|
- Drain node in preparation for maintenance same as kubectl drain.
|
||||||
|
- Cordon will mark the node as unschedulable.
|
||||||
|
- Uncordon will mark the node as schedulable.
|
||||||
|
- The given node will be marked unschedulable to prevent new pods from arriving.
|
||||||
|
- Then drain deletes all pods except mirror pods (which cannot be deleted through the API server).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
The below requirements are needed on the host that executes this module.
|
||||||
|
|
||||||
|
- python >= 3.9
|
||||||
|
- kubernetes >= 24.2.0
|
||||||
|
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<table border=0 cellpadding=0 class="documentation-table">
|
||||||
|
<tr>
|
||||||
|
<th colspan="2">Parameter</th>
|
||||||
|
<th>Choices/<font color="blue">Defaults</font></th>
|
||||||
|
<th width="100%">Comments</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>api_key</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Token used to authenticate with the API. Can also be specified via K8S_AUTH_API_KEY environment variable.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>ca_cert</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Path to a CA certificate used to authenticate with the API. The full certificate chain must be provided to avoid certificate validation errors. Can also be specified via K8S_AUTH_SSL_CA_CERT environment variable.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: ssl_ca_cert</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>client_cert</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Path to a certificate used to authenticate with the API. Can also be specified via K8S_AUTH_CERT_FILE environment variable.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: cert_file</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>client_key</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Path to a key file used to authenticate with the API. Can also be specified via K8S_AUTH_KEY_FILE environment variable.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: key_file</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>context</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The name of a context found in the config file. Can also be specified via K8S_AUTH_CONTEXT environment variable.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>delete_options</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">dictionary</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<b>Default:</b><br/><div style="color: blue">{}</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Specify options to delete pods.</div>
|
||||||
|
<div>This option has effect only when <code>state</code> is set to <em>drain</em>.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>delete_emptydir_data</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Continue even if there are pods using emptyDir (local data that will be deleted when the node is drained).</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>disable_eviction</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Forces drain to use delete rather than evict.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>force</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Continue even if there are pods not managed by a ReplicationController, Job, or DaemonSet.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>ignore_daemonsets</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Ignore DaemonSet-managed pods.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>terminate_grace_period</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">integer</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Specify how many seconds to wait before forcefully terminating.</div>
|
||||||
|
<div>If not specified, the default grace period for the object type will be used.</div>
|
||||||
|
<div>The value zero indicates delete immediately.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>wait_sleep</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">integer</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<b>Default:</b><br/><div style="color: blue">5</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Number of seconds to sleep between checks.</div>
|
||||||
|
<div>Ignored if <code>wait_timeout</code> is not set.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>wait_timeout</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">integer</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The length of time to wait in seconds for pod to be deleted before giving up, zero means infinite.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>host</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_groups</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Group(s) to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_GROUPS environment. Example: Group1,Group2</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_user</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Username to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_USER environment.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>kubeconfig</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">raw</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
||||||
|
<div>Multiple Kubernetes config file can be provided using separator ';' for Windows platform or ':' for others platforms.</div>
|
||||||
|
<div>The kubernetes configuration can be provided as dictionary. This feature requires a python kubernetes client version >= 17.17.0. Added in version 2.2.0.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>name</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
/ <span style="color: red">required</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The name of the node.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>no_proxy</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The comma separated list of hosts/domains/IP/CIDR that shouldn't go through proxy. Can also be specified via K8S_AUTH_NO_PROXY environment variable.</div>
|
||||||
|
<div>Please note that this module does not pick up typical proxy settings from the environment (e.g. NO_PROXY).</div>
|
||||||
|
<div>This feature requires kubernetes>=19.15.0. When kubernetes library is less than 19.15.0, it fails even no_proxy set in correct.</div>
|
||||||
|
<div>example value is "localhost,.local,.example.com,127.0.0.1,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>password</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Provide a password for authenticating with the API. Can also be specified via K8S_AUTH_PASSWORD environment variable.</div>
|
||||||
|
<div>Please read the description of the <code>username</code> option for a discussion of when this option is applicable.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>persist_config</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li>no</li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Whether or not to save the kube config refresh tokens. Can also be specified via K8S_AUTH_PERSIST_CONFIG environment variable.</div>
|
||||||
|
<div>When the k8s context is using a user credentials with refresh tokens (like oidc or gke/gcloud auth), the token is refreshed by the k8s python client library but not saved by default. So the old refresh token can expire and the next auth might fail. Setting this flag to true will tell the k8s python client to save the new refresh token to the kube config file.</div>
|
||||||
|
<div>Default to false.</div>
|
||||||
|
<div>Please note that the current version of the k8s python client library does not support setting this flag to True yet.</div>
|
||||||
|
<div>The fix for this k8s python library is here: https://github.com/kubernetes-client/python-base/pull/169</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>pod_selectors</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Label selector to filter pods on the node.</div>
|
||||||
|
<div>This option has effect only when <code>state</code> is set to <em>drain</em>.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: label_selectors</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>proxy</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The URL of an HTTP proxy to use for the connection. Can also be specified via K8S_AUTH_PROXY environment variable.</div>
|
||||||
|
<div>Please note that this module does not pick up typical proxy settings from the environment (e.g. HTTP_PROXY).</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>proxy_headers</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">dictionary</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.0.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The Header used for the HTTP proxy.</div>
|
||||||
|
<div>Documentation can be found here <a href='https://urllib3.readthedocs.io/en/latest/reference/urllib3.util.html?highlight=proxy_headers#urllib3.util.make_headers'>https://urllib3.readthedocs.io/en/latest/reference/urllib3.util.html?highlight=proxy_headers#urllib3.util.make_headers</a>.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>basic_auth</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Colon-separated username:password for basic authentication header.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_PROXY_HEADERS_BASIC_AUTH environment.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>proxy_basic_auth</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Colon-separated username:password for proxy basic authentication header.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_PROXY_HEADERS_PROXY_BASIC_AUTH environment.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>user_agent</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>String representing the user-agent you want, such as foo/1.0.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_PROXY_HEADERS_USER_AGENT environment.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>state</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li>cordon</li>
|
||||||
|
<li><div style="color: blue"><b>drain</b> ←</div></li>
|
||||||
|
<li>uncordon</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Determines whether to drain, cordon, or uncordon node.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>username</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Provide a username for authenticating with the API. Can also be specified via K8S_AUTH_USERNAME environment variable.</div>
|
||||||
|
<div>Please note that this only works with clusters configured to use HTTP Basic Auth. If your cluster has a different form of authentication (e.g. OAuth2 in OpenShift), this option will not work as expected and you should look into the <span class='module'>community.okd.k8s_auth</span> module, as that might do what you need.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>validate_certs</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li>no</li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Whether or not to verify the API server's SSL certificates. Can also be specified via K8S_AUTH_VERIFY_SSL environment variable.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: verify_ssl</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
|
Notes
|
||||||
|
-----
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
- To avoid SSL certificate validation errors when ``validate_certs`` is *True*, the full certificate chain for the API server must be provided via ``ca_cert`` or in the kubeconfig file.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
- name: Drain node "foo", even if there are pods not managed by a ReplicationController, Job, or DaemonSet on it.
|
||||||
|
kubernetes.core.k8s_drain:
|
||||||
|
state: drain
|
||||||
|
name: foo
|
||||||
|
delete_options:
|
||||||
|
force: yes
|
||||||
|
|
||||||
|
- name: Drain node "foo", but abort if there are pods not managed by a ReplicationController, Job, or DaemonSet, and use a grace period of 15 minutes.
|
||||||
|
kubernetes.core.k8s_drain:
|
||||||
|
state: drain
|
||||||
|
name: foo
|
||||||
|
delete_options:
|
||||||
|
terminate_grace_period: 900
|
||||||
|
|
||||||
|
- name: Mark node "foo" as schedulable.
|
||||||
|
kubernetes.core.k8s_drain:
|
||||||
|
state: uncordon
|
||||||
|
name: foo
|
||||||
|
|
||||||
|
- name: Mark node "foo" as unschedulable.
|
||||||
|
kubernetes.core.k8s_drain:
|
||||||
|
state: cordon
|
||||||
|
name: foo
|
||||||
|
|
||||||
|
- name: Drain node "foo" using label selector to filter the list of pods to be drained.
|
||||||
|
kubernetes.core.k8s_drain:
|
||||||
|
state: drain
|
||||||
|
name: foo
|
||||||
|
pod_selectors:
|
||||||
|
- 'app!=csi-attacher'
|
||||||
|
- 'app!=csi-provisioner'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Return Values
|
||||||
|
-------------
|
||||||
|
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<table border=0 cellpadding=0 class="documentation-table">
|
||||||
|
<tr>
|
||||||
|
<th colspan="1">Key</th>
|
||||||
|
<th>Returned</th>
|
||||||
|
<th width="100%">Description</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>result</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>The node status and the number of pods deleted.</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<br/><br/>
|
||||||
|
|
||||||
|
|
||||||
|
Status
|
||||||
|
------
|
||||||
|
|
||||||
|
|
||||||
|
Authors
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
- Aubin Bikouo (@abikouo)
|
||||||
@@ -25,8 +25,8 @@ Requirements
|
|||||||
------------
|
------------
|
||||||
The below requirements are needed on the host that executes this module.
|
The below requirements are needed on the host that executes this module.
|
||||||
|
|
||||||
- python >= 3.6
|
- python >= 3.9
|
||||||
- kubernetes >= 12.0.0
|
- kubernetes >= 24.2.0
|
||||||
- PyYAML >= 3.11
|
- PyYAML >= 3.11
|
||||||
|
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ Parameters
|
|||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>The command to execute</div>
|
<div>The command to execute.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -134,6 +134,7 @@ Parameters
|
|||||||
<td>
|
<td>
|
||||||
<div>The name of the container in the pod to connect to.</div>
|
<div>The name of the container in the pod to connect to.</div>
|
||||||
<div>Defaults to only container if there is only one container in the pod.</div>
|
<div>Defaults to only container if there is only one container in the pod.</div>
|
||||||
|
<div>If not specified, will choose the first container from the given pod as kubectl cmdline does.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -166,19 +167,56 @@ Parameters
|
|||||||
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_groups</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Group(s) to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_GROUPS environment. Example: Group1,Group2</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_user</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Username to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_USER environment.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>kubeconfig</b>
|
<b>kubeconfig</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">path</span>
|
<span style="color: purple">raw</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
||||||
|
<div>Multiple Kubernetes config file can be provided using separator ';' for Windows platform or ':' for others platforms.</div>
|
||||||
|
<div>The kubernetes configuration can be provided as dictionary. This feature requires a python kubernetes client version >= 17.17.0. Added in version 2.2.0.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -194,7 +232,26 @@ Parameters
|
|||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>The pod namespace name</div>
|
<div>The pod namespace name.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>no_proxy</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The comma separated list of hosts/domains/IP/CIDR that shouldn't go through proxy. Can also be specified via K8S_AUTH_NO_PROXY environment variable.</div>
|
||||||
|
<div>Please note that this module does not pick up typical proxy settings from the environment (e.g. NO_PROXY).</div>
|
||||||
|
<div>This feature requires kubernetes>=19.15.0. When kubernetes library is less than 19.15.0, it fails even no_proxy set in correct.</div>
|
||||||
|
<div>example value is "localhost,.local,.example.com,127.0.0.1,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -249,7 +306,7 @@ Parameters
|
|||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>The pod name</div>
|
<div>The pod name.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -266,7 +323,7 @@ Parameters
|
|||||||
<td>
|
<td>
|
||||||
<div>The URL of an HTTP proxy to use for the connection.</div>
|
<div>The URL of an HTTP proxy to use for the connection.</div>
|
||||||
<div>Can also be specified via <em>K8S_AUTH_PROXY</em> environment variable.</div>
|
<div>Can also be specified via <em>K8S_AUTH_PROXY</em> environment variable.</div>
|
||||||
<div>Please note that this module does not pick up typical proxy settings from the environment (e.g. HTTP_PROXY).</div>
|
<div>Please note that this module does not pick up typical proxy settings from the environment (for example, HTTP_PROXY).</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -382,6 +439,7 @@ Notes
|
|||||||
-----
|
-----
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
- Return code ``rc`` for the command executed is added in output in version 2.2.0, and deprecates return code ``return_code``.
|
||||||
- Return code ``return_code`` for the command executed is added in output in version 1.0.0.
|
- Return code ``return_code`` for the command executed is added in output in version 1.0.0.
|
||||||
- The authenticated user must have at least read access to the pods resource and write access to the pods/exec resource.
|
- The authenticated user must have at least read access to the pods resource and write access to the pods/exec resource.
|
||||||
- To avoid SSL certificate validation errors when ``validate_certs`` is *True*, the full certificate chain for the API server must be provided via ``ca_cert`` or in the kubeconfig file.
|
- To avoid SSL certificate validation errors when ``validate_certs`` is *True*, the full certificate chain for the API server must be provided via ``ca_cert`` or in the kubeconfig file.
|
||||||
@@ -410,7 +468,14 @@ Examples
|
|||||||
- name: Check last command status
|
- name: Check last command status
|
||||||
debug:
|
debug:
|
||||||
msg: "cmd failed"
|
msg: "cmd failed"
|
||||||
when: command_status.return_code != 0
|
when: command_status.rc != 0
|
||||||
|
|
||||||
|
- name: Specify a container name to execute the command on
|
||||||
|
kubernetes.core.k8s_exec:
|
||||||
|
namespace: myproject
|
||||||
|
pod: busybox-test
|
||||||
|
container: manager
|
||||||
|
command: echo "hello"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -443,6 +508,23 @@ Common return values are documented `here <https://docs.ansible.com/ansible/late
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="elbow-placeholder"> </td>
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>rc</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">integer</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.2.0</div>
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
<td>
|
||||||
|
<div>The command status code</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
<td colspan="1">
|
<td colspan="1">
|
||||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
<b>return_code</b>
|
<b>return_code</b>
|
||||||
@@ -453,7 +535,7 @@ Common return values are documented `here <https://docs.ansible.com/ansible/late
|
|||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td>
|
<td>
|
||||||
<div>The command status code</div>
|
<div>The command status code. This attribute is deprecated and will be removed in a future release. Please use rc instead.</div>
|
||||||
<br/>
|
<br/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ Requirements
|
|||||||
------------
|
------------
|
||||||
The below requirements are needed on the host that executes this module.
|
The below requirements are needed on the host that executes this module.
|
||||||
|
|
||||||
- python >= 3.6
|
- python >= 3.9
|
||||||
- kubernetes >= 12.0.0
|
- kubernetes >= 24.2.0
|
||||||
- PyYAML >= 3.11
|
- PyYAML >= 3.11
|
||||||
|
|
||||||
|
|
||||||
@@ -153,11 +153,30 @@ Parameters
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
<b>Default:</b><br/><div style="color: blue">[]</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>List of field selectors to use to filter results</div>
|
<div>List of field selectors to use to filter results</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>hidden_fields</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Hide fields matching any of the field definitions in the result</div>
|
||||||
|
<div>An example might be <code>hidden_fields=[metadata.managedFields]</code> or V(hidden_fields=[spec.containers[0].env[3].value]) or V(hidden_fields=[metadata.annotations[kubectl.kubernetes.io/last-applied-configuration]])</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -173,6 +192,41 @@ Parameters
|
|||||||
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_groups</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Group(s) to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_GROUPS environment. Example: Group1,Group2</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_user</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Username to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_USER environment.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -198,13 +252,15 @@ Parameters
|
|||||||
<b>kubeconfig</b>
|
<b>kubeconfig</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">path</span>
|
<span style="color: purple">raw</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
||||||
|
<div>Multiple Kubernetes config file can be provided using separator ';' for Windows platform or ':' for others platforms.</div>
|
||||||
|
<div>The kubernetes configuration can be provided as dictionary. This feature requires a python kubernetes client version >= 17.17.0. Added in version 2.2.0.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -218,6 +274,7 @@ Parameters
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
<b>Default:</b><br/><div style="color: blue">[]</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>List of label selectors to use to filter results</div>
|
<div>List of label selectors to use to filter results</div>
|
||||||
@@ -259,6 +316,25 @@ Parameters
|
|||||||
<div>If <em>resource definition</em> is provided, the <em>metadata.namespace</em> value from the <em>resource_definition</em> will override this option.</div>
|
<div>If <em>resource definition</em> is provided, the <em>metadata.namespace</em> value from the <em>resource_definition</em> will override this option.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>no_proxy</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The comma separated list of hosts/domains/IP/CIDR that shouldn't go through proxy. Can also be specified via K8S_AUTH_NO_PROXY environment variable.</div>
|
||||||
|
<div>Please note that this module does not pick up typical proxy settings from the environment (e.g. NO_PROXY).</div>
|
||||||
|
<div>This feature requires kubernetes>=19.15.0. When kubernetes library is less than 19.15.0, it fails even no_proxy set in correct.</div>
|
||||||
|
<div>example value is "localhost,.local,.example.com,127.0.0.1,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
|||||||
@@ -1,359 +0,0 @@
|
|||||||
.. _kubernetes.core.k8s_inventory:
|
|
||||||
|
|
||||||
|
|
||||||
*******************
|
|
||||||
kubernetes.core.k8s
|
|
||||||
*******************
|
|
||||||
|
|
||||||
**Kubernetes (K8s) inventory source**
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. contents::
|
|
||||||
:local:
|
|
||||||
:depth: 1
|
|
||||||
|
|
||||||
|
|
||||||
Synopsis
|
|
||||||
--------
|
|
||||||
- Fetch containers and services for one or more clusters.
|
|
||||||
- Groups by cluster name, namespace, namespace_services, namespace_pods, and labels.
|
|
||||||
- Uses the kubectl connection plugin to access the Kubernetes cluster.
|
|
||||||
- Uses k8s.(yml|yaml) YAML configuration file to set parameter values.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Requirements
|
|
||||||
------------
|
|
||||||
The below requirements are needed on the local Ansible controller node that executes this inventory.
|
|
||||||
|
|
||||||
- python >= 3.6
|
|
||||||
- kubernetes >= 12.0.0
|
|
||||||
- PyYAML >= 3.11
|
|
||||||
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<table border=0 cellpadding=0 class="documentation-table">
|
|
||||||
<tr>
|
|
||||||
<th colspan="2">Parameter</th>
|
|
||||||
<th>Choices/<font color="blue">Defaults</font></th>
|
|
||||||
<th>Configuration</th>
|
|
||||||
<th width="100%">Comments</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>connections</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">-</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Optional list of cluster connection settings. If no connections are provided, the default <em>~/.kube/config</em> and active context will be used, and objects will be returned for all namespaces the active user is authorized to access.</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="elbow-placeholder"></td>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>api_key</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">-</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Token used to authenticate with the API. Can also be specified via K8S_AUTH_API_KEY environment variable.</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="elbow-placeholder"></td>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>ca_cert</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">-</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Path to a CA certificate used to authenticate with the API. Can also be specified via K8S_AUTH_SSL_CA_CERT environment variable.</div>
|
|
||||||
<div style="font-size: small; color: darkgreen"><br/>aliases: ssl_ca_cert</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="elbow-placeholder"></td>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>client_cert</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">-</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Path to a certificate used to authenticate with the API. Can also be specified via K8S_AUTH_CERT_FILE environment variable.</div>
|
|
||||||
<div style="font-size: small; color: darkgreen"><br/>aliases: cert_file</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="elbow-placeholder"></td>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>client_key</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">-</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Path to a key file used to authenticate with the API. Can also be specified via K8S_AUTH_KEY_FILE environment variable.</div>
|
|
||||||
<div style="font-size: small; color: darkgreen"><br/>aliases: key_file</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="elbow-placeholder"></td>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>context</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">-</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>The name of a context found in the config file. Can also be specified via K8S_AUTH_CONTEXT environment variable.</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="elbow-placeholder"></td>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>host</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">-</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="elbow-placeholder"></td>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>kubeconfig</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">-</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="elbow-placeholder"></td>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>name</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">-</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Optional name to assign to the cluster. If not provided, a name is constructed from the server and port.</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="elbow-placeholder"></td>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>namespaces</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">-</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>List of namespaces. If not specified, will fetch all containers for all namespaces user is authorized to access.</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="elbow-placeholder"></td>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>password</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">-</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Provide a password for authenticating with the API. Can also be specified via K8S_AUTH_PASSWORD environment variable.</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="elbow-placeholder"></td>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>username</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">-</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Provide a username for authenticating with the API. Can also be specified via K8S_AUTH_USERNAME environment variable.</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="elbow-placeholder"></td>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>validate_certs</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">boolean</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
|
||||||
<li>no</li>
|
|
||||||
<li>yes</li>
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>Whether or not to verify the API server's SSL certificates. Can also be specified via K8S_AUTH_VERIFY_SSL environment variable.</div>
|
|
||||||
<div style="font-size: small; color: darkgreen"><br/>aliases: verify_ssl</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
|
||||||
<b>plugin</b>
|
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">-</span>
|
|
||||||
/ <span style="color: red">required</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
|
||||||
<li>kubernetes.core.k8s</li>
|
|
||||||
<li>k8s</li>
|
|
||||||
<li>community.kubernetes.k8s</li>
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div>token that ensures this is a source file for the 'k8s' plugin.</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Examples
|
|
||||||
--------
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
# File must be named k8s.yaml or k8s.yml
|
|
||||||
|
|
||||||
# Authenticate with token, and return all pods and services for all namespaces
|
|
||||||
plugin: kubernetes.core.k8s
|
|
||||||
connections:
|
|
||||||
- host: https://192.168.64.4:8443
|
|
||||||
api_key: xxxxxxxxxxxxxxxx
|
|
||||||
validate_certs: false
|
|
||||||
|
|
||||||
# Use default config (~/.kube/config) file and active context, and return objects for a specific namespace
|
|
||||||
plugin: kubernetes.core.k8s
|
|
||||||
connections:
|
|
||||||
- namespaces:
|
|
||||||
- testing
|
|
||||||
|
|
||||||
# Use a custom config file, and a specific context.
|
|
||||||
plugin: kubernetes.core.k8s
|
|
||||||
connections:
|
|
||||||
- kubeconfig: /path/to/config
|
|
||||||
context: 'awx/192-168-64-4:8443/developer'
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Status
|
|
||||||
------
|
|
||||||
|
|
||||||
|
|
||||||
Authors
|
|
||||||
~~~~~~~
|
|
||||||
|
|
||||||
- Chris Houseknecht <@chouseknecht>
|
|
||||||
- Fabian von Feilitzsch <@fabianvf>
|
|
||||||
|
|
||||||
|
|
||||||
.. hint::
|
|
||||||
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.
|
|
||||||
@@ -18,7 +18,7 @@ Version added: 2.0.0
|
|||||||
Synopsis
|
Synopsis
|
||||||
--------
|
--------
|
||||||
- This module is used to apply RFC 6902 JSON patch operations only.
|
- This module is used to apply RFC 6902 JSON patch operations only.
|
||||||
- Use the :ref:`k8s <k8s_module>` module for strategic merge or JSON merge operations.
|
- Use the :ref:`kubernetes.core.k8s <kubernetes.core.k8s_module>` module for strategic merge or JSON merge operations.
|
||||||
- The jsonpatch library is required for check mode.
|
- The jsonpatch library is required for check mode.
|
||||||
|
|
||||||
|
|
||||||
@@ -27,8 +27,8 @@ Requirements
|
|||||||
------------
|
------------
|
||||||
The below requirements are needed on the host that executes this module.
|
The below requirements are needed on the host that executes this module.
|
||||||
|
|
||||||
- python >= 3.6
|
- python >= 3.9
|
||||||
- kubernetes >= 12.0.0
|
- kubernetes >= 24.2.0
|
||||||
- PyYAML >= 3.11
|
- PyYAML >= 3.11
|
||||||
- jsonpatch
|
- jsonpatch
|
||||||
|
|
||||||
@@ -140,6 +140,25 @@ Parameters
|
|||||||
<div>The name of a context found in the config file. Can also be specified via K8S_AUTH_CONTEXT environment variable.</div>
|
<div>The name of a context found in the config file. Can also be specified via K8S_AUTH_CONTEXT environment variable.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>hidden_fields</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.1.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<b>Default:</b><br/><div style="color: blue">[]</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>List of fields to hide from the diff output.</div>
|
||||||
|
<div>This is useful for fields that are not relevant to the patch operation, such as `metadata.managedFields`.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -155,6 +174,41 @@ Parameters
|
|||||||
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_groups</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Group(s) to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_GROUPS environment. Example: Group1,Group2</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_user</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Username to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_USER environment.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -178,13 +232,15 @@ Parameters
|
|||||||
<b>kubeconfig</b>
|
<b>kubeconfig</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">path</span>
|
<span style="color: purple">raw</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
||||||
|
<div>Multiple Kubernetes config file can be provided using separator ';' for Windows platform or ':' for others platforms.</div>
|
||||||
|
<div>The kubernetes configuration can be provided as dictionary. This feature requires a python kubernetes client version >= 17.17.0. Added in version 2.2.0.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -220,6 +276,25 @@ Parameters
|
|||||||
<div>Use in conjunction with <em>api_version</em>, <em>kind</em>, and <em>name</em> to identify a specific object.</div>
|
<div>Use in conjunction with <em>api_version</em>, <em>kind</em>, and <em>name</em> to identify a specific object.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>no_proxy</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The comma separated list of hosts/domains/IP/CIDR that shouldn't go through proxy. Can also be specified via K8S_AUTH_NO_PROXY environment variable.</div>
|
||||||
|
<div>Please note that this module does not pick up typical proxy settings from the environment (e.g. NO_PROXY).</div>
|
||||||
|
<div>This feature requires kubernetes>=19.15.0. When kubernetes library is less than 19.15.0, it fails even no_proxy set in correct.</div>
|
||||||
|
<div>example value is "localhost,.local,.example.com,127.0.0.1,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -558,7 +633,7 @@ Examples
|
|||||||
path: /metadata/labels/app
|
path: /metadata/labels/app
|
||||||
value: myapp
|
value: myapp
|
||||||
- op: replace
|
- op: replace
|
||||||
patch: /spec/containers/0/image
|
path: /spec/containers/0/image
|
||||||
value: nginx
|
value: nginx
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ Requirements
|
|||||||
------------
|
------------
|
||||||
The below requirements are needed on the host that executes this module.
|
The below requirements are needed on the host that executes this module.
|
||||||
|
|
||||||
- python >= 3.6
|
- python >= 3.9
|
||||||
- kubernetes >= 12.0.0
|
- kubernetes >= 24.2.0
|
||||||
- PyYAML >= 3.11
|
- PyYAML >= 3.11
|
||||||
|
|
||||||
|
|
||||||
@@ -44,6 +44,27 @@ Parameters
|
|||||||
<th>Choices/<font color="blue">Defaults</font></th>
|
<th>Choices/<font color="blue">Defaults</font></th>
|
||||||
<th width="100%">Comments</th>
|
<th width="100%">Comments</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>all_containers</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.4.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li>no</li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>If set to <code>true</code>, retrieve all containers' logs in the pod(s).</div>
|
||||||
|
<div>mutually exclusive with <code>container</code>.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -141,7 +162,8 @@ Parameters
|
|||||||
<td>
|
<td>
|
||||||
<div>Use to specify the container within a pod to grab the log from.</div>
|
<div>Use to specify the container within a pod to grab the log from.</div>
|
||||||
<div>If there is only one container, this will default to that container.</div>
|
<div>If there is only one container, this will default to that container.</div>
|
||||||
<div>If there is more than one container, this option is required.</div>
|
<div>If there is more than one container, this option is required or set <em>all_containers</em> to <code>true</code>.</div>
|
||||||
|
<div>mutually exclusive with <code>all_containers</code>.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -174,6 +196,41 @@ Parameters
|
|||||||
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_groups</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Group(s) to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_GROUPS environment. Example: Group1,Group2</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_user</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Username to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_USER environment.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -198,13 +255,15 @@ Parameters
|
|||||||
<b>kubeconfig</b>
|
<b>kubeconfig</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">path</span>
|
<span style="color: purple">raw</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
||||||
|
<div>Multiple Kubernetes config file can be provided using separator ';' for Windows platform or ':' for others platforms.</div>
|
||||||
|
<div>The kubernetes configuration can be provided as dictionary. This feature requires a python kubernetes client version >= 17.17.0. Added in version 2.2.0.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -218,6 +277,7 @@ Parameters
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
<b>Default:</b><br/><div style="color: blue">[]</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>List of label selectors to use to filter results</div>
|
<div>List of label selectors to use to filter results</div>
|
||||||
@@ -259,6 +319,25 @@ Parameters
|
|||||||
<div>If <em>resource definition</em> is provided, the <em>metadata.namespace</em> value from the <em>resource_definition</em> will override this option.</div>
|
<div>If <em>resource definition</em> is provided, the <em>metadata.namespace</em> value from the <em>resource_definition</em> will override this option.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>no_proxy</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The comma separated list of hosts/domains/IP/CIDR that shouldn't go through proxy. Can also be specified via K8S_AUTH_NO_PROXY environment variable.</div>
|
||||||
|
<div>Please note that this module does not pick up typical proxy settings from the environment (e.g. NO_PROXY).</div>
|
||||||
|
<div>This feature requires kubernetes>=19.15.0. When kubernetes library is less than 19.15.0, it fails even no_proxy set in correct.</div>
|
||||||
|
<div>example value is "localhost,.local,.example.com,127.0.0.1,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -298,6 +377,26 @@ Parameters
|
|||||||
<div>The fix for this k8s python library is here: https://github.com/kubernetes-client/python-base/pull/169</div>
|
<div>The fix for this k8s python library is here: https://github.com/kubernetes-client/python-base/pull/169</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>previous</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.4.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>If <code>true</code>, print the logs for the previous instance of the container in a pod if it exists.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -383,6 +482,38 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>since_seconds</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.2.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>A relative time in seconds before the current time from which to show logs.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>tail_lines</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">integer</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.4.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>A number of lines from the end of the logs to retrieve.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -457,6 +588,7 @@ Examples
|
|||||||
kind: Deployment
|
kind: Deployment
|
||||||
namespace: testing
|
namespace: testing
|
||||||
name: example
|
name: example
|
||||||
|
since_seconds: "4000"
|
||||||
register: log
|
register: log
|
||||||
|
|
||||||
# This will get the log from a single Pod managed by this DeploymentConfig
|
# This will get the log from a single Pod managed by this DeploymentConfig
|
||||||
@@ -466,8 +598,16 @@ Examples
|
|||||||
kind: DeploymentConfig
|
kind: DeploymentConfig
|
||||||
namespace: testing
|
namespace: testing
|
||||||
name: example
|
name: example
|
||||||
|
tail_lines: 100
|
||||||
register: log
|
register: log
|
||||||
|
|
||||||
|
# This will get the logs from all containers in Pod
|
||||||
|
- name: Get the logs from all containers in pod
|
||||||
|
kubernetes.core.k8s_log:
|
||||||
|
namespace: testing
|
||||||
|
name: some-pod
|
||||||
|
all_containers: true
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Return Values
|
Return Values
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ Requirements
|
|||||||
------------
|
------------
|
||||||
The below requirements are needed on the local Ansible controller node that executes this lookup.
|
The below requirements are needed on the local Ansible controller node that executes this lookup.
|
||||||
|
|
||||||
- python >= 3.6
|
- python >= 3.9
|
||||||
- kubernetes >= 12.0.0
|
- kubernetes >= 24.2.0
|
||||||
- PyYAML >= 3.11
|
- PyYAML >= 3.11
|
||||||
|
|
||||||
|
|
||||||
@@ -381,6 +381,12 @@ Parameters
|
|||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
|
Notes
|
||||||
|
-----
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
- While querying, please use ``query`` or ``lookup`` format with ``wantlist=True`` to provide an easier and more consistent interface. For more details, see https://docs.ansible.com/ansible/latest/plugins/lookup.html#forcing-lookups-to-return-lists-query-and-wantlist-true.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
@@ -390,23 +396,23 @@ Examples
|
|||||||
|
|
||||||
- name: Fetch a list of namespaces
|
- name: Fetch a list of namespaces
|
||||||
set_fact:
|
set_fact:
|
||||||
projects: "{{ lookup('kubernetes.core.k8s', api_version='v1', kind='Namespace') }}"
|
projects: "{{ query('kubernetes.core.k8s', api_version='v1', kind='Namespace') }}"
|
||||||
|
|
||||||
- name: Fetch all deployments
|
- name: Fetch all deployments
|
||||||
set_fact:
|
set_fact:
|
||||||
deployments: "{{ lookup('kubernetes.core.k8s', kind='Deployment') }}"
|
deployments: "{{ query('kubernetes.core.k8s', kind='Deployment') }}"
|
||||||
|
|
||||||
- name: Fetch all deployments in a namespace
|
- name: Fetch all deployments in a namespace
|
||||||
set_fact:
|
set_fact:
|
||||||
deployments: "{{ lookup('kubernetes.core.k8s', kind='Deployment', namespace='testing') }}"
|
deployments: "{{ query('kubernetes.core.k8s', kind='Deployment', namespace='testing') }}"
|
||||||
|
|
||||||
- name: Fetch a specific deployment by name
|
- name: Fetch a specific deployment by name
|
||||||
set_fact:
|
set_fact:
|
||||||
deployments: "{{ lookup('kubernetes.core.k8s', kind='Deployment', namespace='testing', resource_name='elastic') }}"
|
deployments: "{{ query('kubernetes.core.k8s', kind='Deployment', namespace='testing', resource_name='elastic') }}"
|
||||||
|
|
||||||
- name: Fetch with label selector
|
- name: Fetch with label selector
|
||||||
set_fact:
|
set_fact:
|
||||||
service: "{{ lookup('kubernetes.core.k8s', kind='Service', label_selector='app=galaxy') }}"
|
service: "{{ query('kubernetes.core.k8s', kind='Service', label_selector='app=galaxy') }}"
|
||||||
|
|
||||||
# Use parameters from a YAML config
|
# Use parameters from a YAML config
|
||||||
|
|
||||||
@@ -416,11 +422,11 @@ Examples
|
|||||||
|
|
||||||
- name: Using the config (loaded from a file in prior task), fetch the latest version of the object
|
- name: Using the config (loaded from a file in prior task), fetch the latest version of the object
|
||||||
set_fact:
|
set_fact:
|
||||||
service: "{{ lookup('kubernetes.core.k8s', resource_definition=config) }}"
|
service: "{{ query('kubernetes.core.k8s', resource_definition=config) }}"
|
||||||
|
|
||||||
- name: Use a config from the local filesystem
|
- name: Use a config from the local filesystem
|
||||||
set_fact:
|
set_fact:
|
||||||
service: "{{ lookup('kubernetes.core.k8s', src='service.yml') }}"
|
service: "{{ query('kubernetes.core.k8s', src='service.yml') }}"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -432,106 +438,28 @@ Common return values are documented `here <https://docs.ansible.com/ansible/late
|
|||||||
|
|
||||||
<table border=0 cellpadding=0 class="documentation-table">
|
<table border=0 cellpadding=0 class="documentation-table">
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="2">Key</th>
|
<th colspan="1">Key</th>
|
||||||
<th>Returned</th>
|
<th>Returned</th>
|
||||||
<th width="100%">Description</th>
|
<th width="100%">Description</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="1">
|
||||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
<b>_list</b>
|
<b>_list</b>
|
||||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">complex</span>
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=dictionary</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td>
|
<td>
|
||||||
<div>One ore more object definitions returned from the API.</div>
|
<div>One ore more object definitions returned from the API.</div>
|
||||||
<br/>
|
<br/>
|
||||||
|
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||||
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">[{'kind': 'ConfigMap', 'apiVersion': 'v1', 'metadata': {'creationTimestamp': '2022-03-04T13:59:49Z', 'name': 'my-config-map', 'namespace': 'default', 'resourceVersion': '418', 'uid': '5714b011-d090-4eac-8272-a0ea82ec0abd'}, 'data': {'key1': 'val1'}}]</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td class="elbow-placeholder"> </td>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
|
||||||
<b>api_version</b>
|
|
||||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">string</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>success</td>
|
|
||||||
<td>
|
|
||||||
<div>The versioned schema of this representation of an object.</div>
|
|
||||||
<br/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="elbow-placeholder"> </td>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
|
||||||
<b>kind</b>
|
|
||||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">string</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>success</td>
|
|
||||||
<td>
|
|
||||||
<div>Represents the REST resource this object represents.</div>
|
|
||||||
<br/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="elbow-placeholder"> </td>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
|
||||||
<b>metadata</b>
|
|
||||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">complex</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>success</td>
|
|
||||||
<td>
|
|
||||||
<div>Standard object metadata. Includes name, namespace, annotations, labels, etc.</div>
|
|
||||||
<br/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="elbow-placeholder"> </td>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
|
||||||
<b>spec</b>
|
|
||||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">complex</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>success</td>
|
|
||||||
<td>
|
|
||||||
<div>Specific attributes of the object. Will vary based on the <em>api_version</em> and <em>kind</em>.</div>
|
|
||||||
<br/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="elbow-placeholder"> </td>
|
|
||||||
<td colspan="1">
|
|
||||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
|
||||||
<b>status</b>
|
|
||||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
|
||||||
<div style="font-size: small">
|
|
||||||
<span style="color: purple">complex</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>success</td>
|
|
||||||
<td>
|
|
||||||
<div>Current status details for the object.</div>
|
|
||||||
<br/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
|
|
||||||
@@ -543,8 +471,8 @@ Status
|
|||||||
Authors
|
Authors
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
|
|
||||||
- Chris Houseknecht <@chouseknecht>
|
- Chris Houseknecht (@chouseknecht)
|
||||||
- Fabian von Feilitzsch <@fabianvf>
|
- Fabian von Feilitzsch (@fabianvf)
|
||||||
|
|
||||||
|
|
||||||
.. hint::
|
.. hint::
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ Requirements
|
|||||||
------------
|
------------
|
||||||
The below requirements are needed on the host that executes this module.
|
The below requirements are needed on the host that executes this module.
|
||||||
|
|
||||||
- python >= 3.6
|
- python >= 3.9
|
||||||
- kubernetes >= 12.0.0
|
- kubernetes >= 24.2.0
|
||||||
- PyYAML >= 3.11
|
- PyYAML >= 3.11
|
||||||
- jsonpatch
|
- jsonpatch
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ Parameters
|
|||||||
<td>
|
<td>
|
||||||
<div><code>apply</code> compares the desired resource definition with the previously supplied resource definition, ignoring properties that are automatically generated</div>
|
<div><code>apply</code> compares the desired resource definition with the previously supplied resource definition, ignoring properties that are automatically generated</div>
|
||||||
<div><code>apply</code> works better with Services than 'force=yes'</div>
|
<div><code>apply</code> works better with Services than 'force=yes'</div>
|
||||||
<div>mutually exclusive with <code>merge_type</code></div>
|
<div>Mutually exclusive with <code>merge_type</code>.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -208,6 +208,30 @@ Parameters
|
|||||||
<div>This has no effect on the validation step which is controlled by the <code>validate.fail_on_error</code> parameter.</div>
|
<div>This has no effect on the validation step which is controlled by the <code>validate.fail_on_error</code> parameter.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>delete_all</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>When this option is set to <em>true</em> and <em>state=absent</em>, module will delete all resources of the specified resource type in the requested namespace.</div>
|
||||||
|
<div>Ignored when <code>state</code> is not set to <em>absent</em> or when one of (src), <code>name</code> or <code>resource_definition</code> is provided.</div>
|
||||||
|
<div>Parameter <code>kind</code> is required to use this option.</div>
|
||||||
|
<div>This parameter can be used with <code>label_selectors</code> to restrict the resources to be deleted.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: all</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3">
|
<td colspan="3">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -336,6 +360,44 @@ Parameters
|
|||||||
<div>If set to <code>yes</code>, and <em>state</em> is <code>present</code>, an existing object will be replaced.</div>
|
<div>If set to <code>yes</code>, and <em>state</em> is <code>present</code>, an existing object will be replaced.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>generate_name</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Use to specify the basis of an object name and random characters will be added automatically on server to generate a unique name.</div>
|
||||||
|
<div>This option is ignored when <em>state</em> is not set to <code>present</code> or when <em>apply</em> is set to <code>yes</code>.</div>
|
||||||
|
<div>If <em>resource definition</em> is provided, the <em>metadata.generateName</em> value from the <em>resource_definition</em> will override this option.</div>
|
||||||
|
<div>If <em>resource definition</em> is provided, and contains <em>metadata.name</em>, this option is ignored.</div>
|
||||||
|
<div>mutually exclusive with <code>name</code>.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>hidden_fields</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.0.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Hide fields matching this option in the result</div>
|
||||||
|
<div>An example might be <code>hidden_fields=[metadata.managedFields]</code> or V(hidden_fields=[spec.containers[0].env[3].value]) or V(hidden_fields=[metadata.annotations[kubectl.kubernetes.io/last-applied-configuration]])</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3">
|
<td colspan="3">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -351,6 +413,41 @@ Parameters
|
|||||||
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_groups</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Group(s) to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_GROUPS environment. Example: Group1,Group2</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_user</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Username to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_USER environment.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3">
|
<td colspan="3">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -375,13 +472,32 @@ Parameters
|
|||||||
<b>kubeconfig</b>
|
<b>kubeconfig</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">path</span>
|
<span style="color: purple">raw</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
||||||
|
<div>Multiple Kubernetes config file can be provided using separator ';' for Windows platform or ':' for others platforms.</div>
|
||||||
|
<div>The kubernetes configuration can be provided as dictionary. This feature requires a python kubernetes client version >= 17.17.0. Added in version 2.2.0.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>label_selectors</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.2.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Selector (label query) to filter on.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -396,18 +512,17 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
<li>json</li>
|
|
||||||
<li>merge</li>
|
<li>merge</li>
|
||||||
<li>strategic-merge</li>
|
<li>strategic-merge</li>
|
||||||
</ul>
|
</ul>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Whether to override the default patch merge approach with a specific type. By default, the strategic merge will typically be used.</div>
|
<div>Whether to override the default patch merge approach with a specific type. By default, the strategic merge will typically be used.</div>
|
||||||
<div>For example, Custom Resource Definitions typically aren't updatable by the usual strategic merge. You may want to use <code>merge</code> if you see "strategic merge patch format is not supported"</div>
|
<div>For example, Custom Resource Definitions typically aren't updatable by the usual strategic merge. You may want to use <code>merge</code> if you see "strategic merge patch format is not supported".</div>
|
||||||
<div>See <a href='https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/#use-a-json-merge-patch-to-update-a-deployment'>https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/#use-a-json-merge-patch-to-update-a-deployment</a></div>
|
<div>See <a href='https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/#use-a-json-merge-patch-to-update-a-deployment'>https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/#use-a-json-merge-patch-to-update-a-deployment</a></div>
|
||||||
<div>If more than one <code>merge_type</code> is given, the merge_types will be tried in order. This defaults to <code>['strategic-merge', 'merge']</code>, which is ideal for using the same parameters on resource kinds that combine Custom Resources and built-in resources.</div>
|
<div>If more than one <code>merge_type</code> is given, the merge_types will be tried in order. This defaults to <code>['strategic-merge', 'merge']</code>, which is ideal for using the same parameters on resource kinds that combine Custom Resources and built-in resources.</div>
|
||||||
<div>mutually exclusive with <code>apply</code></div>
|
<div>Mutually exclusive with <code>apply</code>.</div>
|
||||||
<div><em>merge_type=json</em> is deprecated and will be removed in version 3.0.0. Please use <span class='module'>kubernetes.core.k8s_json_patch</span> instead.</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>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -446,6 +561,25 @@ Parameters
|
|||||||
<div>If <em>resource definition</em> is provided, the <em>metadata.namespace</em> value from the <em>resource_definition</em> will override this option.</div>
|
<div>If <em>resource definition</em> is provided, the <em>metadata.namespace</em> value from the <em>resource_definition</em> will override this option.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>no_proxy</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The comma separated list of hosts/domains/IP/CIDR that shouldn't go through proxy. Can also be specified via K8S_AUTH_NO_PROXY environment variable.</div>
|
||||||
|
<div>Please note that this module does not pick up typical proxy settings from the environment (e.g. NO_PROXY).</div>
|
||||||
|
<div>This feature requires kubernetes>=19.15.0. When kubernetes library is less than 19.15.0, it fails even no_proxy set in correct.</div>
|
||||||
|
<div>example value is "localhost,.local,.example.com,127.0.0.1,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3">
|
<td colspan="3">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -587,6 +721,63 @@ Parameters
|
|||||||
<div style="font-size: small; color: darkgreen"><br/>aliases: definition, inline</div>
|
<div style="font-size: small; color: darkgreen"><br/>aliases: definition, inline</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>server_side_apply</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">dictionary</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>When this option is set, apply runs in the server instead of the client.</div>
|
||||||
|
<div>Ignored if <code>apply</code> is not set or is set to False.</div>
|
||||||
|
<div>This option requires "kubernetes >= 19.15.0".</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>field_manager</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
/ <span style="color: red">required</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Name of the manager used to track field ownership.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>force_conflicts</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>A conflict is a special status error that occurs when an Server Side Apply operation tries to change a field, which another user also claims to manage.</div>
|
||||||
|
<div>When set to True, server-side apply will force the changes against conflicts.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3">
|
<td colspan="3">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -601,7 +792,8 @@ Parameters
|
|||||||
<td>
|
<td>
|
||||||
<div>Provide a path to a file containing a valid YAML definition of an object or objects to be created or updated. Mutually exclusive with <em>resource_definition</em>. NOTE: <em>kind</em>, <em>api_version</em>, <em>name</em>, and <em>namespace</em> will be overwritten by corresponding values found in the configuration read in from the <em>src</em> file.</div>
|
<div>Provide a path to a file containing a valid YAML definition of an object or objects to be created or updated. Mutually exclusive with <em>resource_definition</em>. NOTE: <em>kind</em>, <em>api_version</em>, <em>name</em>, and <em>namespace</em> will be overwritten by corresponding values found in the configuration read in from the <em>src</em> file.</div>
|
||||||
<div>Reads from the local file system. To read from the Ansible controller's file system, including vaulted files, use the file lookup plugin or template lookup plugin, combined with the from_yaml filter, and pass the result to <em>resource_definition</em>. See Examples below.</div>
|
<div>Reads from the local file system. To read from the Ansible controller's file system, including vaulted files, use the file lookup plugin or template lookup plugin, combined with the from_yaml filter, and pass the result to <em>resource_definition</em>. See Examples below.</div>
|
||||||
<div>Mutually exclusive with <em>template</em> in case of <span class='module'>k8s</span> module.</div>
|
<div>The URL to manifest files that can be used to create the resource. Added in version 2.4.0.</div>
|
||||||
|
<div>Mutually exclusive with <em>template</em> in case of <span class='module'>kubernetes.core.k8s</span> module.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -639,6 +831,7 @@ Parameters
|
|||||||
<td>
|
<td>
|
||||||
<div>Provide a valid YAML template definition file for an object when creating or updating.</div>
|
<div>Provide a valid YAML template definition file for an object when creating or updating.</div>
|
||||||
<div>Value can be provided as string or dictionary.</div>
|
<div>Value can be provided as string or dictionary.</div>
|
||||||
|
<div>The parameter accepts multiple template files. Added in version 2.0.0.</div>
|
||||||
<div>Mutually exclusive with <code>src</code> and <code>resource_definition</code>.</div>
|
<div>Mutually exclusive with <code>src</code> and <code>resource_definition</code>.</div>
|
||||||
<div>Template files needs to be present on the Ansible Controller's file system.</div>
|
<div>Template files needs to be present on the Ansible Controller's file system.</div>
|
||||||
<div>Additional parameters can be specified using dictionary.</div>
|
<div>Additional parameters can be specified using dictionary.</div>
|
||||||
@@ -962,6 +1155,14 @@ Examples
|
|||||||
state: present
|
state: present
|
||||||
definition: "{{ lookup('file', '/testing/deployment.yml') | from_yaml }}"
|
definition: "{{ lookup('file', '/testing/deployment.yml') | from_yaml }}"
|
||||||
|
|
||||||
|
- name: >-
|
||||||
|
(Alternative) Read definition file from the Ansible controller file system.
|
||||||
|
In this case, the definition file contains multiple YAML documents, separated by ---.
|
||||||
|
If the definition file has been encrypted with Ansible Vault it will automatically be decrypted.
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
state: present
|
||||||
|
definition: "{{ lookup('file', '/testing/deployment.yml') | from_yaml_all }}"
|
||||||
|
|
||||||
- name: Read definition template file from the Ansible controller file system
|
- name: Read definition template file from the Ansible controller file system
|
||||||
kubernetes.core.k8s:
|
kubernetes.core.k8s:
|
||||||
state: present
|
state: present
|
||||||
@@ -975,6 +1176,15 @@ Examples
|
|||||||
variable_start_string: '[['
|
variable_start_string: '[['
|
||||||
variable_end_string: ']]'
|
variable_end_string: ']]'
|
||||||
|
|
||||||
|
- name: Read multiple definition template file from the Ansible controller file system
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
state: present
|
||||||
|
template:
|
||||||
|
- path: '/testing/deployment_one.j2'
|
||||||
|
- path: '/testing/deployment_two.j2'
|
||||||
|
variable_start_string: '[['
|
||||||
|
variable_end_string: ']]'
|
||||||
|
|
||||||
- name: fail on validation errors
|
- name: fail on validation errors
|
||||||
kubernetes.core.k8s:
|
kubernetes.core.k8s:
|
||||||
state: present
|
state: present
|
||||||
@@ -1030,6 +1240,41 @@ Examples
|
|||||||
labels:
|
labels:
|
||||||
support: patch
|
support: patch
|
||||||
|
|
||||||
|
# Create object using generateName
|
||||||
|
- name: create resource using name generated by the server
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
state: present
|
||||||
|
generate_name: pod-
|
||||||
|
definition:
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Pod
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: py
|
||||||
|
image: python:3.7-alpine
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
|
||||||
|
# Server side apply
|
||||||
|
- name: Create configmap using server side apply
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
namespace: testing
|
||||||
|
definition:
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: my-configmap
|
||||||
|
apply: yes
|
||||||
|
server_side_apply:
|
||||||
|
field_manager: ansible
|
||||||
|
|
||||||
|
# Delete all Deployment from specified namespace
|
||||||
|
- name: Delete all Deployment from specified namespace
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
api_version: apps/v1
|
||||||
|
namespace: testing
|
||||||
|
kind: Deployment
|
||||||
|
delete_all: true
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Return Values
|
Return Values
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ Requirements
|
|||||||
------------
|
------------
|
||||||
The below requirements are needed on the host that executes this module.
|
The below requirements are needed on the host that executes this module.
|
||||||
|
|
||||||
- python >= 3.6
|
- python >= 3.9
|
||||||
- kubernetes >= 12.0.0
|
- kubernetes >= 24.2.0
|
||||||
- PyYAML >= 3.11
|
- PyYAML >= 3.11
|
||||||
|
|
||||||
|
|
||||||
@@ -152,6 +152,7 @@ Parameters
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
<b>Default:</b><br/><div style="color: blue">[]</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>List of field selectors to use to filter results.</div>
|
<div>List of field selectors to use to filter results.</div>
|
||||||
@@ -172,6 +173,41 @@ Parameters
|
|||||||
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_groups</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Group(s) to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_GROUPS environment. Example: Group1,Group2</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_user</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Username to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_USER environment.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -196,13 +232,15 @@ Parameters
|
|||||||
<b>kubeconfig</b>
|
<b>kubeconfig</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">path</span>
|
<span style="color: purple">raw</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
||||||
|
<div>Multiple Kubernetes config file can be provided using separator ';' for Windows platform or ':' for others platforms.</div>
|
||||||
|
<div>The kubernetes configuration can be provided as dictionary. This feature requires a python kubernetes client version >= 17.17.0. Added in version 2.2.0.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -216,6 +254,7 @@ Parameters
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
<b>Default:</b><br/><div style="color: blue">[]</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>List of label selectors to use to filter results.</div>
|
<div>List of label selectors to use to filter results.</div>
|
||||||
@@ -257,6 +296,25 @@ Parameters
|
|||||||
<div>If <em>resource definition</em> is provided, the <em>metadata.namespace</em> value from the <em>resource_definition</em> will override this option.</div>
|
<div>If <em>resource definition</em> is provided, the <em>metadata.namespace</em> value from the <em>resource_definition</em> will override this option.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>no_proxy</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The comma separated list of hosts/domains/IP/CIDR that shouldn't go through proxy. Can also be specified via K8S_AUTH_NO_PROXY environment variable.</div>
|
||||||
|
<div>Please note that this module does not pick up typical proxy settings from the environment (e.g. NO_PROXY).</div>
|
||||||
|
<div>This feature requires kubernetes>=19.15.0. When kubernetes library is less than 19.15.0, it fails even no_proxy set in correct.</div>
|
||||||
|
<div>example value is "localhost,.local,.example.com,127.0.0.1,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ Requirements
|
|||||||
------------
|
------------
|
||||||
The below requirements are needed on the host that executes this module.
|
The below requirements are needed on the host that executes this module.
|
||||||
|
|
||||||
- python >= 3.6
|
- python >= 3.9
|
||||||
- kubernetes >= 12.0.0
|
- kubernetes >= 24.2.0
|
||||||
- PyYAML >= 3.11
|
- PyYAML >= 3.11
|
||||||
|
|
||||||
|
|
||||||
@@ -189,6 +189,41 @@ Parameters
|
|||||||
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_groups</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Group(s) to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_GROUPS environment. Example: Group1,Group2</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_user</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Username to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_USER environment.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -213,13 +248,15 @@ Parameters
|
|||||||
<b>kubeconfig</b>
|
<b>kubeconfig</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">path</span>
|
<span style="color: purple">raw</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
||||||
|
<div>Multiple Kubernetes config file can be provided using separator ';' for Windows platform or ':' for others platforms.</div>
|
||||||
|
<div>The kubernetes configuration can be provided as dictionary. This feature requires a python kubernetes client version >= 17.17.0. Added in version 2.2.0.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -234,6 +271,7 @@ Parameters
|
|||||||
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.0.0</div>
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.0.0</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
<b>Default:</b><br/><div style="color: blue">[]</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>List of label selectors to use to filter results.</div>
|
<div>List of label selectors to use to filter results.</div>
|
||||||
@@ -275,6 +313,25 @@ Parameters
|
|||||||
<div>If <em>resource definition</em> is provided, the <em>metadata.namespace</em> value from the <em>resource_definition</em> will override this option.</div>
|
<div>If <em>resource definition</em> is provided, the <em>metadata.namespace</em> value from the <em>resource_definition</em> will override this option.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>no_proxy</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The comma separated list of hosts/domains/IP/CIDR that shouldn't go through proxy. Can also be specified via K8S_AUTH_NO_PROXY environment variable.</div>
|
||||||
|
<div>Please note that this module does not pick up typical proxy settings from the environment (e.g. NO_PROXY).</div>
|
||||||
|
<div>This feature requires kubernetes>=19.15.0. When kubernetes library is less than 19.15.0, it fails even no_proxy set in correct.</div>
|
||||||
|
<div>example value is "localhost,.local,.example.com,127.0.0.1,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -461,7 +518,8 @@ Parameters
|
|||||||
<td>
|
<td>
|
||||||
<div>Provide a path to a file containing a valid YAML definition of an object or objects to be created or updated. Mutually exclusive with <em>resource_definition</em>. NOTE: <em>kind</em>, <em>api_version</em>, <em>name</em>, and <em>namespace</em> will be overwritten by corresponding values found in the configuration read in from the <em>src</em> file.</div>
|
<div>Provide a path to a file containing a valid YAML definition of an object or objects to be created or updated. Mutually exclusive with <em>resource_definition</em>. NOTE: <em>kind</em>, <em>api_version</em>, <em>name</em>, and <em>namespace</em> will be overwritten by corresponding values found in the configuration read in from the <em>src</em> file.</div>
|
||||||
<div>Reads from the local file system. To read from the Ansible controller's file system, including vaulted files, use the file lookup plugin or template lookup plugin, combined with the from_yaml filter, and pass the result to <em>resource_definition</em>. See Examples below.</div>
|
<div>Reads from the local file system. To read from the Ansible controller's file system, including vaulted files, use the file lookup plugin or template lookup plugin, combined with the from_yaml filter, and pass the result to <em>resource_definition</em>. See Examples below.</div>
|
||||||
<div>Mutually exclusive with <em>template</em> in case of <span class='module'>k8s</span> module.</div>
|
<div>The URL to manifest files that can be used to create the resource. Added in version 2.4.0.</div>
|
||||||
|
<div>Mutually exclusive with <em>template</em> in case of <span class='module'>kubernetes.core.k8s</span> module.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ Requirements
|
|||||||
------------
|
------------
|
||||||
The below requirements are needed on the host that executes this module.
|
The below requirements are needed on the host that executes this module.
|
||||||
|
|
||||||
- python >= 3.6
|
- python >= 3.9
|
||||||
- kubernetes >= 12.0.0
|
- kubernetes >= 24.2.0
|
||||||
|
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
@@ -172,19 +172,56 @@ Parameters
|
|||||||
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_groups</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Group(s) to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_GROUPS environment. Example: Group1,Group2</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_user</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Username to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_USER environment.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
<b>kubeconfig</b>
|
<b>kubeconfig</b>
|
||||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
<div style="font-size: small">
|
<div style="font-size: small">
|
||||||
<span style="color: purple">path</span>
|
<span style="color: purple">raw</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
||||||
|
<div>Multiple Kubernetes config file can be provided using separator ';' for Windows platform or ':' for others platforms.</div>
|
||||||
|
<div>The kubernetes configuration can be provided as dictionary. This feature requires a python kubernetes client version >= 17.17.0. Added in version 2.2.0.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -244,6 +281,25 @@ Parameters
|
|||||||
<div>Use to specify a Service object namespace.</div>
|
<div>Use to specify a Service object namespace.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>no_proxy</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The comma separated list of hosts/domains/IP/CIDR that shouldn't go through proxy. Can also be specified via K8S_AUTH_NO_PROXY environment variable.</div>
|
||||||
|
<div>Please note that this module does not pick up typical proxy settings from the environment (e.g. NO_PROXY).</div>
|
||||||
|
<div>This feature requires kubernetes>=19.15.0. When kubernetes library is less than 19.15.0, it fails even no_proxy set in correct.</div>
|
||||||
|
<div>example value is "localhost,.local,.example.com,127.0.0.1,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
@@ -432,7 +488,8 @@ Parameters
|
|||||||
<td>
|
<td>
|
||||||
<div>Provide a path to a file containing a valid YAML definition of an object or objects to be created or updated. Mutually exclusive with <em>resource_definition</em>. NOTE: <em>kind</em>, <em>api_version</em>, <em>name</em>, and <em>namespace</em> will be overwritten by corresponding values found in the configuration read in from the <em>src</em> file.</div>
|
<div>Provide a path to a file containing a valid YAML definition of an object or objects to be created or updated. Mutually exclusive with <em>resource_definition</em>. NOTE: <em>kind</em>, <em>api_version</em>, <em>name</em>, and <em>namespace</em> will be overwritten by corresponding values found in the configuration read in from the <em>src</em> file.</div>
|
||||||
<div>Reads from the local file system. To read from the Ansible controller's file system, including vaulted files, use the file lookup plugin or template lookup plugin, combined with the from_yaml filter, and pass the result to <em>resource_definition</em>. See Examples below.</div>
|
<div>Reads from the local file system. To read from the Ansible controller's file system, including vaulted files, use the file lookup plugin or template lookup plugin, combined with the from_yaml filter, and pass the result to <em>resource_definition</em>. See Examples below.</div>
|
||||||
<div>Mutually exclusive with <em>template</em> in case of <span class='module'>k8s</span> module.</div>
|
<div>The URL to manifest files that can be used to create the resource. Added in version 2.4.0.</div>
|
||||||
|
<div>Mutually exclusive with <em>template</em> in case of <span class='module'>kubernetes.core.k8s</span> module.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
661
docs/kubernetes.core.k8s_taint_module.rst
Normal file
661
docs/kubernetes.core.k8s_taint_module.rst
Normal file
@@ -0,0 +1,661 @@
|
|||||||
|
.. _kubernetes.core.k8s_taint_module:
|
||||||
|
|
||||||
|
|
||||||
|
*************************
|
||||||
|
kubernetes.core.k8s_taint
|
||||||
|
*************************
|
||||||
|
|
||||||
|
**Taint a node in a Kubernetes/OpenShift cluster**
|
||||||
|
|
||||||
|
|
||||||
|
Version added: 2.3.0
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:local:
|
||||||
|
:depth: 1
|
||||||
|
|
||||||
|
|
||||||
|
Synopsis
|
||||||
|
--------
|
||||||
|
- Taint allows a node to refuse Pod to be scheduled unless that Pod has a matching toleration.
|
||||||
|
- Untaint will remove taints from nodes as needed.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
The below requirements are needed on the host that executes this module.
|
||||||
|
|
||||||
|
- python >= 3.9
|
||||||
|
- kubernetes >= 24.2.0
|
||||||
|
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<table border=0 cellpadding=0 class="documentation-table">
|
||||||
|
<tr>
|
||||||
|
<th colspan="2">Parameter</th>
|
||||||
|
<th>Choices/<font color="blue">Defaults</font></th>
|
||||||
|
<th width="100%">Comments</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>api_key</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Token used to authenticate with the API. Can also be specified via K8S_AUTH_API_KEY environment variable.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>ca_cert</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Path to a CA certificate used to authenticate with the API. The full certificate chain must be provided to avoid certificate validation errors. Can also be specified via K8S_AUTH_SSL_CA_CERT environment variable.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: ssl_ca_cert</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>client_cert</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Path to a certificate used to authenticate with the API. Can also be specified via K8S_AUTH_CERT_FILE environment variable.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: cert_file</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>client_key</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">path</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Path to a key file used to authenticate with the API. Can also be specified via K8S_AUTH_KEY_FILE environment variable.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: key_file</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>context</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The name of a context found in the config file. Can also be specified via K8S_AUTH_CONTEXT environment variable.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>host</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_groups</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Group(s) to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_GROUPS environment. Example: Group1,Group2</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>impersonate_user</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Username to impersonate for the operation.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_IMPERSONATE_USER environment.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>kubeconfig</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">raw</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Path to an existing Kubernetes config file. If not provided, and no other connection options are provided, the Kubernetes client will attempt to load the default configuration file from <em>~/.kube/config</em>. Can also be specified via K8S_AUTH_KUBECONFIG environment variable.</div>
|
||||||
|
<div>Multiple Kubernetes config file can be provided using separator ';' for Windows platform or ':' for others platforms.</div>
|
||||||
|
<div>The kubernetes configuration can be provided as dictionary. This feature requires a python kubernetes client version >= 17.17.0. Added in version 2.2.0.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>name</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
/ <span style="color: red">required</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The name of the node.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>no_proxy</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.3.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The comma separated list of hosts/domains/IP/CIDR that shouldn't go through proxy. Can also be specified via K8S_AUTH_NO_PROXY environment variable.</div>
|
||||||
|
<div>Please note that this module does not pick up typical proxy settings from the environment (e.g. NO_PROXY).</div>
|
||||||
|
<div>This feature requires kubernetes>=19.15.0. When kubernetes library is less than 19.15.0, it fails even no_proxy set in correct.</div>
|
||||||
|
<div>example value is "localhost,.local,.example.com,127.0.0.1,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>password</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Provide a password for authenticating with the API. Can also be specified via K8S_AUTH_PASSWORD environment variable.</div>
|
||||||
|
<div>Please read the description of the <code>username</code> option for a discussion of when this option is applicable.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>persist_config</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li>no</li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Whether or not to save the kube config refresh tokens. Can also be specified via K8S_AUTH_PERSIST_CONFIG environment variable.</div>
|
||||||
|
<div>When the k8s context is using a user credentials with refresh tokens (like oidc or gke/gcloud auth), the token is refreshed by the k8s python client library but not saved by default. So the old refresh token can expire and the next auth might fail. Setting this flag to true will tell the k8s python client to save the new refresh token to the kube config file.</div>
|
||||||
|
<div>Default to false.</div>
|
||||||
|
<div>Please note that the current version of the k8s python client library does not support setting this flag to True yet.</div>
|
||||||
|
<div>The fix for this k8s python library is here: https://github.com/kubernetes-client/python-base/pull/169</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>proxy</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The URL of an HTTP proxy to use for the connection. Can also be specified via K8S_AUTH_PROXY environment variable.</div>
|
||||||
|
<div>Please note that this module does not pick up typical proxy settings from the environment (e.g. HTTP_PROXY).</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>proxy_headers</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">dictionary</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.0.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The Header used for the HTTP proxy.</div>
|
||||||
|
<div>Documentation can be found here <a href='https://urllib3.readthedocs.io/en/latest/reference/urllib3.util.html?highlight=proxy_headers#urllib3.util.make_headers'>https://urllib3.readthedocs.io/en/latest/reference/urllib3.util.html?highlight=proxy_headers#urllib3.util.make_headers</a>.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>basic_auth</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Colon-separated username:password for basic authentication header.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_PROXY_HEADERS_BASIC_AUTH environment.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>proxy_basic_auth</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Colon-separated username:password for proxy basic authentication header.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_PROXY_HEADERS_PROXY_BASIC_AUTH environment.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>user_agent</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>String representing the user-agent you want, such as foo/1.0.</div>
|
||||||
|
<div>Can also be specified via K8S_AUTH_PROXY_HEADERS_USER_AGENT environment.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>replace</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>If <code>true</code>, allow taints to be replaced.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>state</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>present</b> ←</div></li>
|
||||||
|
<li>absent</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Determines whether to add or remove taints.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>taints</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">list</span>
|
||||||
|
/ <span style="color: purple">elements=dictionary</span>
|
||||||
|
/ <span style="color: red">required</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>List containing the taints.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>effect</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li>NoSchedule</li>
|
||||||
|
<li>NoExecute</li>
|
||||||
|
<li>PreferNoSchedule</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The effect of the taint on Pods that do not tolerate the taint.</div>
|
||||||
|
<div>Required when <em>state=present</em>.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>key</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The taint key to be applied to a node.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"></td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>value</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The taint value corresponding to the taint key.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>username</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Provide a username for authenticating with the API. Can also be specified via K8S_AUTH_USERNAME environment variable.</div>
|
||||||
|
<div>Please note that this only works with clusters configured to use HTTP Basic Auth. If your cluster has a different form of authentication (e.g. OAuth2 in OpenShift), this option will not work as expected and you should look into the <span class='module'>community.okd.k8s_auth</span> module, as that might do what you need.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>validate_certs</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li>no</li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Whether or not to verify the API server's SSL certificates. Can also be specified via K8S_AUTH_VERIFY_SSL environment variable.</div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: verify_ssl</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
|
Notes
|
||||||
|
-----
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
- To avoid SSL certificate validation errors when ``validate_certs`` is *True*, the full certificate chain for the API server must be provided via ``ca_cert`` or in the kubeconfig file.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
- name: Taint node "foo"
|
||||||
|
kubernetes.core.k8s_taint:
|
||||||
|
state: present
|
||||||
|
name: foo
|
||||||
|
taints:
|
||||||
|
- effect: NoExecute
|
||||||
|
key: "key1"
|
||||||
|
|
||||||
|
- name: Taint node "foo"
|
||||||
|
kubernetes.core.k8s_taint:
|
||||||
|
state: present
|
||||||
|
name: foo
|
||||||
|
taints:
|
||||||
|
- effect: NoExecute
|
||||||
|
key: "key1"
|
||||||
|
value: "value1"
|
||||||
|
- effect: NoSchedule
|
||||||
|
key: "key1"
|
||||||
|
value: "value1"
|
||||||
|
|
||||||
|
- name: Remove taint from "foo".
|
||||||
|
kubernetes.core.k8s_taint:
|
||||||
|
state: absent
|
||||||
|
name: foo
|
||||||
|
taints:
|
||||||
|
- effect: NoExecute
|
||||||
|
key: "key1"
|
||||||
|
value: "value1"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Return Values
|
||||||
|
-------------
|
||||||
|
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<table border=0 cellpadding=0 class="documentation-table">
|
||||||
|
<tr>
|
||||||
|
<th colspan="2">Key</th>
|
||||||
|
<th>Returned</th>
|
||||||
|
<th width="100%">Description</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>result</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">complex</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>The tainted Node object. Will be empty in the case of a deletion.</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>api_version</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>The versioned schema of this representation of an object.</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>kind</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>Represents the REST resource this object represents.</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>metadata</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">complex</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>Standard object metadata. Includes name, namespace, annotations, labels, etc.</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>spec</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">complex</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>Specific attributes of the object. Will vary based on the <em>api_version</em> and <em>kind</em>.</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="elbow-placeholder"> </td>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>status</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">complex</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>success</td>
|
||||||
|
<td>
|
||||||
|
<div>Current status details for the object.</div>
|
||||||
|
<br/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
<br/><br/>
|
||||||
|
|
||||||
|
|
||||||
|
Status
|
||||||
|
------
|
||||||
|
|
||||||
|
|
||||||
|
Authors
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
- Alina Buzachis (@alinabuzachis)
|
||||||
@@ -208,6 +208,28 @@ Parameters
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>Path to a kubectl config file. Defaults to <em>~/.kube/config</em></div>
|
<div>Path to a kubectl config file. Defaults to <em>~/.kube/config</em></div>
|
||||||
|
<div>The configuration can be provided as dictionary. Added in version 2.4.0.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>kubectl_local_env_vars</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">dictionary</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 3.1.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<b>Default:</b><br/><div style="color: blue">{}</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>var: ansible_kubectl_local_env_vars</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Local enviromantal variable to be passed locally to the kubectl command line.</div>
|
||||||
|
<div>Please be aware that this passes information directly on the command line and it could expose sensitive data.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -343,6 +365,82 @@ Parameters
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
- name: Run a command in a pod using local kubectl with kubeconfig file ~/.kube/config
|
||||||
|
hosts: localhost
|
||||||
|
gather_facts: no
|
||||||
|
vars:
|
||||||
|
ansible_connection: kubernetes.core.kubectl
|
||||||
|
ansible_kubectl_namespace: my-namespace
|
||||||
|
ansible_kubectl_pod: my-pod
|
||||||
|
ansible_kubectl_container: my-container
|
||||||
|
tasks:
|
||||||
|
# be aware that the command is executed as the user that started the container
|
||||||
|
# and requires python to be installed in the image
|
||||||
|
- name: Run a command in a pod
|
||||||
|
ansible.builtin.command: echo "Hello, World!"
|
||||||
|
|
||||||
|
- name: Run a command in a pod using local kubectl with inventory variables
|
||||||
|
# Example inventory:
|
||||||
|
# k8s:
|
||||||
|
# hosts:
|
||||||
|
# foo.example.com:
|
||||||
|
# ansible_connection: kubernetes.core.kubectl
|
||||||
|
# ansible_kubectl_kubeconfig: /root/.kube/foo.example.com.config
|
||||||
|
# ansible_kubectl_pod: my-foo-pod
|
||||||
|
# ansible_kubectl_container: my-foo-container
|
||||||
|
# ansible_kubectl_namespace: my-foo-namespace
|
||||||
|
# bar.example.com:
|
||||||
|
# ansible_connection: kubernetes.core.kubectl
|
||||||
|
# ansible_kubectl_kubeconfig: /root/.kube/bar.example.com.config
|
||||||
|
# ansible_kubectl_pod: my-bar-pod
|
||||||
|
# ansible_kubectl_container: my-bar-container
|
||||||
|
# ansible_kubectl_namespace: my-bar-namespace
|
||||||
|
hosts: k8s
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
# be aware that the command is executed as the user that started the container
|
||||||
|
# and requires python to be installed in the image
|
||||||
|
- name: Run a command in a pod
|
||||||
|
ansible.builtin.command: echo "Hello, World!"
|
||||||
|
|
||||||
|
- name: Run a command in a pod using dynamic inventory
|
||||||
|
hosts: localhost
|
||||||
|
gather_facts: no
|
||||||
|
vars:
|
||||||
|
kubeconfig: /root/.kube/config
|
||||||
|
namespace: my-namespace
|
||||||
|
my_app: my-app
|
||||||
|
tasks:
|
||||||
|
- name: Get My App pod info based on label
|
||||||
|
kubernetes.core.k8s_info:
|
||||||
|
kubeconfig: "{{ kubeconfig }}"
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
kind: Pod
|
||||||
|
label_selectors: app.kubernetes.io/name = "{{ my_app }}"
|
||||||
|
register: my_app_pod
|
||||||
|
|
||||||
|
- name: Get My App pod name
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
my_app_pod_name: "{{ my_app_pod.resources[0].metadata.name }}"
|
||||||
|
|
||||||
|
- name: Add My App pod to inventory
|
||||||
|
ansible.builtin.add_host:
|
||||||
|
name: "{{ my_app_pod_name }}"
|
||||||
|
ansible_connection: kubernetes.core.kubectl
|
||||||
|
ansible_kubectl_kubeconfig: "{{ kubeconfig }}"
|
||||||
|
ansible_kubectl_pod: "{{ my_app_pod_name }}"
|
||||||
|
ansible_kubectl_namespace: "{{ namespace }}"
|
||||||
|
|
||||||
|
- name: Run a command in My App pod
|
||||||
|
# be aware that the command is executed as the user that started the container
|
||||||
|
# and requires python to be installed in the image
|
||||||
|
ansible.builtin.command: echo "Hello, World!"
|
||||||
|
delegate_to: "{{ my_app_pod_name }}"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -354,7 +452,7 @@ Status
|
|||||||
Authors
|
Authors
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
|
|
||||||
- xuxinkun
|
- xuxinkun (@xuxinkun)
|
||||||
|
|
||||||
|
|
||||||
.. hint::
|
.. hint::
|
||||||
|
|||||||
222
docs/kubernetes.core.kustomize_lookup.rst
Normal file
222
docs/kubernetes.core.kustomize_lookup.rst
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
.. _kubernetes.core.kustomize_lookup:
|
||||||
|
|
||||||
|
|
||||||
|
*************************
|
||||||
|
kubernetes.core.kustomize
|
||||||
|
*************************
|
||||||
|
|
||||||
|
**Build a set of kubernetes resources using a 'kustomization.yaml' file.**
|
||||||
|
|
||||||
|
|
||||||
|
Version added: 2.2.0
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:local:
|
||||||
|
:depth: 1
|
||||||
|
|
||||||
|
|
||||||
|
Synopsis
|
||||||
|
--------
|
||||||
|
- Uses the kustomize or the kubectl tool.
|
||||||
|
- Return the result of ``kustomize build`` or ``kubectl kustomize``.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
The below requirements are needed on the local Ansible controller node that executes this lookup.
|
||||||
|
|
||||||
|
- python >= 3.6
|
||||||
|
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<table border=0 cellpadding=0 class="documentation-table">
|
||||||
|
<tr>
|
||||||
|
<th colspan="1">Parameter</th>
|
||||||
|
<th>Choices/<font color="blue">Defaults</font></th>
|
||||||
|
<th>Configuration</th>
|
||||||
|
<th width="100%">Comments</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>binary_path</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">-</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The path of a kustomize or kubectl binary to use.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>dir</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">-</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<b>Default:</b><br/><div style="color: blue">"."</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The directory path containing 'kustomization.yaml', or a git repository URL with a path suffix specifying same with respect to the repository root.</div>
|
||||||
|
<div>If omitted, '.' is assumed.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>enable_helm</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">-</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<b>Default:</b><br/><div style="color: blue">"False"</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Enable the helm chart inflation generator</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>environment</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">raw</span>
|
||||||
|
</div>
|
||||||
|
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.2.0</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<b>Default:</b><br/><div style="color: blue">{}</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>The environment variables to pass to the kustomize or kubectl command.</div>
|
||||||
|
<div>This can be a dictionary or a string in the format key=value, multiple pairs separated by space.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>opt_dirs</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">-</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>An optional list of directories to search for the executable in addition to PATH.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
|
Notes
|
||||||
|
-----
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
- If both kustomize and kubectl are part of the PATH, kustomize will be used by the plugin.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
- name: Run lookup using kustomize
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
resources: "{{ lookup('kubernetes.core.kustomize', binary_path='/path/to/kustomize') }}"
|
||||||
|
|
||||||
|
- name: Run lookup using kubectl kustomize
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
resources: "{{ lookup('kubernetes.core.kustomize', binary_path='/path/to/kubectl') }}"
|
||||||
|
|
||||||
|
- name: Create kubernetes resources for lookup output
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
definition: "{{ lookup('kubernetes.core.kustomize', dir='/path/to/kustomization') }}"
|
||||||
|
|
||||||
|
- name: Create kubernetes resources for lookup output with `--enable-helm` set
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
definition: "{{ lookup('kubernetes.core.kustomize', dir='/path/to/kustomization', enable_helm=True) }}"
|
||||||
|
|
||||||
|
- name: Create kubernetes resources for lookup output with environment variables in string format
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
definition: "{{ lookup('kubernetes.core.kustomize', binary_path='/path/to/kubectl', environment='HTTP_PROXY=http://proxy.example.com:3128') }}"
|
||||||
|
|
||||||
|
- name: Create kubernetes resources for lookup output with environment variables in dict format
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
definition: "{{ lookup('kubernetes.core.kustomize', binary_path='/path/to/kubectl', environment={'HTTP_PROXY': 'http://proxy.example.com:3128'}) }}"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Return Values
|
||||||
|
-------------
|
||||||
|
Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this lookup:
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<table border=0 cellpadding=0 class="documentation-table">
|
||||||
|
<tr>
|
||||||
|
<th colspan="1">Key</th>
|
||||||
|
<th>Returned</th>
|
||||||
|
<th width="100%">Description</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||||
|
<b>_list</b>
|
||||||
|
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">string</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
<td>
|
||||||
|
<div>YAML string for the object definitions returned from the tool execution.</div>
|
||||||
|
<br/>
|
||||||
|
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||||
|
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">{'kind': 'ConfigMap', 'apiVersion': 'v1', 'metadata': {'name': 'my-config-map', 'namespace': 'default'}, 'data': {'key1': 'val1'}}</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<br/><br/>
|
||||||
|
|
||||||
|
|
||||||
|
Status
|
||||||
|
------
|
||||||
|
|
||||||
|
|
||||||
|
Authors
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
- Aubin Bikouo (@abikouo)
|
||||||
|
|
||||||
|
|
||||||
|
.. hint::
|
||||||
|
Configuration entries for each entry type have a low to high priority order. For example, a variable that is lower in the list will override a variable that is higher up.
|
||||||
@@ -9,8 +9,8 @@ authors:
|
|||||||
- mmazur (https://github.com/mmazur)
|
- mmazur (https://github.com/mmazur)
|
||||||
- jamescassell (https://github.com/jamescassell)
|
- jamescassell (https://github.com/jamescassell)
|
||||||
description: Kubernetes Collection for Ansible.
|
description: Kubernetes Collection for Ansible.
|
||||||
documentation: ''
|
documentation: ""
|
||||||
homepage: ''
|
homepage: ""
|
||||||
issues: https://github.com/ansible-collections/kubernetes.core/issues
|
issues: https://github.com/ansible-collections/kubernetes.core/issues
|
||||||
license_file: LICENSE
|
license_file: LICENSE
|
||||||
namespace: kubernetes
|
namespace: kubernetes
|
||||||
@@ -25,7 +25,7 @@ tags:
|
|||||||
- openshift
|
- openshift
|
||||||
- okd
|
- okd
|
||||||
- cluster
|
- cluster
|
||||||
version: 2.1.0
|
version: 6.2.0
|
||||||
build_ignore:
|
build_ignore:
|
||||||
- .DS_Store
|
- .DS_Store
|
||||||
- '*.tar.gz'
|
- "*.tar.gz"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
requires_ansible: '>=2.9.17'
|
requires_ansible: '>=2.16.0'
|
||||||
|
|
||||||
action_groups:
|
action_groups:
|
||||||
helm:
|
helm:
|
||||||
@@ -9,43 +9,22 @@ action_groups:
|
|||||||
k8s:
|
k8s:
|
||||||
- k8s
|
- k8s
|
||||||
- k8s_exec
|
- k8s_exec
|
||||||
- k8s_facts
|
|
||||||
- k8s_info
|
- k8s_info
|
||||||
- k8s_log
|
- k8s_log
|
||||||
- k8s_scale
|
- k8s_scale
|
||||||
- k8s_service
|
- k8s_service
|
||||||
|
- k8s_cp
|
||||||
|
- k8s_drain
|
||||||
|
|
||||||
plugin_routing:
|
plugin_routing:
|
||||||
action:
|
|
||||||
helm:
|
|
||||||
redirect: kubernetes.core.k8s_info
|
|
||||||
helm_info:
|
|
||||||
redirect: kubernetes.core.k8s_info
|
|
||||||
helm_plugin:
|
|
||||||
redirect: kubernetes.core.k8s_info
|
|
||||||
helm_plugin_info:
|
|
||||||
redirect: kubernetes.core.k8s_info
|
|
||||||
helm_repository:
|
|
||||||
redirect: kubernetes.core.k8s_info
|
|
||||||
k8s:
|
|
||||||
redirect: kubernetes.core.k8s_info
|
|
||||||
k8s_cluster_info:
|
|
||||||
redirect: kubernetes.core.k8s_info
|
|
||||||
k8s_event_info:
|
|
||||||
redirect: kubernetes.core.k8s_info
|
|
||||||
k8s_exec:
|
|
||||||
redirect: kubernetes.core.k8s_info
|
|
||||||
k8s_log:
|
|
||||||
redirect: kubernetes.core.k8s_info
|
|
||||||
k8s_rollback:
|
|
||||||
redirect: kubernetes.core.k8s_info
|
|
||||||
k8s_scale:
|
|
||||||
redirect: kubernetes.core.k8s_info
|
|
||||||
k8s_service:
|
|
||||||
redirect: kubernetes.core.k8s_info
|
|
||||||
inventory:
|
inventory:
|
||||||
openshift:
|
openshift:
|
||||||
redirect: community.okd.openshift
|
redirect: community.okd.openshift
|
||||||
|
k8s:
|
||||||
|
tombstone:
|
||||||
|
removal_version: 6.0.0
|
||||||
|
warning_text: >-
|
||||||
|
The k8s inventory plugin was slated for deprecation in 3.3.0 and has been removed in release 6.0.0. Use kubernetes.core.k8s_info and ansible.builtin.add_host instead.
|
||||||
modules:
|
modules:
|
||||||
k8s_auth:
|
k8s_auth:
|
||||||
redirect: community.okd.k8s_auth
|
redirect: community.okd.k8s_auth
|
||||||
|
|||||||
@@ -1,254 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Converge
|
|
||||||
hosts: localhost
|
|
||||||
connection: local
|
|
||||||
|
|
||||||
collections:
|
|
||||||
- kubernetes.core
|
|
||||||
|
|
||||||
vars_files:
|
|
||||||
- vars/main.yml
|
|
||||||
|
|
||||||
tasks:
|
|
||||||
- name: Verify cluster is working.
|
|
||||||
k8s_info:
|
|
||||||
namespace: kube-system
|
|
||||||
kind: Pod
|
|
||||||
register: pod_list
|
|
||||||
|
|
||||||
- name: Verify cluster has more than 5 pods running.
|
|
||||||
assert:
|
|
||||||
that: (pod_list.resources | count) > 5
|
|
||||||
|
|
||||||
- name: Include access_review.yml
|
|
||||||
include_tasks:
|
|
||||||
file: tasks/access_review.yml
|
|
||||||
apply:
|
|
||||||
tags: [ access_review, k8s ]
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
- name: Include append_hash.yml
|
|
||||||
include_tasks:
|
|
||||||
file: tasks/append_hash.yml
|
|
||||||
apply:
|
|
||||||
tags: [ append_hash, k8s ]
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
- name: Include apply.yml
|
|
||||||
include_tasks:
|
|
||||||
file: tasks/apply.yml
|
|
||||||
apply:
|
|
||||||
tags: [ apply, k8s ]
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
- name: Include cluster_info.yml
|
|
||||||
include_tasks:
|
|
||||||
file: tasks/cluster_info.yml
|
|
||||||
apply:
|
|
||||||
tags: [ cluster_info, k8s ]
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
- name: Include crd.yml
|
|
||||||
include_tasks:
|
|
||||||
file: tasks/crd.yml
|
|
||||||
apply:
|
|
||||||
tags: [ crd, k8s ]
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
- name: Include delete.yml
|
|
||||||
include_tasks:
|
|
||||||
file: tasks/delete.yml
|
|
||||||
apply:
|
|
||||||
tags: [ delete, k8s ]
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
- name: Include exec.yml
|
|
||||||
include_tasks:
|
|
||||||
file: tasks/exec.yml
|
|
||||||
apply:
|
|
||||||
tags: [ exec, k8s ]
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
- name: Include full.yml
|
|
||||||
include_tasks:
|
|
||||||
file: tasks/full.yml
|
|
||||||
apply:
|
|
||||||
tags: [ full, k8s ]
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
- name: Include gc.yml
|
|
||||||
include_tasks:
|
|
||||||
file: tasks/gc.yml
|
|
||||||
apply:
|
|
||||||
tags: [ gc, k8s ]
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
- name: Include info.yml
|
|
||||||
include_tasks:
|
|
||||||
file: tasks/info.yml
|
|
||||||
apply:
|
|
||||||
tags: [ info, k8s ]
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
- name: Include json_patch.yml
|
|
||||||
include_tasks:
|
|
||||||
file: tasks/json_patch.yml
|
|
||||||
apply:
|
|
||||||
tags: [ json_patch, k8s ]
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
- name: Include lists.yml
|
|
||||||
include_tasks:
|
|
||||||
file: tasks/lists.yml
|
|
||||||
apply:
|
|
||||||
tags: [ lists, k8s ]
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
- name: Include log.yml
|
|
||||||
include_tasks:
|
|
||||||
file: tasks/log.yml
|
|
||||||
apply:
|
|
||||||
tags: [ log, k8s ]
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
- name: Include rollback.yml
|
|
||||||
include_tasks:
|
|
||||||
file: tasks/rollback.yml
|
|
||||||
apply:
|
|
||||||
tags: [ rollback, k8s ]
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
- name: Include scale.yml
|
|
||||||
include_tasks:
|
|
||||||
file: tasks/scale.yml
|
|
||||||
apply:
|
|
||||||
tags: [ scale, k8s ]
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
- name: Include template.yml
|
|
||||||
include_tasks:
|
|
||||||
file: tasks/template.yml
|
|
||||||
apply:
|
|
||||||
tags: [ template, k8s ]
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
- name: Include waiter.yml
|
|
||||||
include_tasks:
|
|
||||||
file: tasks/waiter.yml
|
|
||||||
apply:
|
|
||||||
tags: [ waiter, k8s ]
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
|
|
||||||
- name: Include merge_type.yml
|
|
||||||
include_tasks:
|
|
||||||
file: tasks/merge_type.yml
|
|
||||||
apply:
|
|
||||||
tags: [ merge_type, k8s ]
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
|
|
||||||
- name: Include patched.yml
|
|
||||||
include_tasks:
|
|
||||||
file: tasks/patched.yml
|
|
||||||
apply:
|
|
||||||
tags: [ patched, k8s ]
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
|
|
||||||
- name: Include lookup_k8s.yml
|
|
||||||
include_tasks:
|
|
||||||
file: tasks/lookup_k8s.yml
|
|
||||||
apply:
|
|
||||||
tags: [ lookup, k8s ]
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
|
|
||||||
roles:
|
|
||||||
- role: helm
|
|
||||||
tags:
|
|
||||||
- helm
|
|
||||||
|
|
||||||
post_tasks:
|
|
||||||
- name: Ensure namespace exists
|
|
||||||
k8s:
|
|
||||||
api_version: v1
|
|
||||||
kind: Namespace
|
|
||||||
name: inventory
|
|
||||||
|
|
||||||
- name: Add a deployment
|
|
||||||
k8s:
|
|
||||||
definition:
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: inventory
|
|
||||||
namespace: inventory
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: "{{ k8s_pod_name }}"
|
|
||||||
template: "{{ k8s_pod_template }}"
|
|
||||||
wait: yes
|
|
||||||
wait_timeout: 120
|
|
||||||
vars:
|
|
||||||
k8s_pod_name: inventory
|
|
||||||
k8s_pod_image: python
|
|
||||||
k8s_pod_command:
|
|
||||||
- python
|
|
||||||
- '-m'
|
|
||||||
- http.server
|
|
||||||
k8s_pod_env:
|
|
||||||
- name: TEST
|
|
||||||
value: test
|
|
||||||
|
|
||||||
- meta: refresh_inventory
|
|
||||||
|
|
||||||
- name: Verify inventory and connection plugins
|
|
||||||
hosts: namespace_inventory_pods
|
|
||||||
gather_facts: no
|
|
||||||
|
|
||||||
vars:
|
|
||||||
file_content: |
|
|
||||||
Hello world
|
|
||||||
|
|
||||||
tasks:
|
|
||||||
- name: End play if host not running (TODO should we not add these to the inventory?)
|
|
||||||
meta: end_host
|
|
||||||
when: pod_phase != "Running"
|
|
||||||
|
|
||||||
- debug: var=hostvars
|
|
||||||
- setup:
|
|
||||||
|
|
||||||
- debug: var=ansible_facts
|
|
||||||
|
|
||||||
- name: Assert the TEST environment variable was retrieved
|
|
||||||
assert:
|
|
||||||
that: ansible_facts.env.TEST == 'test'
|
|
||||||
|
|
||||||
- name: Copy a file into the host
|
|
||||||
copy:
|
|
||||||
content: '{{ file_content }}'
|
|
||||||
dest: /tmp/test_file
|
|
||||||
|
|
||||||
- name: Retrieve the file from the host
|
|
||||||
slurp:
|
|
||||||
src: /tmp/test_file
|
|
||||||
register: slurped_file
|
|
||||||
|
|
||||||
- name: Assert the file content matches expectations
|
|
||||||
assert:
|
|
||||||
that: (slurped_file.content|b64decode) == file_content
|
|
||||||
|
|
||||||
- name: Delete inventory namespace
|
|
||||||
hosts: localhost
|
|
||||||
connection: local
|
|
||||||
gather_facts: no
|
|
||||||
tasks:
|
|
||||||
- name: Remove inventory namespace
|
|
||||||
k8s:
|
|
||||||
api_version: v1
|
|
||||||
kind: Namespace
|
|
||||||
name: inventory
|
|
||||||
state: absent
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
---
|
|
||||||
driver:
|
|
||||||
name: delegated
|
|
||||||
options:
|
|
||||||
managed: false
|
|
||||||
login_cmd_template: 'docker exec -ti {instance} bash'
|
|
||||||
ansible_connection_options:
|
|
||||||
ansible_connection: docker
|
|
||||||
lint: |
|
|
||||||
set -e
|
|
||||||
yamllint .
|
|
||||||
flake8
|
|
||||||
platforms:
|
|
||||||
- name: instance-kind
|
|
||||||
provisioner:
|
|
||||||
name: ansible
|
|
||||||
log: true
|
|
||||||
config_options:
|
|
||||||
inventory:
|
|
||||||
enable_plugins: kubernetes.core.k8s
|
|
||||||
lint: {}
|
|
||||||
inventory:
|
|
||||||
hosts:
|
|
||||||
plugin: kubernetes.core.k8s
|
|
||||||
host_vars:
|
|
||||||
localhost:
|
|
||||||
ansible_python_interpreter: '{{ ansible_playbook_python }}'
|
|
||||||
env:
|
|
||||||
ANSIBLE_FORCE_COLOR: 'true'
|
|
||||||
options:
|
|
||||||
vvv: True
|
|
||||||
scenario:
|
|
||||||
name: default
|
|
||||||
test_sequence:
|
|
||||||
- dependency
|
|
||||||
- lint
|
|
||||||
- syntax
|
|
||||||
- converge
|
|
||||||
- verify
|
|
||||||
dependency:
|
|
||||||
name: galaxy
|
|
||||||
options:
|
|
||||||
requirements-file: requirements.yml
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
---
|
|
||||||
helm_archive_name: "helm-{{ helm_version }}-{{ ansible_system | lower }}-amd64.tar.gz"
|
|
||||||
helm_binary: "/tmp/helm/{{ ansible_system | lower }}-amd64/helm"
|
|
||||||
helm_namespace: helm
|
|
||||||
|
|
||||||
tiller_namespace: tiller
|
|
||||||
tiller_cluster_role: cluster-admin
|
|
||||||
|
|
||||||
chart_test: "ingress-nginx"
|
|
||||||
chart_test_local_path: "nginx-ingress"
|
|
||||||
chart_test_version: 3.8.0
|
|
||||||
chart_test_version_local_path: 1.32.0
|
|
||||||
chart_test_version_upgrade: 3.9.0
|
|
||||||
chart_test_version_upgrade_local_path: 1.33.0
|
|
||||||
chart_test_repo: "https://kubernetes.github.io/ingress-nginx"
|
|
||||||
chart_test_git_repo: "http://github.com/helm/charts.git"
|
|
||||||
chart_test_values:
|
|
||||||
revisionHistoryLimit: 0
|
|
||||||
myValue: "changed"
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Init Helm folders
|
|
||||||
file:
|
|
||||||
path: /tmp/helm/
|
|
||||||
state: directory
|
|
||||||
|
|
||||||
- name: Unarchive Helm binary
|
|
||||||
unarchive:
|
|
||||||
src: 'https://get.helm.sh/{{ helm_archive_name }}'
|
|
||||||
dest: /tmp/helm/
|
|
||||||
remote_src: yes
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Test CRDs
|
|
||||||
vars:
|
|
||||||
test_chart: "test-crds"
|
|
||||||
block:
|
|
||||||
- name: Create namespace
|
|
||||||
k8s:
|
|
||||||
kind: Namespace
|
|
||||||
name: "{{ helm_namespace }}"
|
|
||||||
|
|
||||||
- name: Copy test chart
|
|
||||||
copy:
|
|
||||||
src: "{{ test_chart }}"
|
|
||||||
dest: "/tmp/helm_test_crds/"
|
|
||||||
|
|
||||||
- name: Install chart while skipping CRDs
|
|
||||||
helm:
|
|
||||||
chart_ref: "/tmp/helm_test_crds/{{ test_chart }}"
|
|
||||||
namespace: "{{ helm_namespace }}"
|
|
||||||
name: test-crds
|
|
||||||
skip_crds: true
|
|
||||||
register: install
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- install is changed
|
|
||||||
- install.status.name == "test-crds"
|
|
||||||
|
|
||||||
- name: Fail to create custom resource
|
|
||||||
k8s:
|
|
||||||
definition:
|
|
||||||
apiVersion: example.com/v1
|
|
||||||
kind: Foo
|
|
||||||
metadata:
|
|
||||||
namespace: "{{ helm_namespace }}"
|
|
||||||
name: test-foo
|
|
||||||
foobar: footest
|
|
||||||
ignore_errors: true
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- result is failed
|
|
||||||
- "result.msg.startswith('Failed to find exact match for example.com/v1.Foo')"
|
|
||||||
|
|
||||||
# Helm won't install CRDs into an existing release, so we need to delete this, first
|
|
||||||
- name: Uninstall chart
|
|
||||||
helm:
|
|
||||||
namespace: "{{ helm_namespace }}"
|
|
||||||
name: test-crds
|
|
||||||
state: absent
|
|
||||||
|
|
||||||
- name: Install chart with CRDs
|
|
||||||
helm:
|
|
||||||
chart_ref: "/tmp/helm_test_crds/{{ test_chart }}"
|
|
||||||
namespace: "{{ helm_namespace }}"
|
|
||||||
name: test-crds
|
|
||||||
|
|
||||||
- name: Create custom resource
|
|
||||||
k8s:
|
|
||||||
definition:
|
|
||||||
apiVersion: example.com/v1
|
|
||||||
kind: Foo
|
|
||||||
metadata:
|
|
||||||
namespace: "{{ helm_namespace }}"
|
|
||||||
name: test-foo
|
|
||||||
foobar: footest
|
|
||||||
register: result
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- result is changed
|
|
||||||
- result.result.foobar == "footest"
|
|
||||||
|
|
||||||
always:
|
|
||||||
- name: Remove chart
|
|
||||||
file:
|
|
||||||
path: "/tmp/helm_test_crds"
|
|
||||||
state: absent
|
|
||||||
ignore_errors: true
|
|
||||||
|
|
||||||
- name: Remove namespace
|
|
||||||
k8s:
|
|
||||||
kind: Namespace
|
|
||||||
name: "{{ helm_namespace }}"
|
|
||||||
state: absent
|
|
||||||
wait: true
|
|
||||||
wait_timeout: 180
|
|
||||||
ignore_errors: true
|
|
||||||
|
|
||||||
# CRDs aren't deleted with a namespace, so we need to manually delete it
|
|
||||||
- name: Remove CRD
|
|
||||||
k8s:
|
|
||||||
kind: CustomResourceDefinition
|
|
||||||
name: foos.example.com
|
|
||||||
state: absent
|
|
||||||
ignore_errors: true
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Install Chart from URL
|
|
||||||
include_tasks: "../tests_chart.yml"
|
|
||||||
vars:
|
|
||||||
source: url
|
|
||||||
chart_source: "https://github.com/kubernetes/ingress-nginx/releases/download/{{ chart_test }}-{{ chart_test_version }}/{{ chart_test }}-{{ chart_test_version }}.tgz"
|
|
||||||
chart_source_upgrade: "https://github.com/kubernetes/ingress-nginx/releases/download/{{ chart_test }}-{{ chart_test_version_upgrade }}/{{ chart_test }}-{{ chart_test_version_upgrade }}.tgz"
|
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Test helm diff functionality
|
|
||||||
vars:
|
|
||||||
test_chart_ref: "/tmp/test-chart"
|
|
||||||
|
|
||||||
block:
|
|
||||||
- name: Install helm diff
|
|
||||||
helm_plugin:
|
|
||||||
state: present
|
|
||||||
plugin_path: https://github.com/databus23/helm-diff
|
|
||||||
|
|
||||||
- name: Copy test chart
|
|
||||||
copy:
|
|
||||||
src: "test-chart/"
|
|
||||||
dest: "{{ test_chart_ref }}"
|
|
||||||
|
|
||||||
- name: Install local chart
|
|
||||||
helm:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
name: test-chart
|
|
||||||
namespace: "{{ helm_namespace }}"
|
|
||||||
chart_ref: "{{ test_chart_ref }}"
|
|
||||||
create_namespace: yes
|
|
||||||
register: install
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- install is changed
|
|
||||||
|
|
||||||
- name: Modify local chart
|
|
||||||
blockinfile:
|
|
||||||
create: yes
|
|
||||||
path: "{{ test_chart_ref }}/templates/anothermap.yaml"
|
|
||||||
block: !unsafe |
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: test-chart-another-configmap
|
|
||||||
data:
|
|
||||||
foo: {{ .Values.foo | default "bar" }}
|
|
||||||
|
|
||||||
- name: Upgrade local chart with modifications
|
|
||||||
helm:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
name: test-chart
|
|
||||||
namespace: "{{ helm_namespace }}"
|
|
||||||
chart_ref: "{{ test_chart_ref }}"
|
|
||||||
register: install
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- install is changed
|
|
||||||
|
|
||||||
- name: Upgrade modified local chart idempotency check
|
|
||||||
helm:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
name: test-chart
|
|
||||||
namespace: "{{ helm_namespace }}"
|
|
||||||
chart_ref: "{{ test_chart_ref }}"
|
|
||||||
register: install
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- install is not changed
|
|
||||||
|
|
||||||
- name: Modify values
|
|
||||||
blockinfile:
|
|
||||||
create: yes
|
|
||||||
path: "{{ test_chart_ref }}/values.yml"
|
|
||||||
block: |
|
|
||||||
---
|
|
||||||
foo: baz
|
|
||||||
|
|
||||||
- name: Upgrade with values file
|
|
||||||
helm:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
name: test-chart
|
|
||||||
namespace: "{{ helm_namespace }}"
|
|
||||||
chart_ref: "{{ test_chart_ref }}"
|
|
||||||
values_files:
|
|
||||||
- "{{ test_chart_ref }}/values.yml"
|
|
||||||
register: install
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- install is changed
|
|
||||||
|
|
||||||
- name: Upgrade with values file idempotency check
|
|
||||||
helm:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
name: test-chart
|
|
||||||
namespace: "{{ helm_namespace }}"
|
|
||||||
chart_ref: "{{ test_chart_ref }}"
|
|
||||||
values_files:
|
|
||||||
- "{{ test_chart_ref }}/values.yml"
|
|
||||||
register: install
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- install is not changed
|
|
||||||
|
|
||||||
- name: Upgrade with values
|
|
||||||
helm:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
name: test-chart
|
|
||||||
namespace: "{{ helm_namespace }}"
|
|
||||||
chart_ref: "{{ test_chart_ref }}"
|
|
||||||
values:
|
|
||||||
foo: gaz
|
|
||||||
register: install
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- install is changed
|
|
||||||
|
|
||||||
- name: Upgrade with values idempotency check
|
|
||||||
helm:
|
|
||||||
binary_path: "{{ helm_binary }}"
|
|
||||||
name: test-chart
|
|
||||||
namespace: "{{ helm_namespace }}"
|
|
||||||
chart_ref: "{{ test_chart_ref }}"
|
|
||||||
values:
|
|
||||||
foo: gaz
|
|
||||||
register: install
|
|
||||||
|
|
||||||
- assert:
|
|
||||||
that:
|
|
||||||
- install is not changed
|
|
||||||
|
|
||||||
always:
|
|
||||||
- name: Remove chart directory
|
|
||||||
file:
|
|
||||||
path: "{{ test_chart_ref }}"
|
|
||||||
state: absent
|
|
||||||
ignore_errors: yes
|
|
||||||
|
|
||||||
- name: Uninstall helm diff
|
|
||||||
helm_plugin:
|
|
||||||
state: absent
|
|
||||||
plugin_name: diff
|
|
||||||
ignore_errors: yes
|
|
||||||
|
|
||||||
- name: Remove helm namespace
|
|
||||||
k8s:
|
|
||||||
api_version: v1
|
|
||||||
kind: Namespace
|
|
||||||
name: "{{ helm_namespace }}"
|
|
||||||
state: absent
|
|
||||||
wait: yes
|
|
||||||
wait_timeout: 180
|
|
||||||
ignore_errors: yes
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
---
|
|
||||||
- block:
|
|
||||||
- set_fact:
|
|
||||||
delete_namespace: delete
|
|
||||||
|
|
||||||
- name: Ensure namespace exists
|
|
||||||
k8s:
|
|
||||||
definition:
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: "{{ delete_namespace }}"
|
|
||||||
|
|
||||||
- name: Add a daemonset
|
|
||||||
k8s:
|
|
||||||
definition:
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: DaemonSet
|
|
||||||
metadata:
|
|
||||||
name: delete-daemonset
|
|
||||||
namespace: "{{ delete_namespace }}"
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: "{{ k8s_pod_name }}"
|
|
||||||
template: "{{ k8s_pod_template }}"
|
|
||||||
wait: yes
|
|
||||||
wait_timeout: 180
|
|
||||||
vars:
|
|
||||||
k8s_pod_name: delete-ds
|
|
||||||
k8s_pod_image: gcr.io/kuar-demo/kuard-amd64:1
|
|
||||||
register: ds
|
|
||||||
|
|
||||||
- name: Check that daemonset wait worked
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- ds.result.status.currentNumberScheduled == ds.result.status.desiredNumberScheduled
|
|
||||||
|
|
||||||
- name: Check if pods exist
|
|
||||||
k8s_info:
|
|
||||||
namespace: "{{ delete_namespace }}"
|
|
||||||
kind: Pod
|
|
||||||
label_selectors:
|
|
||||||
- "app={{ k8s_pod_name }}"
|
|
||||||
vars:
|
|
||||||
k8s_pod_name: delete-ds
|
|
||||||
register: pods_create
|
|
||||||
|
|
||||||
- name: Assert that there are pods
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- pods_create.resources
|
|
||||||
|
|
||||||
- name: Remove the daemonset
|
|
||||||
k8s:
|
|
||||||
kind: DaemonSet
|
|
||||||
name: delete-daemonset
|
|
||||||
namespace: "{{ delete_namespace }}"
|
|
||||||
state: absent
|
|
||||||
wait: yes
|
|
||||||
|
|
||||||
- name: Show status of pods
|
|
||||||
k8s_info:
|
|
||||||
namespace: "{{ delete_namespace }}"
|
|
||||||
kind: Pod
|
|
||||||
label_selectors:
|
|
||||||
- "app={{ k8s_pod_name }}"
|
|
||||||
vars:
|
|
||||||
k8s_pod_name: delete-ds
|
|
||||||
|
|
||||||
- name: Wait for background deletion
|
|
||||||
pause:
|
|
||||||
seconds: 30
|
|
||||||
|
|
||||||
- name: Check if pods still exist
|
|
||||||
k8s_info:
|
|
||||||
namespace: "{{ delete_namespace }}"
|
|
||||||
kind: Pod
|
|
||||||
label_selectors:
|
|
||||||
- "app={{ k8s_pod_name }}"
|
|
||||||
vars:
|
|
||||||
k8s_pod_name: delete-ds
|
|
||||||
register: pods_delete
|
|
||||||
|
|
||||||
- name: Assert that deleting the daemonset deleted the pods
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- not pods_delete.resources
|
|
||||||
|
|
||||||
always:
|
|
||||||
- name: Remove namespace
|
|
||||||
k8s:
|
|
||||||
kind: Namespace
|
|
||||||
name: "{{ delete_namespace }}"
|
|
||||||
state: absent
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
---
|
|
||||||
- vars:
|
|
||||||
exec_namespace: k8s-exec
|
|
||||||
pod: sleep-pod
|
|
||||||
exec_pod_definition:
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
name: "{{ pod }}"
|
|
||||||
namespace: "{{ exec_namespace }}"
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: sleeper
|
|
||||||
image: busybox
|
|
||||||
command: ["sleep", "infinity"]
|
|
||||||
|
|
||||||
block:
|
|
||||||
- name: "Ensure that {{ exec_namespace }} namespace exists"
|
|
||||||
k8s:
|
|
||||||
kind: Namespace
|
|
||||||
name: "{{ exec_namespace }}"
|
|
||||||
|
|
||||||
- name: "Create a pod"
|
|
||||||
k8s:
|
|
||||||
definition: "{{ exec_pod_definition }}"
|
|
||||||
wait: yes
|
|
||||||
wait_sleep: 1
|
|
||||||
wait_timeout: 30
|
|
||||||
|
|
||||||
- name: "Execute a command"
|
|
||||||
k8s_exec:
|
|
||||||
pod: "{{ pod }}"
|
|
||||||
namespace: "{{ exec_namespace }}"
|
|
||||||
command: cat /etc/resolv.conf
|
|
||||||
register: output
|
|
||||||
|
|
||||||
- name: "Show k8s_exec output"
|
|
||||||
debug:
|
|
||||||
var: output
|
|
||||||
|
|
||||||
- name: "Assert k8s_exec output is correct"
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- "'nameserver' in output.stdout"
|
|
||||||
|
|
||||||
- name: Check if rc is returned for the given command
|
|
||||||
k8s_exec:
|
|
||||||
namespace: "{{ exec_namespace }}"
|
|
||||||
pod: "{{ pod }}"
|
|
||||||
command: 'false'
|
|
||||||
register: command_status
|
|
||||||
ignore_errors: True
|
|
||||||
|
|
||||||
- name: Check last command status
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- command_status.return_code != 0
|
|
||||||
|
|
||||||
always:
|
|
||||||
- name: "Cleanup namespace"
|
|
||||||
k8s:
|
|
||||||
kind: Namespace
|
|
||||||
name: "{{ exec_namespace }}"
|
|
||||||
state: absent
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
---
|
|
||||||
- block:
|
|
||||||
- name: ensure that k8s-log namespace exists
|
|
||||||
k8s:
|
|
||||||
kind: Namespace
|
|
||||||
name: k8s-log
|
|
||||||
|
|
||||||
- name: create hello-world deployment
|
|
||||||
k8s:
|
|
||||||
wait: yes
|
|
||||||
definition:
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: hello-world
|
|
||||||
namespace: k8s-log
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: hello-world
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: hello-world
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- image: busybox
|
|
||||||
name: hello-world
|
|
||||||
command: ['sh']
|
|
||||||
args: ['-c', 'while true ; do echo "hello world" && sleep 10 ; done']
|
|
||||||
restartPolicy: Always
|
|
||||||
|
|
||||||
- name: retrieve the log by providing the deployment
|
|
||||||
k8s_log:
|
|
||||||
api_version: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
namespace: k8s-log
|
|
||||||
name: hello-world
|
|
||||||
register: deployment_log
|
|
||||||
|
|
||||||
- name: verify that the log can be retrieved via the deployment
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- "'hello world' in deployment_log.log"
|
|
||||||
- item == 'hello world' or item == ''
|
|
||||||
with_items: '{{ deployment_log.log_lines }}'
|
|
||||||
|
|
||||||
- name: retrieve the log with a label selector
|
|
||||||
k8s_log:
|
|
||||||
namespace: k8s-log
|
|
||||||
label_selectors:
|
|
||||||
- 'app=hello-world'
|
|
||||||
register: label_selector_log
|
|
||||||
|
|
||||||
- name: verify that the log can be retrieved via the label
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- "'hello world' in label_selector_log.log"
|
|
||||||
- item == 'hello world' or item == ''
|
|
||||||
with_items: '{{ label_selector_log.log_lines }}'
|
|
||||||
|
|
||||||
- name: get the hello-world pod
|
|
||||||
k8s_info:
|
|
||||||
kind: Pod
|
|
||||||
namespace: k8s-log
|
|
||||||
label_selectors:
|
|
||||||
- 'app=hello-world'
|
|
||||||
register: k8s_log_pods
|
|
||||||
|
|
||||||
- name: retrieve the log directly with the pod name
|
|
||||||
k8s_log:
|
|
||||||
namespace: k8s-log
|
|
||||||
name: '{{ k8s_log_pods.resources.0.metadata.name }}'
|
|
||||||
register: pod_log
|
|
||||||
|
|
||||||
- name: verify that the log can be retrieved via the pod name
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- "'hello world' in pod_log.log"
|
|
||||||
- item == 'hello world' or item == ''
|
|
||||||
with_items: '{{ pod_log.log_lines }}'
|
|
||||||
|
|
||||||
- name: Create a job that calculates 7
|
|
||||||
k8s:
|
|
||||||
state: present
|
|
||||||
wait: yes
|
|
||||||
wait_timeout: 120
|
|
||||||
wait_condition:
|
|
||||||
type: Complete
|
|
||||||
status: 'True'
|
|
||||||
definition:
|
|
||||||
apiVersion: batch/v1
|
|
||||||
kind: Job
|
|
||||||
metadata:
|
|
||||||
name: int-log
|
|
||||||
namespace: k8s-log
|
|
||||||
spec:
|
|
||||||
template:
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: busybox
|
|
||||||
image: busybox
|
|
||||||
command: ["echo", "7"]
|
|
||||||
restartPolicy: Never
|
|
||||||
backoffLimit: 4
|
|
||||||
|
|
||||||
- name: retrieve logs from the job
|
|
||||||
k8s_log:
|
|
||||||
api_version: batch/v1
|
|
||||||
kind: Job
|
|
||||||
namespace: k8s-log
|
|
||||||
name: int-log
|
|
||||||
register: job_logs
|
|
||||||
|
|
||||||
- name: verify the log was successfully retrieved
|
|
||||||
assert:
|
|
||||||
that: job_logs.log_lines[0] == "7"
|
|
||||||
|
|
||||||
always:
|
|
||||||
- name: ensure that namespace is removed
|
|
||||||
k8s:
|
|
||||||
kind: Namespace
|
|
||||||
name: k8s-log
|
|
||||||
state: absent
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
---
|
|
||||||
- block:
|
|
||||||
# https://github.com/ansible-collections/kubernetes.core/issues/9
|
|
||||||
- name: Create a namespace with label
|
|
||||||
kubernetes.core.k8s:
|
|
||||||
definition:
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: "app-development-one"
|
|
||||||
labels:
|
|
||||||
namespace_label: "app_development"
|
|
||||||
|
|
||||||
- set_fact:
|
|
||||||
namespace_info: "{{ lookup('kubernetes.core.k8s', kind='Namespace', label_selector='namespace_label=app_development') }}"
|
|
||||||
|
|
||||||
- name: Check if the returned value is list with a single element
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- namespace_info is iterable
|
|
||||||
- not namespace_info is string
|
|
||||||
- not namespace_info is mapping
|
|
||||||
- namespace_info | length == 1
|
|
||||||
|
|
||||||
- name: Create another namespace with label
|
|
||||||
kubernetes.core.k8s:
|
|
||||||
definition:
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: "app-development-two"
|
|
||||||
labels:
|
|
||||||
namespace_label: "app_development"
|
|
||||||
|
|
||||||
- set_fact:
|
|
||||||
namespace_info: "{{ lookup('kubernetes.core.k8s', kind='Namespace', label_selector='namespace_label=app_development') }}"
|
|
||||||
|
|
||||||
- name: Check if the returned value is list with 2 elements
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- namespace_info is iterable
|
|
||||||
- not namespace_info is string
|
|
||||||
- not namespace_info is mapping
|
|
||||||
- namespace_info | length == 2
|
|
||||||
|
|
||||||
always:
|
|
||||||
- name: Ensure that namespace is removed
|
|
||||||
k8s:
|
|
||||||
kind: Namespace
|
|
||||||
name: "{{ item }}"
|
|
||||||
state: absent
|
|
||||||
with_items:
|
|
||||||
- app-development-one
|
|
||||||
- app-development-two
|
|
||||||
@@ -1,217 +0,0 @@
|
|||||||
---
|
|
||||||
- block:
|
|
||||||
- name: Set variables
|
|
||||||
set_fact:
|
|
||||||
namespace: "testingrollback"
|
|
||||||
|
|
||||||
- name: Create a namespace
|
|
||||||
k8s:
|
|
||||||
name: "{{ namespace }}"
|
|
||||||
kind: Namespace
|
|
||||||
api_version: v1
|
|
||||||
apply: no
|
|
||||||
register: output
|
|
||||||
|
|
||||||
- name: show output
|
|
||||||
debug:
|
|
||||||
var: output
|
|
||||||
|
|
||||||
- name: Create a deployment
|
|
||||||
k8s:
|
|
||||||
state: present
|
|
||||||
wait: yes
|
|
||||||
inline: &deploy
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: nginx-deploy
|
|
||||||
labels:
|
|
||||||
app: nginx
|
|
||||||
namespace: "{{ namespace }}"
|
|
||||||
spec:
|
|
||||||
replicas: 3
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: nginx
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: nginx
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: nginx
|
|
||||||
image: nginx:1.17
|
|
||||||
ports:
|
|
||||||
- containerPort: 80
|
|
||||||
register: output
|
|
||||||
|
|
||||||
- name: Show output
|
|
||||||
debug:
|
|
||||||
var: output
|
|
||||||
|
|
||||||
- name: Crash the existing deployment
|
|
||||||
k8s:
|
|
||||||
state: present
|
|
||||||
wait: yes
|
|
||||||
definition:
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: nginx-deploy
|
|
||||||
labels:
|
|
||||||
app: nginx
|
|
||||||
namespace: "{{ namespace }}"
|
|
||||||
spec:
|
|
||||||
replicas: 3
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: nginx
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: nginx
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: nginx
|
|
||||||
image: nginx:1.0.23449928384992872784
|
|
||||||
ports:
|
|
||||||
- containerPort: 80
|
|
||||||
ignore_errors: yes
|
|
||||||
register: output
|
|
||||||
|
|
||||||
- name: Rolling Back the crashed deployment
|
|
||||||
k8s_rollback:
|
|
||||||
api_version: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
name: nginx-deploy
|
|
||||||
namespace: "{{ namespace }}"
|
|
||||||
when: output.failed
|
|
||||||
register: output
|
|
||||||
|
|
||||||
- name: Show output
|
|
||||||
debug:
|
|
||||||
var: output
|
|
||||||
|
|
||||||
- name: Create a DaemonSet
|
|
||||||
k8s:
|
|
||||||
state: present
|
|
||||||
wait: yes
|
|
||||||
definition:
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: DaemonSet
|
|
||||||
metadata:
|
|
||||||
name: fluentd-elasticsearch
|
|
||||||
namespace: "{{ namespace }}"
|
|
||||||
labels:
|
|
||||||
k8s-app: fluentd-logging
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
name: fluentd-elasticsearch
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
name: fluentd-elasticsearch
|
|
||||||
spec:
|
|
||||||
tolerations:
|
|
||||||
- key: node-role.kubernetes.io/master
|
|
||||||
effect: NoSchedule
|
|
||||||
containers:
|
|
||||||
- name: fluentd-elasticsearch
|
|
||||||
image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 200Mi
|
|
||||||
requests:
|
|
||||||
cpu: 100m
|
|
||||||
memory: 200Mi
|
|
||||||
volumeMounts:
|
|
||||||
- name: varlog
|
|
||||||
mountPath: /var/log
|
|
||||||
- name: varlibdockercontainers
|
|
||||||
mountPath: /var/lib/docker/containers
|
|
||||||
readOnly: true
|
|
||||||
terminationGracePeriodSeconds: 30
|
|
||||||
volumes:
|
|
||||||
- name: varlog
|
|
||||||
hostPath:
|
|
||||||
path: /var/log
|
|
||||||
- name: varlibdockercontainers
|
|
||||||
hostPath:
|
|
||||||
path: /var/lib/docker/containers
|
|
||||||
register: output
|
|
||||||
|
|
||||||
- name: Show output
|
|
||||||
debug:
|
|
||||||
var: output
|
|
||||||
|
|
||||||
- name: Crash the existing DaemonSet
|
|
||||||
k8s:
|
|
||||||
state: present
|
|
||||||
wait: yes
|
|
||||||
definition:
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: DaemonSet
|
|
||||||
metadata:
|
|
||||||
name: fluentd-elasticsearch
|
|
||||||
namespace: "{{ namespace }}"
|
|
||||||
labels:
|
|
||||||
k8s-app: fluentd-logging
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
name: fluentd-elasticsearch
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
name: fluentd-elasticsearch
|
|
||||||
spec:
|
|
||||||
tolerations:
|
|
||||||
- key: node-role.kubernetes.io/master
|
|
||||||
effect: NoSchedule
|
|
||||||
containers:
|
|
||||||
- name: fluentd-elasticsearch
|
|
||||||
image: quay.io/fluentd_elasticsearch/fluentd:v2734894949
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
memory: 200Mi
|
|
||||||
requests:
|
|
||||||
cpu: 100m
|
|
||||||
memory: 200Mi
|
|
||||||
volumeMounts:
|
|
||||||
- name: varlog
|
|
||||||
mountPath: /var/log
|
|
||||||
- name: varlibdockercontainers
|
|
||||||
mountPath: /var/lib/docker/containers
|
|
||||||
readOnly: true
|
|
||||||
terminationGracePeriodSeconds: 30
|
|
||||||
volumes:
|
|
||||||
- name: varlog
|
|
||||||
hostPath:
|
|
||||||
path: /var/log
|
|
||||||
- name: varlibdockercontainers
|
|
||||||
hostPath:
|
|
||||||
path: /var/lib/docker/containers
|
|
||||||
ignore_errors: yes
|
|
||||||
register: output
|
|
||||||
|
|
||||||
- name: Rolling Back the crashed DaemonSet
|
|
||||||
k8s_rollback:
|
|
||||||
api_version: apps/v1
|
|
||||||
kind: DaemonSet
|
|
||||||
name: fluentd-elasticsearch
|
|
||||||
namespace: "{{ namespace }}"
|
|
||||||
when: output.failed
|
|
||||||
register: output
|
|
||||||
|
|
||||||
- name: Show output
|
|
||||||
debug:
|
|
||||||
var: output
|
|
||||||
|
|
||||||
always:
|
|
||||||
- name: Delete {{ namespace }} namespace
|
|
||||||
k8s:
|
|
||||||
name: "{{ namespace }}"
|
|
||||||
kind: Namespace
|
|
||||||
api_version: v1
|
|
||||||
state: absent
|
|
||||||
1
plugins/action/k8s_drain.py
Symbolic link
1
plugins/action/k8s_drain.py
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
k8s_info.py
|
||||||
@@ -3,43 +3,64 @@
|
|||||||
# Copyright (c) 2020, Ansible Project
|
# Copyright (c) 2020, Ansible Project
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
import os
|
||||||
|
import platform
|
||||||
import traceback
|
import traceback
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
||||||
|
|
||||||
from ansible.config.manager import ensure_type
|
from ansible.config.manager import ensure_type
|
||||||
from ansible.errors import AnsibleError, AnsibleFileNotFound, AnsibleAction, AnsibleActionFail
|
from ansible.errors import (
|
||||||
|
AnsibleAction,
|
||||||
|
AnsibleActionFail,
|
||||||
|
AnsibleError,
|
||||||
|
AnsibleFileNotFound,
|
||||||
|
)
|
||||||
|
from ansible.module_utils._text import to_bytes, to_native, to_text
|
||||||
from ansible.module_utils.parsing.convert_bool import boolean
|
from ansible.module_utils.parsing.convert_bool import boolean
|
||||||
from ansible.module_utils.six import string_types, iteritems
|
|
||||||
from ansible.module_utils._text import to_text, to_bytes, to_native
|
|
||||||
from ansible.plugins.action import ActionBase
|
from ansible.plugins.action import ActionBase
|
||||||
|
|
||||||
|
try:
|
||||||
|
from ansible.template import trust_as_template
|
||||||
|
except ImportError:
|
||||||
|
trust_as_template = None
|
||||||
|
|
||||||
|
|
||||||
|
def _from_yaml_to_definition(buffer):
|
||||||
|
try:
|
||||||
|
import yaml
|
||||||
|
except ImportError:
|
||||||
|
raise AnsibleError("Failed to import the required Python library (PyYAML).")
|
||||||
|
return list(yaml.safe_load_all(buffer))
|
||||||
|
|
||||||
|
|
||||||
|
ENV_KUBECONFIG_PATH_SEPARATOR = ";" if platform.system() == "Windows" else ":"
|
||||||
|
|
||||||
|
|
||||||
class ActionModule(ActionBase):
|
class ActionModule(ActionBase):
|
||||||
|
|
||||||
TRANSFERS_FILES = True
|
TRANSFERS_FILES = True
|
||||||
DEFAULT_NEWLINE_SEQUENCE = "\n"
|
DEFAULT_NEWLINE_SEQUENCE = "\n"
|
||||||
|
|
||||||
def _ensure_invocation(self, result):
|
def _ensure_invocation(self, result):
|
||||||
# NOTE: adding invocation arguments here needs to be kept in sync with
|
# NOTE: adding invocation arguments here needs to be kept in sync with
|
||||||
# any no_log specified in the argument_spec in the module.
|
# any no_log specified in the argument_spec in the module.
|
||||||
if 'invocation' not in result:
|
if "invocation" not in result:
|
||||||
if self._play_context.no_log:
|
if self._play_context.no_log:
|
||||||
result['invocation'] = "CENSORED: no_log is set"
|
result["invocation"] = "CENSORED: no_log is set"
|
||||||
else:
|
else:
|
||||||
result['invocation'] = self._task.args.copy()
|
result["invocation"] = self._task.args.copy()
|
||||||
result['invocation']['module_args'] = self._task.args.copy()
|
result["invocation"]["module_args"] = self._task.args.copy()
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def get_template_data(self, template_path):
|
def get_template_data(self, template_path):
|
||||||
try:
|
try:
|
||||||
source = self._find_needle('templates', template_path)
|
source = self._find_needle("templates", template_path)
|
||||||
except AnsibleError as e:
|
except AnsibleError as e:
|
||||||
raise AnsibleActionFail(to_text(e))
|
raise AnsibleActionFail(to_text(e))
|
||||||
|
|
||||||
@@ -47,15 +68,19 @@ class ActionModule(ActionBase):
|
|||||||
try:
|
try:
|
||||||
tmp_source = self._loader.get_real_file(source)
|
tmp_source = self._loader.get_real_file(source)
|
||||||
except AnsibleFileNotFound as e:
|
except AnsibleFileNotFound as e:
|
||||||
raise AnsibleActionFail("could not find template=%s, %s" % (source, to_text(e)))
|
raise AnsibleActionFail(
|
||||||
b_tmp_source = to_bytes(tmp_source, errors='surrogate_or_strict')
|
"could not find template=%s, %s" % (source, to_text(e))
|
||||||
|
)
|
||||||
|
b_tmp_source = to_bytes(tmp_source, errors="surrogate_or_strict")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(b_tmp_source, 'rb') as f:
|
with open(b_tmp_source, "rb") as f:
|
||||||
try:
|
try:
|
||||||
template_data = to_text(f.read(), errors='surrogate_or_strict')
|
template_data = to_text(f.read(), errors="surrogate_or_strict")
|
||||||
except UnicodeError:
|
except UnicodeError:
|
||||||
raise AnsibleActionFail("Template source files must be utf-8 encoded")
|
raise AnsibleActionFail(
|
||||||
|
"Template source files must be utf-8 encoded"
|
||||||
|
)
|
||||||
yield template_data
|
yield template_data
|
||||||
except AnsibleAction:
|
except AnsibleAction:
|
||||||
raise
|
raise
|
||||||
@@ -72,72 +97,115 @@ class ActionModule(ActionBase):
|
|||||||
"block_start_string": None,
|
"block_start_string": None,
|
||||||
"block_end_string": None,
|
"block_end_string": None,
|
||||||
"trim_blocks": True,
|
"trim_blocks": True,
|
||||||
"lstrip_blocks": False
|
"lstrip_blocks": False,
|
||||||
}
|
}
|
||||||
if isinstance(template, string_types):
|
if isinstance(template, str):
|
||||||
# treat this as raw_params
|
# treat this as raw_params
|
||||||
template_param['path'] = template
|
template_param["path"] = template
|
||||||
elif isinstance(template, dict):
|
elif isinstance(template, dict):
|
||||||
template_args = template
|
template_args = template
|
||||||
template_path = template_args.get('path', None)
|
template_path = template_args.get("path", None)
|
||||||
if not template_path:
|
if not template_path:
|
||||||
raise AnsibleActionFail("Please specify path for template.")
|
raise AnsibleActionFail("Please specify path for template.")
|
||||||
template_param['path'] = template_path
|
template_param["path"] = template_path
|
||||||
|
|
||||||
# Options type validation strings
|
# Options type validation strings
|
||||||
for s_type in ('newline_sequence', 'variable_start_string', 'variable_end_string', 'block_start_string',
|
for s_type in (
|
||||||
'block_end_string'):
|
"newline_sequence",
|
||||||
|
"variable_start_string",
|
||||||
|
"variable_end_string",
|
||||||
|
"block_start_string",
|
||||||
|
"block_end_string",
|
||||||
|
):
|
||||||
if s_type in template_args:
|
if s_type in template_args:
|
||||||
value = ensure_type(template_args[s_type], 'string')
|
value = ensure_type(template_args[s_type], "string")
|
||||||
if value is not None and not isinstance(value, string_types):
|
if value is not None and not isinstance(value, str):
|
||||||
raise AnsibleActionFail("%s is expected to be a string, but got %s instead" % (s_type, type(value)))
|
raise AnsibleActionFail(
|
||||||
|
"%s is expected to be a string, but got %s instead"
|
||||||
|
% (s_type, type(value))
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
template_param.update({
|
template_param.update(
|
||||||
"trim_blocks": boolean(template_args.get('trim_blocks', True), strict=False),
|
{
|
||||||
"lstrip_blocks": boolean(template_args.get('lstrip_blocks', False), strict=False)
|
"trim_blocks": boolean(
|
||||||
})
|
template_args.get("trim_blocks", True), strict=False
|
||||||
|
),
|
||||||
|
"lstrip_blocks": boolean(
|
||||||
|
template_args.get("lstrip_blocks", False), strict=False
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
except TypeError as e:
|
except TypeError as e:
|
||||||
raise AnsibleActionFail(to_native(e))
|
raise AnsibleActionFail(to_native(e))
|
||||||
|
|
||||||
template_param.update({
|
template_param.update(
|
||||||
"newline_sequence": template_args.get('newline_sequence', self.DEFAULT_NEWLINE_SEQUENCE),
|
{
|
||||||
"variable_start_string": template_args.get('variable_start_string', None),
|
"newline_sequence": template_args.get(
|
||||||
"variable_end_string": template_args.get('variable_end_string', None),
|
"newline_sequence", self.DEFAULT_NEWLINE_SEQUENCE
|
||||||
"block_start_string": template_args.get('block_start_string', None),
|
),
|
||||||
"block_end_string": template_args.get('block_end_string', None)
|
"variable_start_string": template_args.get(
|
||||||
})
|
"variable_start_string", None
|
||||||
|
),
|
||||||
|
"variable_end_string": template_args.get(
|
||||||
|
"variable_end_string", None
|
||||||
|
),
|
||||||
|
"block_start_string": template_args.get("block_start_string", None),
|
||||||
|
"block_end_string": template_args.get("block_end_string", None),
|
||||||
|
}
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
raise AnsibleActionFail("Error while reading template file - "
|
raise AnsibleActionFail(
|
||||||
"a string or dict for template expected, but got %s instead" % type(template))
|
"Error while reading template file - "
|
||||||
|
"a string or dict for template expected, but got %s instead"
|
||||||
|
% type(template)
|
||||||
|
)
|
||||||
return template_param
|
return template_param
|
||||||
|
|
||||||
def import_jinja2_lstrip(self, templates):
|
def import_jinja2_lstrip(self, templates):
|
||||||
# Option `lstrip_blocks' was added in Jinja2 version 2.7.
|
# Option `lstrip_blocks' was added in Jinja2 version 2.7.
|
||||||
if any([tmp['lstrip_blocks'] for tmp in templates]):
|
if any(tmp["lstrip_blocks"] for tmp in templates):
|
||||||
try:
|
try:
|
||||||
import jinja2.defaults
|
import jinja2.defaults
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise AnsibleError('Unable to import Jinja2 defaults for determining Jinja2 features.')
|
raise AnsibleError(
|
||||||
|
"Unable to import Jinja2 defaults for determining Jinja2 features."
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
jinja2.defaults.LSTRIP_BLOCKS
|
jinja2.defaults.LSTRIP_BLOCKS
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise AnsibleError("Option `lstrip_blocks' is only available in Jinja2 versions >=2.7")
|
raise AnsibleError(
|
||||||
|
"Option `lstrip_blocks' is only available in Jinja2 versions >=2.7"
|
||||||
|
)
|
||||||
|
|
||||||
def load_template(self, template, new_module_args, task_vars):
|
def load_template(self, template, new_module_args, task_vars):
|
||||||
# template is only supported by k8s module.
|
# template is only supported by k8s module.
|
||||||
if self._task.action not in ('k8s', 'kubernetes.core.k8s', 'community.okd.k8s'):
|
if self._task.action not in (
|
||||||
raise AnsibleActionFail("'template' is only supported parameter for 'k8s' module.")
|
"k8s",
|
||||||
|
"kubernetes.core.k8s",
|
||||||
|
"community.okd.k8s",
|
||||||
|
"redhat.openshift.k8s",
|
||||||
|
"community.kubernetes.k8s",
|
||||||
|
"openshift_adm_groups_sync",
|
||||||
|
"community.okd.openshift_adm_groups_sync",
|
||||||
|
"redhat.openshift.openshift_adm_groups_sync",
|
||||||
|
):
|
||||||
|
raise AnsibleActionFail(
|
||||||
|
"'template' is only a supported parameter for the 'k8s' module."
|
||||||
|
)
|
||||||
|
|
||||||
template_params = []
|
template_params = []
|
||||||
if isinstance(template, string_types) or isinstance(template, dict):
|
if isinstance(template, str) or isinstance(template, dict):
|
||||||
template_params.append(self.get_template_args(template))
|
template_params.append(self.get_template_args(template))
|
||||||
elif isinstance(template, list):
|
elif isinstance(template, list):
|
||||||
for element in template:
|
for element in template:
|
||||||
template_params.append(self.get_template_args(element))
|
template_params.append(self.get_template_args(element))
|
||||||
else:
|
else:
|
||||||
raise AnsibleActionFail("Error while reading template file - "
|
raise AnsibleActionFail(
|
||||||
"a string or dict for template expected, but got %s instead" % type(template))
|
"Error while reading template file - "
|
||||||
|
"a string or dict for template expected, but got %s instead"
|
||||||
|
% type(template)
|
||||||
|
)
|
||||||
|
|
||||||
self.import_jinja2_lstrip(template_params)
|
self.import_jinja2_lstrip(template_params)
|
||||||
|
|
||||||
@@ -148,39 +216,117 @@ class ActionModule(ActionBase):
|
|||||||
old_vars = self._templar.available_variables
|
old_vars = self._templar.available_variables
|
||||||
|
|
||||||
default_environment = {}
|
default_environment = {}
|
||||||
for key in ("newline_sequence", "variable_start_string", "variable_end_string",
|
if trust_as_template is None:
|
||||||
"block_start_string", "block_end_string", "trim_blocks", "lstrip_blocks"):
|
for key in (
|
||||||
if hasattr(self._templar.environment, key):
|
"newline_sequence",
|
||||||
default_environment[key] = getattr(self._templar.environment, key)
|
"variable_start_string",
|
||||||
|
"variable_end_string",
|
||||||
|
"block_start_string",
|
||||||
|
"block_end_string",
|
||||||
|
"trim_blocks",
|
||||||
|
"lstrip_blocks",
|
||||||
|
):
|
||||||
|
if hasattr(self._templar.environment, key):
|
||||||
|
default_environment[key] = getattr(self._templar.environment, key)
|
||||||
for template_item in template_params:
|
for template_item in template_params:
|
||||||
# We need to convert unescaped sequences to proper escaped sequences for Jinja2
|
# We need to convert unescaped sequences to proper escaped sequences for Jinja2
|
||||||
newline_sequence = template_item['newline_sequence']
|
newline_sequence = template_item["newline_sequence"]
|
||||||
if newline_sequence in wrong_sequences:
|
if newline_sequence in wrong_sequences:
|
||||||
template_item['newline_sequence'] = allowed_sequences[wrong_sequences.index(newline_sequence)]
|
template_item["newline_sequence"] = allowed_sequences[
|
||||||
|
wrong_sequences.index(newline_sequence)
|
||||||
|
]
|
||||||
elif newline_sequence not in allowed_sequences:
|
elif newline_sequence not in allowed_sequences:
|
||||||
raise AnsibleActionFail("newline_sequence needs to be one of: \n, \r or \r\n")
|
raise AnsibleActionFail(
|
||||||
|
"newline_sequence needs to be one of: \n, \r or \r\n"
|
||||||
|
)
|
||||||
|
|
||||||
# template the source data locally & get ready to transfer
|
# template the source data locally & get ready to transfer
|
||||||
with self.get_template_data(template_item['path']) as template_data:
|
with self.get_template_data(template_item["path"]) as template_data:
|
||||||
# add ansible 'template' vars
|
# add ansible 'template' vars
|
||||||
temp_vars = copy.deepcopy(task_vars)
|
temp_vars = copy.deepcopy(task_vars)
|
||||||
for key, value in iteritems(template_item):
|
overrides = {}
|
||||||
|
for key, value in template_item.items():
|
||||||
if hasattr(self._templar.environment, key):
|
if hasattr(self._templar.environment, key):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
setattr(self._templar.environment, key, value)
|
overrides[key] = value
|
||||||
else:
|
if trust_as_template is None:
|
||||||
setattr(self._templar.environment, key, default_environment.get(key))
|
setattr(self._templar.environment, key, value)
|
||||||
|
elif trust_as_template is None:
|
||||||
|
setattr(
|
||||||
|
self._templar.environment,
|
||||||
|
key,
|
||||||
|
default_environment.get(key),
|
||||||
|
)
|
||||||
self._templar.available_variables = temp_vars
|
self._templar.available_variables = temp_vars
|
||||||
result = self._templar.do_template(template_data, preserve_trailing_newlines=True, escape_backslashes=False)
|
if trust_as_template:
|
||||||
result_template.append(result)
|
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))
|
||||||
self._templar.available_variables = old_vars
|
self._templar.available_variables = old_vars
|
||||||
resource_definition = self._task.args.get('definition', None)
|
resource_definition = self._task.args.get("definition", None)
|
||||||
if not resource_definition:
|
if not resource_definition:
|
||||||
new_module_args.pop('template')
|
new_module_args.pop("template")
|
||||||
new_module_args['definition'] = result_template
|
new_module_args["definition"] = result_template
|
||||||
|
|
||||||
|
def get_file_realpath(self, local_path):
|
||||||
|
# local_path is only supported by k8s_cp module.
|
||||||
|
if self._task.action not in (
|
||||||
|
"k8s_cp",
|
||||||
|
"kubernetes.core.k8s_cp",
|
||||||
|
"community.kubernetes.k8s_cp",
|
||||||
|
):
|
||||||
|
raise AnsibleActionFail(
|
||||||
|
"'local_path' is only supported parameter for 'k8s_cp' module."
|
||||||
|
)
|
||||||
|
|
||||||
|
if os.path.exists(local_path):
|
||||||
|
return local_path
|
||||||
|
|
||||||
|
try:
|
||||||
|
# find in expected paths
|
||||||
|
return self._find_needle("files", local_path)
|
||||||
|
except AnsibleError:
|
||||||
|
raise AnsibleActionFail(
|
||||||
|
"%s does not exist in local filesystem" % local_path
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_kubeconfig(self, kubeconfig, remote_transport, new_module_args):
|
||||||
|
if isinstance(kubeconfig, str):
|
||||||
|
# find the kubeconfig in the expected search path
|
||||||
|
if not remote_transport:
|
||||||
|
# kubeconfig is local
|
||||||
|
# find in expected paths
|
||||||
|
configs = []
|
||||||
|
for config in kubeconfig.split(ENV_KUBECONFIG_PATH_SEPARATOR):
|
||||||
|
config = self._find_needle("files", config)
|
||||||
|
|
||||||
|
# decrypt kubeconfig found
|
||||||
|
configs.append(self._loader.get_real_file(config, decrypt=True))
|
||||||
|
new_module_args["kubeconfig"] = ENV_KUBECONFIG_PATH_SEPARATOR.join(
|
||||||
|
configs
|
||||||
|
)
|
||||||
|
|
||||||
|
elif isinstance(kubeconfig, dict):
|
||||||
|
new_module_args["kubeconfig"] = kubeconfig
|
||||||
|
else:
|
||||||
|
raise AnsibleActionFail(
|
||||||
|
"Error while reading kubeconfig parameter - "
|
||||||
|
"a string or dict expected, but got %s instead" % type(kubeconfig)
|
||||||
|
)
|
||||||
|
|
||||||
def run(self, tmp=None, task_vars=None):
|
def run(self, tmp=None, task_vars=None):
|
||||||
''' handler for k8s options '''
|
"""handler for k8s options"""
|
||||||
if task_vars is None:
|
if task_vars is None:
|
||||||
task_vars = dict()
|
task_vars = dict()
|
||||||
|
|
||||||
@@ -191,55 +337,61 @@ class ActionModule(ActionBase):
|
|||||||
# look for kubeconfig and src
|
# look for kubeconfig and src
|
||||||
# 'local' => look files on Ansible Controller
|
# 'local' => look files on Ansible Controller
|
||||||
# Transport other than 'local' => look files on remote node
|
# Transport other than 'local' => look files on remote node
|
||||||
remote_transport = self._connection.transport != 'local'
|
remote_transport = self._connection.transport != "local"
|
||||||
|
|
||||||
new_module_args = copy.deepcopy(self._task.args)
|
new_module_args = copy.deepcopy(self._task.args)
|
||||||
|
|
||||||
kubeconfig = self._task.args.get('kubeconfig', None)
|
kubeconfig = self._task.args.get("kubeconfig", None)
|
||||||
# find the kubeconfig in the expected search path
|
if kubeconfig:
|
||||||
if kubeconfig and not remote_transport:
|
|
||||||
# kubeconfig is local
|
|
||||||
try:
|
try:
|
||||||
# find in expected paths
|
self.get_kubeconfig(kubeconfig, remote_transport, new_module_args)
|
||||||
kubeconfig = self._find_needle('files', kubeconfig)
|
|
||||||
except AnsibleError as e:
|
except AnsibleError as e:
|
||||||
result['failed'] = True
|
result["failed"] = True
|
||||||
result['msg'] = to_text(e)
|
result["msg"] = to_text(e)
|
||||||
result['exception'] = traceback.format_exc()
|
result["exception"] = traceback.format_exc()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
# decrypt kubeconfig found
|
|
||||||
actual_file = self._loader.get_real_file(kubeconfig, decrypt=True)
|
|
||||||
new_module_args['kubeconfig'] = actual_file
|
|
||||||
|
|
||||||
# find the file in the expected search path
|
# find the file in the expected search path
|
||||||
src = self._task.args.get('src', None)
|
src = self._task.args.get("src", None)
|
||||||
|
|
||||||
if src:
|
if src and not src.startswith(("http://", "https://", "ftp://")):
|
||||||
if remote_transport:
|
if remote_transport:
|
||||||
# src is on remote node
|
# src is on remote node
|
||||||
result.update(self._execute_module(module_name=self._task.action, task_vars=task_vars))
|
result.update(
|
||||||
|
self._execute_module(
|
||||||
|
module_name=self._task.action, task_vars=task_vars
|
||||||
|
)
|
||||||
|
)
|
||||||
return self._ensure_invocation(result)
|
return self._ensure_invocation(result)
|
||||||
|
|
||||||
# src is local
|
# src is local
|
||||||
try:
|
try:
|
||||||
# find in expected paths
|
# find in expected paths
|
||||||
src = self._find_needle('files', src)
|
src = self._find_needle("files", src)
|
||||||
except AnsibleError as e:
|
except AnsibleError as e:
|
||||||
result['failed'] = True
|
result["failed"] = True
|
||||||
result['msg'] = to_text(e)
|
result["msg"] = to_text(e)
|
||||||
result['exception'] = traceback.format_exc()
|
result["exception"] = traceback.format_exc()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
if src:
|
if src:
|
||||||
new_module_args['src'] = src
|
new_module_args["src"] = src
|
||||||
|
|
||||||
template = self._task.args.get('template', None)
|
template = self._task.args.get("template", None)
|
||||||
if template:
|
if template:
|
||||||
self.load_template(template, new_module_args, task_vars)
|
self.load_template(template, new_module_args, task_vars)
|
||||||
|
|
||||||
|
local_path = self._task.args.get("local_path")
|
||||||
|
state = self._task.args.get("state", None)
|
||||||
|
if local_path and state == "to_pod" and not remote_transport:
|
||||||
|
new_module_args["local_path"] = self.get_file_realpath(local_path)
|
||||||
|
|
||||||
# Execute the k8s_* module.
|
# Execute the k8s_* module.
|
||||||
module_return = self._execute_module(module_name=self._task.action, module_args=new_module_args, task_vars=task_vars)
|
module_return = self._execute_module(
|
||||||
|
module_name=self._task.action,
|
||||||
|
module_args=new_module_args,
|
||||||
|
task_vars=task_vars,
|
||||||
|
)
|
||||||
|
|
||||||
# Delete tmp path
|
# Delete tmp path
|
||||||
self._remove_tmp_path(self._connection._shell.tmpdir)
|
self._remove_tmp_path(self._connection._shell.tmpdir)
|
||||||
|
|||||||
1
plugins/action/k8s_json_patch.py
Symbolic link
1
plugins/action/k8s_json_patch.py
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
k8s_info.py
|
||||||
@@ -17,14 +17,15 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
DOCUMENTATION = r"""
|
DOCUMENTATION = r"""
|
||||||
author:
|
author:
|
||||||
- xuxinkun
|
- xuxinkun (@xuxinkun)
|
||||||
|
|
||||||
connection: kubectl
|
name: kubectl
|
||||||
|
|
||||||
short_description: Execute tasks in pods running on Kubernetes.
|
short_description: Execute tasks in pods running on Kubernetes.
|
||||||
|
|
||||||
@@ -71,9 +72,19 @@ DOCUMENTATION = r"""
|
|||||||
- name: ansible_kubectl_extra_args
|
- name: ansible_kubectl_extra_args
|
||||||
env:
|
env:
|
||||||
- name: K8S_AUTH_EXTRA_ARGS
|
- name: K8S_AUTH_EXTRA_ARGS
|
||||||
|
kubectl_local_env_vars:
|
||||||
|
description:
|
||||||
|
- Local enviromantal variable to be passed locally to the kubectl command line.
|
||||||
|
- Please be aware that this passes information directly on the command line and it could expose sensitive data.
|
||||||
|
default: {}
|
||||||
|
type: dict
|
||||||
|
version_added: 3.1.0
|
||||||
|
vars:
|
||||||
|
- name: ansible_kubectl_local_env_vars
|
||||||
kubectl_kubeconfig:
|
kubectl_kubeconfig:
|
||||||
description:
|
description:
|
||||||
- Path to a kubectl config file. Defaults to I(~/.kube/config)
|
- Path to a kubectl config file. Defaults to I(~/.kube/config)
|
||||||
|
- The configuration can be provided as dictionary. Added in version 2.4.0.
|
||||||
default: ''
|
default: ''
|
||||||
vars:
|
vars:
|
||||||
- name: ansible_kubectl_kubeconfig
|
- name: ansible_kubectl_kubeconfig
|
||||||
@@ -170,41 +181,118 @@ DOCUMENTATION = r"""
|
|||||||
aliases: [ kubectl_verify_ssl ]
|
aliases: [ kubectl_verify_ssl ]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import distutils.spawn
|
EXAMPLES = r"""
|
||||||
|
|
||||||
|
- name: Run a command in a pod using local kubectl with kubeconfig file ~/.kube/config
|
||||||
|
hosts: localhost
|
||||||
|
gather_facts: no
|
||||||
|
vars:
|
||||||
|
ansible_connection: kubernetes.core.kubectl
|
||||||
|
ansible_kubectl_namespace: my-namespace
|
||||||
|
ansible_kubectl_pod: my-pod
|
||||||
|
ansible_kubectl_container: my-container
|
||||||
|
tasks:
|
||||||
|
# be aware that the command is executed as the user that started the container
|
||||||
|
# and requires python to be installed in the image
|
||||||
|
- name: Run a command in a pod
|
||||||
|
ansible.builtin.command: echo "Hello, World!"
|
||||||
|
|
||||||
|
- name: Run a command in a pod using local kubectl with inventory variables
|
||||||
|
# Example inventory:
|
||||||
|
# k8s:
|
||||||
|
# hosts:
|
||||||
|
# foo.example.com:
|
||||||
|
# ansible_connection: kubernetes.core.kubectl
|
||||||
|
# ansible_kubectl_kubeconfig: /root/.kube/foo.example.com.config
|
||||||
|
# ansible_kubectl_pod: my-foo-pod
|
||||||
|
# ansible_kubectl_container: my-foo-container
|
||||||
|
# ansible_kubectl_namespace: my-foo-namespace
|
||||||
|
# bar.example.com:
|
||||||
|
# ansible_connection: kubernetes.core.kubectl
|
||||||
|
# ansible_kubectl_kubeconfig: /root/.kube/bar.example.com.config
|
||||||
|
# ansible_kubectl_pod: my-bar-pod
|
||||||
|
# ansible_kubectl_container: my-bar-container
|
||||||
|
# ansible_kubectl_namespace: my-bar-namespace
|
||||||
|
hosts: k8s
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
# be aware that the command is executed as the user that started the container
|
||||||
|
# and requires python to be installed in the image
|
||||||
|
- name: Run a command in a pod
|
||||||
|
ansible.builtin.command: echo "Hello, World!"
|
||||||
|
|
||||||
|
- name: Run a command in a pod using dynamic inventory
|
||||||
|
hosts: localhost
|
||||||
|
gather_facts: no
|
||||||
|
vars:
|
||||||
|
kubeconfig: /root/.kube/config
|
||||||
|
namespace: my-namespace
|
||||||
|
my_app: my-app
|
||||||
|
tasks:
|
||||||
|
- name: Get My App pod info based on label
|
||||||
|
kubernetes.core.k8s_info:
|
||||||
|
kubeconfig: "{{ kubeconfig }}"
|
||||||
|
namespace: "{{ namespace }}"
|
||||||
|
kind: Pod
|
||||||
|
label_selectors: app.kubernetes.io/name = "{{ my_app }}"
|
||||||
|
register: my_app_pod
|
||||||
|
|
||||||
|
- name: Get My App pod name
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
my_app_pod_name: "{{ my_app_pod.resources[0].metadata.name }}"
|
||||||
|
|
||||||
|
- name: Add My App pod to inventory
|
||||||
|
ansible.builtin.add_host:
|
||||||
|
name: "{{ my_app_pod_name }}"
|
||||||
|
ansible_connection: kubernetes.core.kubectl
|
||||||
|
ansible_kubectl_kubeconfig: "{{ kubeconfig }}"
|
||||||
|
ansible_kubectl_pod: "{{ my_app_pod_name }}"
|
||||||
|
ansible_kubectl_namespace: "{{ namespace }}"
|
||||||
|
|
||||||
|
- name: Run a command in My App pod
|
||||||
|
# be aware that the command is executed as the user that started the container
|
||||||
|
# and requires python to be installed in the image
|
||||||
|
ansible.builtin.command: echo "Hello, World!"
|
||||||
|
delegate_to: "{{ my_app_pod_name }}"
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import tempfile
|
||||||
|
|
||||||
from ansible.parsing.yaml.loader import AnsibleLoader
|
|
||||||
from ansible.errors import AnsibleError, AnsibleFileNotFound
|
from ansible.errors import AnsibleError, AnsibleFileNotFound
|
||||||
from ansible.module_utils.six.moves import shlex_quote
|
|
||||||
from ansible.module_utils._text import to_bytes
|
from ansible.module_utils._text import to_bytes
|
||||||
from ansible.plugins.connection import ConnectionBase, BUFSIZE
|
from ansible.module_utils.six.moves import shlex_quote
|
||||||
|
from ansible.parsing.yaml.loader import AnsibleLoader
|
||||||
|
from ansible.plugins.connection import BUFSIZE, ConnectionBase
|
||||||
from ansible.utils.display import Display
|
from ansible.utils.display import Display
|
||||||
|
|
||||||
display = Display()
|
display = Display()
|
||||||
|
|
||||||
|
|
||||||
CONNECTION_TRANSPORT = 'kubectl'
|
CONNECTION_TRANSPORT = "kubectl"
|
||||||
|
|
||||||
CONNECTION_OPTIONS = {
|
CONNECTION_OPTIONS = {
|
||||||
'kubectl_container': '-c',
|
"kubectl_container": "-c",
|
||||||
'kubectl_namespace': '-n',
|
"kubectl_namespace": "-n",
|
||||||
'kubectl_kubeconfig': '--kubeconfig',
|
"kubectl_kubeconfig": "--kubeconfig",
|
||||||
'kubectl_context': '--context',
|
"kubectl_context": "--context",
|
||||||
'kubectl_host': '--server',
|
"kubectl_host": "--server",
|
||||||
'kubectl_username': '--username',
|
"kubectl_username": "--username",
|
||||||
'kubectl_password': '--password',
|
"kubectl_password": "--password",
|
||||||
'client_cert': '--client-certificate',
|
"client_cert": "--client-certificate",
|
||||||
'client_key': '--client-key',
|
"client_key": "--client-key",
|
||||||
'ca_cert': '--certificate-authority',
|
"ca_cert": "--certificate-authority",
|
||||||
'validate_certs': '--insecure-skip-tls-verify',
|
"validate_certs": "--insecure-skip-tls-verify",
|
||||||
'kubectl_token': '--token'
|
"kubectl_token": "--token",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Connection(ConnectionBase):
|
class Connection(ConnectionBase):
|
||||||
''' Local kubectl based connections '''
|
"""Local kubectl based connections"""
|
||||||
|
|
||||||
transport = CONNECTION_TRANSPORT
|
transport = CONNECTION_TRANSPORT
|
||||||
connection_options = CONNECTION_OPTIONS
|
connection_options = CONNECTION_OPTIONS
|
||||||
@@ -217,153 +305,246 @@ class Connection(ConnectionBase):
|
|||||||
|
|
||||||
# Note: kubectl runs commands as the user that started the container.
|
# Note: kubectl runs commands as the user that started the container.
|
||||||
# It is impossible to set the remote user for a kubectl connection.
|
# It is impossible to set the remote user for a kubectl connection.
|
||||||
cmd_arg = '{0}_command'.format(self.transport)
|
cmd_arg = "{0}_command".format(self.transport)
|
||||||
if cmd_arg in kwargs:
|
self.transport_cmd = kwargs.get(cmd_arg, shutil.which(self.transport))
|
||||||
self.transport_cmd = kwargs[cmd_arg]
|
if not self.transport_cmd:
|
||||||
else:
|
raise AnsibleError("{0} command not found in PATH".format(self.transport))
|
||||||
self.transport_cmd = distutils.spawn.find_executable(self.transport)
|
self._file_to_delete = None
|
||||||
if not self.transport_cmd:
|
|
||||||
raise AnsibleError("{0} command not found in PATH".format(self.transport))
|
def delete_temporary_file(self):
|
||||||
|
if self._file_to_delete is not None:
|
||||||
|
os.remove(self._file_to_delete)
|
||||||
|
self._file_to_delete = None
|
||||||
|
|
||||||
def _build_exec_cmd(self, cmd):
|
def _build_exec_cmd(self, cmd):
|
||||||
""" Build the local kubectl exec command to run cmd on remote_host
|
"""Build the local kubectl exec command to run cmd on remote_host"""
|
||||||
"""
|
|
||||||
local_cmd = [self.transport_cmd]
|
local_cmd = [self.transport_cmd]
|
||||||
censored_local_cmd = [self.transport_cmd]
|
censored_local_cmd = [self.transport_cmd]
|
||||||
|
|
||||||
# Build command options based on doc string
|
# Build command options based on doc string
|
||||||
doc_yaml = AnsibleLoader(self.documentation).get_single_data()
|
doc_yaml = AnsibleLoader(self.documentation).get_single_data()
|
||||||
for key in doc_yaml.get('options'):
|
for key in doc_yaml.get("options"):
|
||||||
if key.endswith('verify_ssl') and self.get_option(key) != '':
|
if key.endswith("verify_ssl") and self.get_option(key) != "":
|
||||||
# Translate verify_ssl to skip_verify_ssl, and output as string
|
# Translate verify_ssl to skip_verify_ssl, and output as string
|
||||||
skip_verify_ssl = not self.get_option(key)
|
skip_verify_ssl = not self.get_option(key)
|
||||||
local_cmd.append(u'{0}={1}'.format(self.connection_options[key], str(skip_verify_ssl).lower()))
|
local_cmd.append(
|
||||||
censored_local_cmd.append(u'{0}={1}'.format(self.connection_options[key], str(skip_verify_ssl).lower()))
|
"{0}={1}".format(
|
||||||
elif not key.endswith('container') and self.get_option(key) and self.connection_options.get(key):
|
self.connection_options[key], str(skip_verify_ssl).lower()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
censored_local_cmd.append(
|
||||||
|
"{0}={1}".format(
|
||||||
|
self.connection_options[key], str(skip_verify_ssl).lower()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif key.endswith("kubeconfig") and self.get_option(key) != "":
|
||||||
|
kubeconfig_path = self.get_option(key)
|
||||||
|
if isinstance(kubeconfig_path, dict):
|
||||||
|
fd, tmpfile = tempfile.mkstemp()
|
||||||
|
with os.fdopen(fd, "w") as fp:
|
||||||
|
json.dump(kubeconfig_path, fp)
|
||||||
|
kubeconfig_path = tmpfile
|
||||||
|
self._file_to_delete = tmpfile
|
||||||
|
|
||||||
|
cmd_arg = self.connection_options[key]
|
||||||
|
local_cmd += [cmd_arg, kubeconfig_path]
|
||||||
|
censored_local_cmd += [cmd_arg, kubeconfig_path]
|
||||||
|
elif (
|
||||||
|
not key.endswith("container")
|
||||||
|
and self.get_option(key)
|
||||||
|
and self.connection_options.get(key)
|
||||||
|
):
|
||||||
cmd_arg = self.connection_options[key]
|
cmd_arg = self.connection_options[key]
|
||||||
local_cmd += [cmd_arg, self.get_option(key)]
|
local_cmd += [cmd_arg, self.get_option(key)]
|
||||||
# Redact password and token from console log
|
# Redact password and token from console log
|
||||||
if key.endswith(('_token', '_password')):
|
if key.endswith(("_token", "_password")):
|
||||||
censored_local_cmd += [cmd_arg, '********']
|
censored_local_cmd += [cmd_arg, "********"]
|
||||||
|
else:
|
||||||
|
censored_local_cmd += [cmd_arg, self.get_option(key)]
|
||||||
|
|
||||||
extra_args_name = u'{0}_extra_args'.format(self.transport)
|
extra_args_name = "{0}_extra_args".format(self.transport)
|
||||||
if self.get_option(extra_args_name):
|
if self.get_option(extra_args_name):
|
||||||
local_cmd += self.get_option(extra_args_name).split(' ')
|
local_cmd += self.get_option(extra_args_name).split(" ")
|
||||||
censored_local_cmd += self.get_option(extra_args_name).split(' ')
|
censored_local_cmd += self.get_option(extra_args_name).split(" ")
|
||||||
|
|
||||||
pod = self.get_option(u'{0}_pod'.format(self.transport))
|
pod = self.get_option("{0}_pod".format(self.transport))
|
||||||
if not pod:
|
if not pod:
|
||||||
pod = self._play_context.remote_addr
|
pod = self._play_context.remote_addr
|
||||||
# -i is needed to keep stdin open which allows pipelining to work
|
# -i is needed to keep stdin open which allows pipelining to work
|
||||||
local_cmd += ['exec', '-i', pod]
|
local_cmd += ["exec", "-i", pod]
|
||||||
censored_local_cmd += ['exec', '-i', pod]
|
censored_local_cmd += ["exec", "-i", pod]
|
||||||
|
|
||||||
# if the pod has more than one container, then container is required
|
# if the pod has more than one container, then container is required
|
||||||
container_arg_name = u'{0}_container'.format(self.transport)
|
container_arg_name = "{0}_container".format(self.transport)
|
||||||
if self.get_option(container_arg_name):
|
if self.get_option(container_arg_name):
|
||||||
local_cmd += ['-c', self.get_option(container_arg_name)]
|
local_cmd += ["-c", self.get_option(container_arg_name)]
|
||||||
censored_local_cmd += ['-c', self.get_option(container_arg_name)]
|
censored_local_cmd += ["-c", self.get_option(container_arg_name)]
|
||||||
|
|
||||||
local_cmd += ['--'] + cmd
|
local_cmd += ["--"] + cmd
|
||||||
censored_local_cmd += ['--'] + cmd
|
censored_local_cmd += ["--"] + cmd
|
||||||
|
|
||||||
return local_cmd, censored_local_cmd
|
return local_cmd, censored_local_cmd
|
||||||
|
|
||||||
|
def _local_env(self):
|
||||||
|
"""Return a dict of local environment variables to pass to the kubectl command"""
|
||||||
|
local_env = {}
|
||||||
|
local_local_env_vars_name = "{0}_local_env_vars".format(self.transport)
|
||||||
|
local_env_vars = self.get_option(local_local_env_vars_name)
|
||||||
|
if local_env_vars:
|
||||||
|
if isinstance(local_env_vars, dict):
|
||||||
|
local_env_vars = json.dumps(local_env_vars)
|
||||||
|
local_env = os.environ.copy()
|
||||||
|
local_env.update(json.loads(local_env_vars))
|
||||||
|
return local_env
|
||||||
|
return None
|
||||||
|
|
||||||
def _connect(self, port=None):
|
def _connect(self, port=None):
|
||||||
""" Connect to the container. Nothing to do """
|
"""Connect to the container. Nothing to do"""
|
||||||
super(Connection, self)._connect()
|
super(Connection, self)._connect()
|
||||||
if not self._connected:
|
if not self._connected:
|
||||||
display.vvv(u"ESTABLISH {0} CONNECTION".format(self.transport), host=self._play_context.remote_addr)
|
display.vvv(
|
||||||
|
"ESTABLISH {0} CONNECTION".format(self.transport),
|
||||||
|
host=self._play_context.remote_addr,
|
||||||
|
)
|
||||||
self._connected = True
|
self._connected = True
|
||||||
|
|
||||||
def exec_command(self, cmd, in_data=None, sudoable=False):
|
def exec_command(self, cmd, in_data=None, sudoable=False):
|
||||||
""" Run a command in the container """
|
"""Run a command in the container"""
|
||||||
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
|
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
|
||||||
|
|
||||||
local_cmd, censored_local_cmd = self._build_exec_cmd([self._play_context.executable, '-c', cmd])
|
local_cmd, censored_local_cmd = self._build_exec_cmd(
|
||||||
|
[self._play_context.executable, "-c", cmd]
|
||||||
|
)
|
||||||
|
|
||||||
display.vvv("EXEC %s" % (censored_local_cmd,), host=self._play_context.remote_addr)
|
display.vvv(
|
||||||
local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
|
"EXEC %s" % (censored_local_cmd,), host=self._play_context.remote_addr
|
||||||
p = subprocess.Popen(local_cmd, shell=False, stdin=subprocess.PIPE,
|
)
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
local_cmd = [to_bytes(i, errors="surrogate_or_strict") for i in local_cmd]
|
||||||
|
p = subprocess.Popen(
|
||||||
|
local_cmd,
|
||||||
|
shell=False,
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
env=self._local_env(),
|
||||||
|
)
|
||||||
|
|
||||||
stdout, stderr = p.communicate(in_data)
|
stdout, stderr = p.communicate(in_data)
|
||||||
|
self.delete_temporary_file()
|
||||||
return (p.returncode, stdout, stderr)
|
return (p.returncode, stdout, stderr)
|
||||||
|
|
||||||
def _prefix_login_path(self, remote_path):
|
def _prefix_login_path(self, remote_path):
|
||||||
''' Make sure that we put files into a standard path
|
"""Make sure that we put files into a standard path
|
||||||
|
|
||||||
If a path is relative, then we need to choose where to put it.
|
If a path is relative, then we need to choose where to put it.
|
||||||
ssh chooses $HOME but we aren't guaranteed that a home dir will
|
ssh chooses $HOME but we aren't guaranteed that a home dir will
|
||||||
exist in any given chroot. So for now we're choosing "/" instead.
|
exist in any given chroot. So for now we're choosing "/" instead.
|
||||||
This also happens to be the former default.
|
This also happens to be the former default.
|
||||||
|
|
||||||
Can revisit using $HOME instead if it's a problem
|
Can revisit using $HOME instead if it's a problem
|
||||||
'''
|
"""
|
||||||
if not remote_path.startswith(os.path.sep):
|
if not remote_path.startswith(os.path.sep):
|
||||||
remote_path = os.path.join(os.path.sep, remote_path)
|
remote_path = os.path.join(os.path.sep, remote_path)
|
||||||
return os.path.normpath(remote_path)
|
return os.path.normpath(remote_path)
|
||||||
|
|
||||||
def put_file(self, in_path, out_path):
|
def put_file(self, in_path, out_path):
|
||||||
""" Transfer a file from local to the container """
|
"""Transfer a file from local to the container"""
|
||||||
super(Connection, self).put_file(in_path, out_path)
|
super(Connection, self).put_file(in_path, out_path)
|
||||||
display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr)
|
display.vvv(
|
||||||
|
"PUT %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr
|
||||||
|
)
|
||||||
|
|
||||||
out_path = self._prefix_login_path(out_path)
|
out_path = self._prefix_login_path(out_path)
|
||||||
if not os.path.exists(to_bytes(in_path, errors='surrogate_or_strict')):
|
if not os.path.exists(to_bytes(in_path, errors="surrogate_or_strict")):
|
||||||
raise AnsibleFileNotFound(
|
raise AnsibleFileNotFound("file or module does not exist: %s" % in_path)
|
||||||
"file or module does not exist: %s" % in_path)
|
|
||||||
|
|
||||||
out_path = shlex_quote(out_path)
|
out_path = shlex_quote(out_path)
|
||||||
# kubectl doesn't have native support for copying files into
|
# kubectl doesn't have native support for copying files into
|
||||||
# running containers, so we use kubectl exec to implement this
|
# running containers, so we use kubectl exec to implement this
|
||||||
with open(to_bytes(in_path, errors='surrogate_or_strict'), 'rb') as in_file:
|
with open(to_bytes(in_path, errors="surrogate_or_strict"), "rb") as in_file:
|
||||||
if not os.fstat(in_file.fileno()).st_size:
|
if not os.fstat(in_file.fileno()).st_size:
|
||||||
count = ' count=0'
|
count = " count=0"
|
||||||
else:
|
else:
|
||||||
count = ''
|
count = ""
|
||||||
args, dummy = self._build_exec_cmd([self._play_context.executable, "-c", "dd of=%s bs=%s%s" % (out_path, BUFSIZE, count)])
|
args, dummy = self._build_exec_cmd(
|
||||||
args = [to_bytes(i, errors='surrogate_or_strict') for i in args]
|
[
|
||||||
|
self._play_context.executable,
|
||||||
|
"-c",
|
||||||
|
"dd of=%s bs=%s%s && sleep 0" % (out_path, BUFSIZE, count),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
args = [to_bytes(i, errors="surrogate_or_strict") for i in args]
|
||||||
try:
|
try:
|
||||||
p = subprocess.Popen(args, stdin=in_file,
|
p = subprocess.Popen(
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
args,
|
||||||
|
stdin=in_file,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
env=self._local_env(),
|
||||||
|
)
|
||||||
except OSError:
|
except OSError:
|
||||||
raise AnsibleError("kubectl connection requires dd command in the container to put files")
|
raise AnsibleError(
|
||||||
|
"kubectl connection requires dd command in the container to put files"
|
||||||
|
)
|
||||||
stdout, stderr = p.communicate()
|
stdout, stderr = p.communicate()
|
||||||
|
self.delete_temporary_file()
|
||||||
|
|
||||||
if p.returncode != 0:
|
if p.returncode != 0:
|
||||||
raise AnsibleError("failed to transfer file %s to %s:\n%s\n%s" % (in_path, out_path, stdout, stderr))
|
raise AnsibleError(
|
||||||
|
"failed to transfer file %s to %s:\n%s\n%s"
|
||||||
|
% (in_path, out_path, stdout, stderr)
|
||||||
|
)
|
||||||
|
|
||||||
def fetch_file(self, in_path, out_path):
|
def fetch_file(self, in_path, out_path):
|
||||||
""" Fetch a file from container to local. """
|
"""Fetch a file from container to local."""
|
||||||
super(Connection, self).fetch_file(in_path, out_path)
|
super(Connection, self).fetch_file(in_path, out_path)
|
||||||
display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr)
|
display.vvv(
|
||||||
|
"FETCH %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr
|
||||||
|
)
|
||||||
|
|
||||||
in_path = self._prefix_login_path(in_path)
|
in_path = self._prefix_login_path(in_path)
|
||||||
out_dir = os.path.dirname(out_path)
|
out_dir = os.path.dirname(out_path)
|
||||||
|
|
||||||
# kubectl doesn't have native support for fetching files from
|
# kubectl doesn't have native support for fetching files from
|
||||||
# running containers, so we use kubectl exec to implement this
|
# running containers, so we use kubectl exec to implement this
|
||||||
args, dummy = self._build_exec_cmd([self._play_context.executable, "-c", "dd if=%s bs=%s" % (in_path, BUFSIZE)])
|
args, dummy = self._build_exec_cmd(
|
||||||
args = [to_bytes(i, errors='surrogate_or_strict') for i in args]
|
[self._play_context.executable, "-c", "dd if=%s bs=%s" % (in_path, BUFSIZE)]
|
||||||
|
)
|
||||||
|
args = [to_bytes(i, errors="surrogate_or_strict") for i in args]
|
||||||
actual_out_path = os.path.join(out_dir, os.path.basename(in_path))
|
actual_out_path = os.path.join(out_dir, os.path.basename(in_path))
|
||||||
with open(to_bytes(actual_out_path, errors='surrogate_or_strict'), 'wb') as out_file:
|
with open(
|
||||||
|
to_bytes(actual_out_path, errors="surrogate_or_strict"), "wb"
|
||||||
|
) as out_file:
|
||||||
try:
|
try:
|
||||||
p = subprocess.Popen(args, stdin=subprocess.PIPE,
|
p = subprocess.Popen(
|
||||||
stdout=out_file, stderr=subprocess.PIPE)
|
args,
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
stdout=out_file,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
env=self._local_env(),
|
||||||
|
)
|
||||||
except OSError:
|
except OSError:
|
||||||
raise AnsibleError(
|
raise AnsibleError(
|
||||||
"{0} connection requires dd command in the container to fetch files".format(self.transport)
|
"{0} connection requires dd command in the container to fetch files".format(
|
||||||
|
self.transport
|
||||||
|
)
|
||||||
)
|
)
|
||||||
stdout, stderr = p.communicate()
|
stdout, stderr = p.communicate()
|
||||||
|
self.delete_temporary_file()
|
||||||
|
|
||||||
if p.returncode != 0:
|
if p.returncode != 0:
|
||||||
raise AnsibleError("failed to fetch file %s to %s:\n%s\n%s" % (in_path, out_path, stdout, stderr))
|
raise AnsibleError(
|
||||||
|
"failed to fetch file %s to %s:\n%s\n%s"
|
||||||
|
% (in_path, out_path, stdout, stderr)
|
||||||
|
)
|
||||||
|
|
||||||
if actual_out_path != out_path:
|
if actual_out_path != out_path:
|
||||||
os.rename(to_bytes(actual_out_path, errors='strict'), to_bytes(out_path, errors='strict'))
|
os.rename(
|
||||||
|
to_bytes(actual_out_path, errors="strict"),
|
||||||
|
to_bytes(out_path, errors="strict"),
|
||||||
|
)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
""" Terminate the connection. Nothing to do for kubectl"""
|
"""Terminate the connection. Nothing to do for kubectl"""
|
||||||
super(Connection, self).close()
|
super(Connection, self).close()
|
||||||
self._connected = False
|
self._connected = False
|
||||||
|
|||||||
@@ -6,13 +6,13 @@
|
|||||||
|
|
||||||
# Options for common Helm modules
|
# Options for common Helm modules
|
||||||
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
class ModuleDocFragment(object):
|
class ModuleDocFragment(object):
|
||||||
|
DOCUMENTATION = r"""
|
||||||
DOCUMENTATION = r'''
|
|
||||||
options:
|
options:
|
||||||
binary_path:
|
binary_path:
|
||||||
description:
|
description:
|
||||||
@@ -29,18 +29,19 @@ options:
|
|||||||
description:
|
description:
|
||||||
- Helm option to specify kubeconfig path to use.
|
- Helm option to specify kubeconfig path to use.
|
||||||
- If the value is not specified in the task, the value of environment variable C(K8S_AUTH_KUBECONFIG) will be used instead.
|
- If the value is not specified in the task, the value of environment variable C(K8S_AUTH_KUBECONFIG) will be used instead.
|
||||||
type: path
|
- The configuration can be provided as dictionary. Added in version 2.4.0.
|
||||||
|
type: raw
|
||||||
aliases: [ kubeconfig_path ]
|
aliases: [ kubeconfig_path ]
|
||||||
host:
|
host:
|
||||||
description:
|
description:
|
||||||
- Provide a URL for accessing the API. Can also be specified via C(K8S_AUTH_HOST) environment variable.
|
- Provide a URL for accessing the API. Can also be specified via C(K8S_AUTH_HOST) environment variable.
|
||||||
type: str
|
type: str
|
||||||
version_added: "1.2.0"
|
version_added: 1.2.0
|
||||||
api_key:
|
api_key:
|
||||||
description:
|
description:
|
||||||
- Token used to authenticate with the API. Can also be specified via C(K8S_AUTH_API_KEY) environment variable.
|
- Token used to authenticate with the API. Can also be specified via C(K8S_AUTH_API_KEY) environment variable.
|
||||||
type: str
|
type: str
|
||||||
version_added: "1.2.0"
|
version_added: 1.2.0
|
||||||
validate_certs:
|
validate_certs:
|
||||||
description:
|
description:
|
||||||
- Whether or not to verify the API server's SSL certificates. Can also be specified via C(K8S_AUTH_VERIFY_SSL)
|
- Whether or not to verify the API server's SSL certificates. Can also be specified via C(K8S_AUTH_VERIFY_SSL)
|
||||||
@@ -48,12 +49,12 @@ options:
|
|||||||
type: bool
|
type: bool
|
||||||
aliases: [ verify_ssl ]
|
aliases: [ verify_ssl ]
|
||||||
default: True
|
default: True
|
||||||
version_added: "1.2.0"
|
version_added: 1.2.0
|
||||||
ca_cert:
|
ca_cert:
|
||||||
description:
|
description:
|
||||||
- Path to a CA certificate used to authenticate with the API. The full certificate chain must be provided to
|
- Path to a CA certificate used to authenticate with the API. The full certificate chain must be provided to
|
||||||
avoid certificate validation errors. Can also be specified via C(K8S_AUTH_SSL_CA_CERT) environment variable.
|
avoid certificate validation errors. Can also be specified via C(K8S_AUTH_SSL_CA_CERT) environment variable.
|
||||||
type: path
|
type: path
|
||||||
aliases: [ ssl_ca_cert ]
|
aliases: [ ssl_ca_cert ]
|
||||||
version_added: "1.2.0"
|
version_added: 1.2.0
|
||||||
'''
|
"""
|
||||||
|
|||||||
@@ -5,13 +5,13 @@
|
|||||||
|
|
||||||
# Options for authenticating with the API.
|
# Options for authenticating with the API.
|
||||||
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
class ModuleDocFragment(object):
|
class ModuleDocFragment(object):
|
||||||
|
DOCUMENTATION = r"""
|
||||||
DOCUMENTATION = r'''
|
|
||||||
options:
|
options:
|
||||||
host:
|
host:
|
||||||
description:
|
description:
|
||||||
@@ -27,7 +27,9 @@ options:
|
|||||||
options are provided, the Kubernetes client will attempt to load the default
|
options are provided, the Kubernetes client will attempt to load the default
|
||||||
configuration file from I(~/.kube/config). Can also be specified via K8S_AUTH_KUBECONFIG environment
|
configuration file from I(~/.kube/config). Can also be specified via K8S_AUTH_KUBECONFIG environment
|
||||||
variable.
|
variable.
|
||||||
type: path
|
- Multiple Kubernetes config file can be provided using separator ';' for Windows platform or ':' for others platforms.
|
||||||
|
- The kubernetes configuration can be provided as dictionary. This feature requires a python kubernetes client version >= 17.17.0. Added in version 2.2.0.
|
||||||
|
type: raw
|
||||||
context:
|
context:
|
||||||
description:
|
description:
|
||||||
- The name of a context found in the config file. Can also be specified via K8S_AUTH_CONTEXT environment variable.
|
- The name of a context found in the config file. Can also be specified via K8S_AUTH_CONTEXT environment variable.
|
||||||
@@ -75,6 +77,14 @@ options:
|
|||||||
- The URL of an HTTP proxy to use for the connection. Can also be specified via K8S_AUTH_PROXY environment variable.
|
- The URL of an HTTP proxy to use for the connection. Can also be specified via K8S_AUTH_PROXY environment variable.
|
||||||
- Please note that this module does not pick up typical proxy settings from the environment (e.g. HTTP_PROXY).
|
- Please note that this module does not pick up typical proxy settings from the environment (e.g. HTTP_PROXY).
|
||||||
type: str
|
type: str
|
||||||
|
no_proxy:
|
||||||
|
description:
|
||||||
|
- The comma separated list of hosts/domains/IP/CIDR that shouldn't go through proxy. Can also be specified via K8S_AUTH_NO_PROXY environment variable.
|
||||||
|
- Please note that this module does not pick up typical proxy settings from the environment (e.g. NO_PROXY).
|
||||||
|
- This feature requires kubernetes>=19.15.0. When kubernetes library is less than 19.15.0, it fails even no_proxy set in correct.
|
||||||
|
- example value is "localhost,.local,.example.com,127.0.0.1,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
|
||||||
|
type: str
|
||||||
|
version_added: 2.3.0
|
||||||
proxy_headers:
|
proxy_headers:
|
||||||
description:
|
description:
|
||||||
- The Header used for the HTTP proxy.
|
- The Header used for the HTTP proxy.
|
||||||
@@ -109,8 +119,21 @@ options:
|
|||||||
- Please note that the current version of the k8s python client library does not support setting this flag to True yet.
|
- Please note that the current version of the k8s python client library does not support setting this flag to True yet.
|
||||||
- "The fix for this k8s python library is here: https://github.com/kubernetes-client/python-base/pull/169"
|
- "The fix for this k8s python library is here: https://github.com/kubernetes-client/python-base/pull/169"
|
||||||
type: bool
|
type: bool
|
||||||
|
impersonate_user:
|
||||||
|
description:
|
||||||
|
- Username to impersonate for the operation.
|
||||||
|
- Can also be specified via K8S_AUTH_IMPERSONATE_USER environment.
|
||||||
|
type: str
|
||||||
|
version_added: 2.3.0
|
||||||
|
impersonate_groups:
|
||||||
|
description:
|
||||||
|
- Group(s) to impersonate for the operation.
|
||||||
|
- "Can also be specified via K8S_AUTH_IMPERSONATE_GROUPS environment. Example: Group1,Group2"
|
||||||
|
type: list
|
||||||
|
elements: str
|
||||||
|
version_added: 2.3.0
|
||||||
notes:
|
notes:
|
||||||
- "To avoid SSL certificate validation errors when C(validate_certs) is I(True), the full
|
- "To avoid SSL certificate validation errors when C(validate_certs) is I(True), the full
|
||||||
certificate chain for the API server must be provided via C(ca_cert) or in the
|
certificate chain for the API server must be provided via C(ca_cert) or in the
|
||||||
kubeconfig file."
|
kubeconfig file."
|
||||||
'''
|
"""
|
||||||
|
|||||||
@@ -5,17 +5,17 @@
|
|||||||
|
|
||||||
# Options for specifying object wait
|
# Options for specifying object wait
|
||||||
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
class ModuleDocFragment(object):
|
class ModuleDocFragment(object):
|
||||||
|
DOCUMENTATION = r"""
|
||||||
DOCUMENTATION = r'''
|
|
||||||
options:
|
options:
|
||||||
delete_options:
|
delete_options:
|
||||||
type: dict
|
type: dict
|
||||||
version_added: '1.2.0'
|
version_added: 1.2.0
|
||||||
description:
|
description:
|
||||||
- Configure behavior when deleting an object.
|
- Configure behavior when deleting an object.
|
||||||
- Only used when I(state=absent).
|
- Only used when I(state=absent).
|
||||||
@@ -48,4 +48,4 @@ options:
|
|||||||
type: str
|
type: str
|
||||||
description:
|
description:
|
||||||
- Specify the UID of the target object.
|
- Specify the UID of the target object.
|
||||||
'''
|
"""
|
||||||
|
|||||||
@@ -5,13 +5,13 @@
|
|||||||
|
|
||||||
# Options for selecting or identifying a specific K8s object
|
# Options for selecting or identifying a specific K8s object
|
||||||
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
class ModuleDocFragment(object):
|
class ModuleDocFragment(object):
|
||||||
|
DOCUMENTATION = r"""
|
||||||
DOCUMENTATION = r'''
|
|
||||||
options:
|
options:
|
||||||
api_version:
|
api_version:
|
||||||
description:
|
description:
|
||||||
@@ -49,4 +49,4 @@ options:
|
|||||||
- If I(resource definition) is provided, the I(metadata.namespace) value from the I(resource_definition)
|
- If I(resource definition) is provided, the I(metadata.namespace) value from the I(resource_definition)
|
||||||
will override this option.
|
will override this option.
|
||||||
type: str
|
type: str
|
||||||
'''
|
"""
|
||||||
|
|||||||
@@ -5,13 +5,13 @@
|
|||||||
|
|
||||||
# Options for providing an object configuration
|
# Options for providing an object configuration
|
||||||
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
class ModuleDocFragment(object):
|
class ModuleDocFragment(object):
|
||||||
|
DOCUMENTATION = r"""
|
||||||
DOCUMENTATION = r'''
|
|
||||||
options:
|
options:
|
||||||
resource_definition:
|
resource_definition:
|
||||||
description:
|
description:
|
||||||
@@ -28,6 +28,7 @@ options:
|
|||||||
- Reads from the local file system. To read from the Ansible controller's file system, including vaulted files, use the file lookup
|
- Reads from the local file system. To read from the Ansible controller's file system, including vaulted files, use the file lookup
|
||||||
plugin or template lookup plugin, combined with the from_yaml filter, and pass the result to
|
plugin or template lookup plugin, combined with the from_yaml filter, and pass the result to
|
||||||
I(resource_definition). See Examples below.
|
I(resource_definition). See Examples below.
|
||||||
- Mutually exclusive with I(template) in case of M(k8s) module.
|
- The URL to manifest files that can be used to create the resource. Added in version 2.4.0.
|
||||||
|
- Mutually exclusive with I(template) in case of M(kubernetes.core.k8s) module.
|
||||||
type: path
|
type: path
|
||||||
'''
|
"""
|
||||||
|
|||||||
@@ -5,13 +5,13 @@
|
|||||||
|
|
||||||
# Options used by scale modules.
|
# Options used by scale modules.
|
||||||
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
class ModuleDocFragment(object):
|
class ModuleDocFragment(object):
|
||||||
|
DOCUMENTATION = r"""
|
||||||
DOCUMENTATION = r'''
|
|
||||||
options:
|
options:
|
||||||
replicas:
|
replicas:
|
||||||
description:
|
description:
|
||||||
@@ -46,4 +46,4 @@ options:
|
|||||||
default: 5
|
default: 5
|
||||||
type: int
|
type: int
|
||||||
version_added: 2.0.0
|
version_added: 2.0.0
|
||||||
'''
|
"""
|
||||||
|
|||||||
@@ -5,13 +5,13 @@
|
|||||||
|
|
||||||
# Options for specifying object state
|
# Options for specifying object state
|
||||||
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
class ModuleDocFragment(object):
|
class ModuleDocFragment(object):
|
||||||
|
DOCUMENTATION = r"""
|
||||||
DOCUMENTATION = r'''
|
|
||||||
options:
|
options:
|
||||||
state:
|
state:
|
||||||
description:
|
description:
|
||||||
@@ -27,4 +27,4 @@ options:
|
|||||||
- If set to C(yes), and I(state) is C(present), an existing object will be replaced.
|
- If set to C(yes), and I(state) is C(present), an existing object will be replaced.
|
||||||
type: bool
|
type: bool
|
||||||
default: no
|
default: no
|
||||||
'''
|
"""
|
||||||
|
|||||||
@@ -5,13 +5,13 @@
|
|||||||
|
|
||||||
# Options for specifying object wait
|
# Options for specifying object wait
|
||||||
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
class ModuleDocFragment(object):
|
class ModuleDocFragment(object):
|
||||||
|
DOCUMENTATION = r"""
|
||||||
DOCUMENTATION = r'''
|
|
||||||
options:
|
options:
|
||||||
wait:
|
wait:
|
||||||
description:
|
description:
|
||||||
@@ -64,4 +64,4 @@ options:
|
|||||||
- The possible reasons in a condition are specific to each resource type in Kubernetes.
|
- The possible reasons in a condition are specific to each resource type in Kubernetes.
|
||||||
- See the API documentation of the status field for a given resource to see possible choices.
|
- See the API documentation of the status field for a given resource to see possible choices.
|
||||||
type: dict
|
type: dict
|
||||||
'''
|
"""
|
||||||
|
|||||||
@@ -2,12 +2,15 @@
|
|||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
from ansible.errors import AnsibleFilterError
|
from ansible.errors import AnsibleFilterError
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.hashes import generate_hash
|
from ansible_collections.kubernetes.core.plugins.module_utils.hashes import (
|
||||||
|
generate_hash,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def k8s_config_resource_name(resource):
|
def k8s_config_resource_name(resource):
|
||||||
@@ -15,15 +18,14 @@ def k8s_config_resource_name(resource):
|
|||||||
Generate resource name for the given resource of type ConfigMap, Secret
|
Generate resource name for the given resource of type ConfigMap, Secret
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return resource['metadata']['name'] + '-' + generate_hash(resource)
|
return resource["metadata"]["name"] + "-" + generate_hash(resource)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise AnsibleFilterError("resource must have a metadata.name key to generate a resource name")
|
raise AnsibleFilterError(
|
||||||
|
"resource must have a metadata.name key to generate a resource name"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# ---- Ansible filters ----
|
# ---- Ansible filters ----
|
||||||
class FilterModule(object):
|
class FilterModule(object):
|
||||||
|
|
||||||
def filters(self):
|
def filters(self):
|
||||||
return {
|
return {"k8s_config_resource_name": k8s_config_resource_name}
|
||||||
'k8s_config_resource_name': k8s_config_resource_name
|
|
||||||
}
|
|
||||||
|
|||||||
36
plugins/filter/k8s_config_resource_name.yml
Normal file
36
plugins/filter/k8s_config_resource_name.yml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
# Copyright (c) Ansible Project
|
||||||
|
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
DOCUMENTATION:
|
||||||
|
name: k8s_config_resource_name
|
||||||
|
short_description: Generate resource name for the given resource of type ConfigMap, Secret
|
||||||
|
description:
|
||||||
|
- Generate resource name for the given resource of type ConfigMap, Secret.
|
||||||
|
- Resource must have a C(metadata.name) key to generate a resource name
|
||||||
|
options:
|
||||||
|
_input:
|
||||||
|
description:
|
||||||
|
- A valid YAML definition for a ConfigMap or a Secret.
|
||||||
|
type: dict
|
||||||
|
required: true
|
||||||
|
author:
|
||||||
|
- ansible cloud team
|
||||||
|
|
||||||
|
EXAMPLES: |
|
||||||
|
# Dump generated name for a configmap into a variable
|
||||||
|
- set_fact:
|
||||||
|
generated_name: '{{ definition | kubernetes.core.k8s_config_resource_name }}'
|
||||||
|
vars:
|
||||||
|
definition:
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: myconfigmap
|
||||||
|
namespace: mynamespace
|
||||||
|
|
||||||
|
RETURN:
|
||||||
|
_value:
|
||||||
|
description: Generated resource name.
|
||||||
|
type: str
|
||||||
@@ -1,363 +0,0 @@
|
|||||||
# Copyright (c) 2018 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
|
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
|
||||||
name: k8s
|
|
||||||
plugin_type: inventory
|
|
||||||
author:
|
|
||||||
- Chris Houseknecht <@chouseknecht>
|
|
||||||
- Fabian von Feilitzsch <@fabianvf>
|
|
||||||
|
|
||||||
short_description: Kubernetes (K8s) inventory source
|
|
||||||
|
|
||||||
description:
|
|
||||||
- Fetch containers and services for one or more clusters.
|
|
||||||
- Groups by cluster name, namespace, namespace_services, namespace_pods, and labels.
|
|
||||||
- Uses the kubectl connection plugin to access the Kubernetes cluster.
|
|
||||||
- Uses k8s.(yml|yaml) YAML configuration file to set parameter values.
|
|
||||||
|
|
||||||
options:
|
|
||||||
plugin:
|
|
||||||
description: token that ensures this is a source file for the 'k8s' plugin.
|
|
||||||
required: True
|
|
||||||
choices: ['kubernetes.core.k8s', 'k8s', 'community.kubernetes.k8s']
|
|
||||||
connections:
|
|
||||||
description:
|
|
||||||
- Optional list of cluster connection settings. If no connections are provided, the default
|
|
||||||
I(~/.kube/config) and active context will be used, and objects will be returned for all namespaces
|
|
||||||
the active user is authorized to access.
|
|
||||||
suboptions:
|
|
||||||
name:
|
|
||||||
description:
|
|
||||||
- Optional name to assign to the cluster. If not provided, a name is constructed from the server
|
|
||||||
and port.
|
|
||||||
kubeconfig:
|
|
||||||
description:
|
|
||||||
- Path to an existing Kubernetes config file. If not provided, and no other connection
|
|
||||||
options are provided, the Kubernetes client will attempt to load the default
|
|
||||||
configuration file from I(~/.kube/config). Can also be specified via K8S_AUTH_KUBECONFIG
|
|
||||||
environment variable.
|
|
||||||
context:
|
|
||||||
description:
|
|
||||||
- The name of a context found in the config file. Can also be specified via K8S_AUTH_CONTEXT environment
|
|
||||||
variable.
|
|
||||||
host:
|
|
||||||
description:
|
|
||||||
- Provide a URL for accessing the API. Can also be specified via K8S_AUTH_HOST environment variable.
|
|
||||||
api_key:
|
|
||||||
description:
|
|
||||||
- Token used to authenticate with the API. Can also be specified via K8S_AUTH_API_KEY environment
|
|
||||||
variable.
|
|
||||||
username:
|
|
||||||
description:
|
|
||||||
- Provide a username for authenticating with the API. Can also be specified via K8S_AUTH_USERNAME
|
|
||||||
environment variable.
|
|
||||||
password:
|
|
||||||
description:
|
|
||||||
- Provide a password for authenticating with the API. Can also be specified via K8S_AUTH_PASSWORD
|
|
||||||
environment variable.
|
|
||||||
client_cert:
|
|
||||||
description:
|
|
||||||
- Path to a certificate used to authenticate with the API. Can also be specified via K8S_AUTH_CERT_FILE
|
|
||||||
environment variable.
|
|
||||||
aliases: [ cert_file ]
|
|
||||||
client_key:
|
|
||||||
description:
|
|
||||||
- Path to a key file used to authenticate with the API. Can also be specified via K8S_AUTH_KEY_FILE
|
|
||||||
environment variable.
|
|
||||||
aliases: [ key_file ]
|
|
||||||
ca_cert:
|
|
||||||
description:
|
|
||||||
- Path to a CA certificate used to authenticate with the API. Can also be specified via
|
|
||||||
K8S_AUTH_SSL_CA_CERT environment variable.
|
|
||||||
aliases: [ ssl_ca_cert ]
|
|
||||||
validate_certs:
|
|
||||||
description:
|
|
||||||
- "Whether or not to verify the API server's SSL certificates. Can also be specified via
|
|
||||||
K8S_AUTH_VERIFY_SSL environment variable."
|
|
||||||
type: bool
|
|
||||||
aliases: [ verify_ssl ]
|
|
||||||
namespaces:
|
|
||||||
description:
|
|
||||||
- List of namespaces. If not specified, will fetch all containers for all namespaces user is authorized
|
|
||||||
to access.
|
|
||||||
|
|
||||||
requirements:
|
|
||||||
- "python >= 3.6"
|
|
||||||
- "kubernetes >= 12.0.0"
|
|
||||||
- "PyYAML >= 3.11"
|
|
||||||
'''
|
|
||||||
|
|
||||||
EXAMPLES = '''
|
|
||||||
# File must be named k8s.yaml or k8s.yml
|
|
||||||
|
|
||||||
# Authenticate with token, and return all pods and services for all namespaces
|
|
||||||
plugin: kubernetes.core.k8s
|
|
||||||
connections:
|
|
||||||
- host: https://192.168.64.4:8443
|
|
||||||
api_key: xxxxxxxxxxxxxxxx
|
|
||||||
validate_certs: false
|
|
||||||
|
|
||||||
# Use default config (~/.kube/config) file and active context, and return objects for a specific namespace
|
|
||||||
plugin: kubernetes.core.k8s
|
|
||||||
connections:
|
|
||||||
- namespaces:
|
|
||||||
- testing
|
|
||||||
|
|
||||||
# Use a custom config file, and a specific context.
|
|
||||||
plugin: kubernetes.core.k8s
|
|
||||||
connections:
|
|
||||||
- kubeconfig: /path/to/config
|
|
||||||
context: 'awx/192-168-64-4:8443/developer'
|
|
||||||
'''
|
|
||||||
|
|
||||||
import json
|
|
||||||
|
|
||||||
from ansible.errors import AnsibleError
|
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.common import K8sAnsibleMixin, HAS_K8S_MODULE_HELPER, k8s_import_exception, get_api_client
|
|
||||||
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cacheable
|
|
||||||
|
|
||||||
try:
|
|
||||||
from kubernetes.dynamic.exceptions import DynamicApiError
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
class K8sInventoryException(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable, K8sAnsibleMixin):
|
|
||||||
NAME = 'kubernetes.core.k8s'
|
|
||||||
|
|
||||||
connection_plugin = 'kubernetes.core.kubectl'
|
|
||||||
transport = 'kubectl'
|
|
||||||
|
|
||||||
def parse(self, inventory, loader, path, cache=True):
|
|
||||||
super(InventoryModule, self).parse(inventory, loader, path)
|
|
||||||
cache_key = self._get_cache_prefix(path)
|
|
||||||
config_data = self._read_config_data(path)
|
|
||||||
self.setup(config_data, cache, cache_key)
|
|
||||||
|
|
||||||
def setup(self, config_data, cache, cache_key):
|
|
||||||
connections = config_data.get('connections')
|
|
||||||
|
|
||||||
if not HAS_K8S_MODULE_HELPER:
|
|
||||||
raise K8sInventoryException(
|
|
||||||
"This module requires the Kubernetes Python client. Try `pip install kubernetes`. Detail: {0}".format(k8s_import_exception)
|
|
||||||
)
|
|
||||||
|
|
||||||
source_data = None
|
|
||||||
if cache and cache_key in self._cache:
|
|
||||||
try:
|
|
||||||
source_data = self._cache[cache_key]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if not source_data:
|
|
||||||
self.fetch_objects(connections)
|
|
||||||
|
|
||||||
def fetch_objects(self, connections):
|
|
||||||
|
|
||||||
if connections:
|
|
||||||
if not isinstance(connections, list):
|
|
||||||
raise K8sInventoryException("Expecting connections to be a list.")
|
|
||||||
|
|
||||||
for connection in connections:
|
|
||||||
if not isinstance(connection, dict):
|
|
||||||
raise K8sInventoryException("Expecting connection to be a dictionary.")
|
|
||||||
client = get_api_client(**connection)
|
|
||||||
name = connection.get('name', self.get_default_host_name(client.configuration.host))
|
|
||||||
if connection.get('namespaces'):
|
|
||||||
namespaces = connection['namespaces']
|
|
||||||
else:
|
|
||||||
namespaces = self.get_available_namespaces(client)
|
|
||||||
for namespace in namespaces:
|
|
||||||
self.get_pods_for_namespace(client, name, namespace)
|
|
||||||
self.get_services_for_namespace(client, name, namespace)
|
|
||||||
else:
|
|
||||||
client = get_api_client()
|
|
||||||
name = self.get_default_host_name(client.configuration.host)
|
|
||||||
namespaces = self.get_available_namespaces(client)
|
|
||||||
for namespace in namespaces:
|
|
||||||
self.get_pods_for_namespace(client, name, namespace)
|
|
||||||
self.get_services_for_namespace(client, name, namespace)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_default_host_name(host):
|
|
||||||
return host.replace('https://', '').replace('http://', '').replace('.', '-').replace(':', '_')
|
|
||||||
|
|
||||||
def get_available_namespaces(self, client):
|
|
||||||
v1_namespace = client.resources.get(api_version='v1', kind='Namespace')
|
|
||||||
try:
|
|
||||||
obj = v1_namespace.get()
|
|
||||||
except DynamicApiError as exc:
|
|
||||||
self.display.debug(exc)
|
|
||||||
raise K8sInventoryException('Error fetching Namespace list: %s' % format_dynamic_api_exc(exc))
|
|
||||||
return [namespace.metadata.name for namespace in obj.items]
|
|
||||||
|
|
||||||
def get_pods_for_namespace(self, client, name, namespace):
|
|
||||||
v1_pod = client.resources.get(api_version='v1', kind='Pod')
|
|
||||||
try:
|
|
||||||
obj = v1_pod.get(namespace=namespace)
|
|
||||||
except DynamicApiError as exc:
|
|
||||||
self.display.debug(exc)
|
|
||||||
raise K8sInventoryException('Error fetching Pod list: %s' % format_dynamic_api_exc(exc))
|
|
||||||
|
|
||||||
namespace_group = 'namespace_{0}'.format(namespace)
|
|
||||||
namespace_pods_group = '{0}_pods'.format(namespace_group)
|
|
||||||
|
|
||||||
self.inventory.add_group(name)
|
|
||||||
self.inventory.add_group(namespace_group)
|
|
||||||
self.inventory.add_child(name, namespace_group)
|
|
||||||
self.inventory.add_group(namespace_pods_group)
|
|
||||||
self.inventory.add_child(namespace_group, namespace_pods_group)
|
|
||||||
|
|
||||||
for pod in obj.items:
|
|
||||||
pod_name = pod.metadata.name
|
|
||||||
pod_groups = []
|
|
||||||
pod_annotations = {} if not pod.metadata.annotations else dict(pod.metadata.annotations)
|
|
||||||
|
|
||||||
if pod.metadata.labels:
|
|
||||||
# create a group for each label_value
|
|
||||||
for key, value in pod.metadata.labels:
|
|
||||||
group_name = 'label_{0}_{1}'.format(key, value)
|
|
||||||
if group_name not in pod_groups:
|
|
||||||
pod_groups.append(group_name)
|
|
||||||
self.inventory.add_group(group_name)
|
|
||||||
pod_labels = dict(pod.metadata.labels)
|
|
||||||
else:
|
|
||||||
pod_labels = {}
|
|
||||||
|
|
||||||
if not pod.status.containerStatuses:
|
|
||||||
continue
|
|
||||||
|
|
||||||
for container in pod.status.containerStatuses:
|
|
||||||
# add each pod_container to the namespace group, and to each label_value group
|
|
||||||
container_name = '{0}_{1}'.format(pod.metadata.name, container.name)
|
|
||||||
self.inventory.add_host(container_name)
|
|
||||||
self.inventory.add_child(namespace_pods_group, container_name)
|
|
||||||
if pod_groups:
|
|
||||||
for group in pod_groups:
|
|
||||||
self.inventory.add_child(group, container_name)
|
|
||||||
|
|
||||||
# Add hostvars
|
|
||||||
self.inventory.set_variable(container_name, 'object_type', 'pod')
|
|
||||||
self.inventory.set_variable(container_name, 'labels', pod_labels)
|
|
||||||
self.inventory.set_variable(container_name, 'annotations', pod_annotations)
|
|
||||||
self.inventory.set_variable(container_name, 'cluster_name', pod.metadata.clusterName)
|
|
||||||
self.inventory.set_variable(container_name, 'pod_node_name', pod.spec.nodeName)
|
|
||||||
self.inventory.set_variable(container_name, 'pod_name', pod.spec.name)
|
|
||||||
self.inventory.set_variable(container_name, 'pod_host_ip', pod.status.hostIP)
|
|
||||||
self.inventory.set_variable(container_name, 'pod_phase', pod.status.phase)
|
|
||||||
self.inventory.set_variable(container_name, 'pod_ip', pod.status.podIP)
|
|
||||||
self.inventory.set_variable(container_name, 'pod_self_link', pod.metadata.selfLink)
|
|
||||||
self.inventory.set_variable(container_name, 'pod_resource_version', pod.metadata.resourceVersion)
|
|
||||||
self.inventory.set_variable(container_name, 'pod_uid', pod.metadata.uid)
|
|
||||||
self.inventory.set_variable(container_name, 'container_name', container.image)
|
|
||||||
self.inventory.set_variable(container_name, 'container_image', container.image)
|
|
||||||
if container.state.running:
|
|
||||||
self.inventory.set_variable(container_name, 'container_state', 'Running')
|
|
||||||
if container.state.terminated:
|
|
||||||
self.inventory.set_variable(container_name, 'container_state', 'Terminated')
|
|
||||||
if container.state.waiting:
|
|
||||||
self.inventory.set_variable(container_name, 'container_state', 'Waiting')
|
|
||||||
self.inventory.set_variable(container_name, 'container_ready', container.ready)
|
|
||||||
self.inventory.set_variable(container_name, 'ansible_remote_tmp', '/tmp/')
|
|
||||||
self.inventory.set_variable(container_name, 'ansible_connection', self.connection_plugin)
|
|
||||||
self.inventory.set_variable(container_name, 'ansible_{0}_pod'.format(self.transport),
|
|
||||||
pod_name)
|
|
||||||
self.inventory.set_variable(container_name, 'ansible_{0}_container'.format(self.transport),
|
|
||||||
container.name)
|
|
||||||
self.inventory.set_variable(container_name, 'ansible_{0}_namespace'.format(self.transport),
|
|
||||||
namespace)
|
|
||||||
|
|
||||||
def get_services_for_namespace(self, client, name, namespace):
|
|
||||||
v1_service = client.resources.get(api_version='v1', kind='Service')
|
|
||||||
try:
|
|
||||||
obj = v1_service.get(namespace=namespace)
|
|
||||||
except DynamicApiError as exc:
|
|
||||||
self.display.debug(exc)
|
|
||||||
raise K8sInventoryException('Error fetching Service list: %s' % format_dynamic_api_exc(exc))
|
|
||||||
|
|
||||||
namespace_group = 'namespace_{0}'.format(namespace)
|
|
||||||
namespace_services_group = '{0}_services'.format(namespace_group)
|
|
||||||
|
|
||||||
self.inventory.add_group(name)
|
|
||||||
self.inventory.add_group(namespace_group)
|
|
||||||
self.inventory.add_child(name, namespace_group)
|
|
||||||
self.inventory.add_group(namespace_services_group)
|
|
||||||
self.inventory.add_child(namespace_group, namespace_services_group)
|
|
||||||
|
|
||||||
for service in obj.items:
|
|
||||||
service_name = service.metadata.name
|
|
||||||
service_labels = {} if not service.metadata.labels else dict(service.metadata.labels)
|
|
||||||
service_annotations = {} if not service.metadata.annotations else dict(service.metadata.annotations)
|
|
||||||
|
|
||||||
self.inventory.add_host(service_name)
|
|
||||||
|
|
||||||
if service.metadata.labels:
|
|
||||||
# create a group for each label_value
|
|
||||||
for key, value in service.metadata.labels:
|
|
||||||
group_name = 'label_{0}_{1}'.format(key, value)
|
|
||||||
self.inventory.add_group(group_name)
|
|
||||||
self.inventory.add_child(group_name, service_name)
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.inventory.add_child(namespace_services_group, service_name)
|
|
||||||
except AnsibleError:
|
|
||||||
raise
|
|
||||||
|
|
||||||
ports = [{'name': port.name,
|
|
||||||
'port': port.port,
|
|
||||||
'protocol': port.protocol,
|
|
||||||
'targetPort': port.targetPort,
|
|
||||||
'nodePort': port.nodePort} for port in service.spec.ports or []]
|
|
||||||
|
|
||||||
# add hostvars
|
|
||||||
self.inventory.set_variable(service_name, 'object_type', 'service')
|
|
||||||
self.inventory.set_variable(service_name, 'labels', service_labels)
|
|
||||||
self.inventory.set_variable(service_name, 'annotations', service_annotations)
|
|
||||||
self.inventory.set_variable(service_name, 'cluster_name', service.metadata.clusterName)
|
|
||||||
self.inventory.set_variable(service_name, 'ports', ports)
|
|
||||||
self.inventory.set_variable(service_name, 'type', service.spec.type)
|
|
||||||
self.inventory.set_variable(service_name, 'self_link', service.metadata.selfLink)
|
|
||||||
self.inventory.set_variable(service_name, 'resource_version', service.metadata.resourceVersion)
|
|
||||||
self.inventory.set_variable(service_name, 'uid', service.metadata.uid)
|
|
||||||
|
|
||||||
if service.spec.externalTrafficPolicy:
|
|
||||||
self.inventory.set_variable(service_name, 'external_traffic_policy',
|
|
||||||
service.spec.externalTrafficPolicy)
|
|
||||||
if service.spec.externalIPs:
|
|
||||||
self.inventory.set_variable(service_name, 'external_ips', service.spec.externalIPs)
|
|
||||||
|
|
||||||
if service.spec.externalName:
|
|
||||||
self.inventory.set_variable(service_name, 'external_name', service.spec.externalName)
|
|
||||||
|
|
||||||
if service.spec.healthCheckNodePort:
|
|
||||||
self.inventory.set_variable(service_name, 'health_check_node_port',
|
|
||||||
service.spec.healthCheckNodePort)
|
|
||||||
if service.spec.loadBalancerIP:
|
|
||||||
self.inventory.set_variable(service_name, 'load_balancer_ip',
|
|
||||||
service.spec.loadBalancerIP)
|
|
||||||
if service.spec.selector:
|
|
||||||
self.inventory.set_variable(service_name, 'selector', dict(service.spec.selector))
|
|
||||||
|
|
||||||
if hasattr(service.status.loadBalancer, 'ingress') and service.status.loadBalancer.ingress:
|
|
||||||
load_balancer = [{'hostname': ingress.hostname,
|
|
||||||
'ip': ingress.ip} for ingress in service.status.loadBalancer.ingress]
|
|
||||||
self.inventory.set_variable(service_name, 'load_balancer', load_balancer)
|
|
||||||
@@ -3,25 +3,28 @@
|
|||||||
#
|
#
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
DOCUMENTATION = '''
|
DOCUMENTATION = """
|
||||||
lookup: k8s
|
name: k8s
|
||||||
|
|
||||||
short_description: Query the K8s API
|
short_description: Query the K8s API
|
||||||
|
|
||||||
author:
|
author:
|
||||||
- Chris Houseknecht <@chouseknecht>
|
- Chris Houseknecht (@chouseknecht)
|
||||||
- Fabian von Feilitzsch <@fabianvf>
|
- Fabian von Feilitzsch (@fabianvf)
|
||||||
|
|
||||||
description:
|
description:
|
||||||
- Uses the Kubernetes Python client to fetch a specific object by name, all matching objects within a
|
- Uses the Kubernetes Python client to fetch a specific object by name, all matching objects within a
|
||||||
namespace, or all matching objects for all namespaces, as well as information about the cluster.
|
namespace, or all matching objects for all namespaces, as well as information about the cluster.
|
||||||
- Provides access the full range of K8s APIs.
|
- Provides access the full range of K8s APIs.
|
||||||
- Enables authentication via config file, certificates, password or token.
|
- Enables authentication via config file, certificates, password or token.
|
||||||
|
notes:
|
||||||
|
- While querying, please use C(query) or C(lookup) format with C(wantlist=True) to provide an easier and more
|
||||||
|
consistent interface. For more details, see
|
||||||
|
U(https://docs.ansible.com/ansible/latest/plugins/lookup.html#forcing-lookups-to-return-lists-query-and-wantlist-true).
|
||||||
options:
|
options:
|
||||||
cluster_info:
|
cluster_info:
|
||||||
description:
|
description:
|
||||||
@@ -111,31 +114,31 @@ DOCUMENTATION = '''
|
|||||||
aliases: [ verify_ssl ]
|
aliases: [ verify_ssl ]
|
||||||
|
|
||||||
requirements:
|
requirements:
|
||||||
- "python >= 3.6"
|
- "python >= 3.9"
|
||||||
- "kubernetes >= 12.0.0"
|
- "kubernetes >= 24.2.0"
|
||||||
- "PyYAML >= 3.11"
|
- "PyYAML >= 3.11"
|
||||||
'''
|
"""
|
||||||
|
|
||||||
EXAMPLES = """
|
EXAMPLES = """
|
||||||
- name: Fetch a list of namespaces
|
- name: Fetch a list of namespaces
|
||||||
set_fact:
|
set_fact:
|
||||||
projects: "{{ lookup('kubernetes.core.k8s', api_version='v1', kind='Namespace') }}"
|
projects: "{{ query('kubernetes.core.k8s', api_version='v1', kind='Namespace') }}"
|
||||||
|
|
||||||
- name: Fetch all deployments
|
- name: Fetch all deployments
|
||||||
set_fact:
|
set_fact:
|
||||||
deployments: "{{ lookup('kubernetes.core.k8s', kind='Deployment') }}"
|
deployments: "{{ query('kubernetes.core.k8s', kind='Deployment') }}"
|
||||||
|
|
||||||
- name: Fetch all deployments in a namespace
|
- name: Fetch all deployments in a namespace
|
||||||
set_fact:
|
set_fact:
|
||||||
deployments: "{{ lookup('kubernetes.core.k8s', kind='Deployment', namespace='testing') }}"
|
deployments: "{{ query('kubernetes.core.k8s', kind='Deployment', namespace='testing') }}"
|
||||||
|
|
||||||
- name: Fetch a specific deployment by name
|
- name: Fetch a specific deployment by name
|
||||||
set_fact:
|
set_fact:
|
||||||
deployments: "{{ lookup('kubernetes.core.k8s', kind='Deployment', namespace='testing', resource_name='elastic') }}"
|
deployments: "{{ query('kubernetes.core.k8s', kind='Deployment', namespace='testing', resource_name='elastic') }}"
|
||||||
|
|
||||||
- name: Fetch with label selector
|
- name: Fetch with label selector
|
||||||
set_fact:
|
set_fact:
|
||||||
service: "{{ lookup('kubernetes.core.k8s', kind='Service', label_selector='app=galaxy') }}"
|
service: "{{ query('kubernetes.core.k8s', kind='Service', label_selector='app=galaxy') }}"
|
||||||
|
|
||||||
# Use parameters from a YAML config
|
# Use parameters from a YAML config
|
||||||
|
|
||||||
@@ -145,50 +148,62 @@ EXAMPLES = """
|
|||||||
|
|
||||||
- name: Using the config (loaded from a file in prior task), fetch the latest version of the object
|
- name: Using the config (loaded from a file in prior task), fetch the latest version of the object
|
||||||
set_fact:
|
set_fact:
|
||||||
service: "{{ lookup('kubernetes.core.k8s', resource_definition=config) }}"
|
service: "{{ query('kubernetes.core.k8s', resource_definition=config) }}"
|
||||||
|
|
||||||
- name: Use a config from the local filesystem
|
- name: Use a config from the local filesystem
|
||||||
set_fact:
|
set_fact:
|
||||||
service: "{{ lookup('kubernetes.core.k8s', src='service.yml') }}"
|
service: "{{ query('kubernetes.core.k8s', src='service.yml') }}"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
RETURN = """
|
RETURN = """
|
||||||
_list:
|
_list:
|
||||||
description:
|
description:
|
||||||
- One ore more object definitions returned from the API.
|
- One ore more object definitions returned from the API.
|
||||||
type: complex
|
type: list
|
||||||
contains:
|
elements: dict
|
||||||
api_version:
|
sample:
|
||||||
description: The versioned schema of this representation of an object.
|
- kind: ConfigMap
|
||||||
returned: success
|
apiVersion: v1
|
||||||
type: str
|
metadata:
|
||||||
kind:
|
creationTimestamp: "2022-03-04T13:59:49Z"
|
||||||
description: Represents the REST resource this object represents.
|
name: my-config-map
|
||||||
returned: success
|
namespace: default
|
||||||
type: str
|
resourceVersion: "418"
|
||||||
metadata:
|
uid: 5714b011-d090-4eac-8272-a0ea82ec0abd
|
||||||
description: Standard object metadata. Includes name, namespace, annotations, labels, etc.
|
data:
|
||||||
returned: success
|
key1: val1
|
||||||
type: complex
|
|
||||||
spec:
|
|
||||||
description: Specific attributes of the object. Will vary based on the I(api_version) and I(kind).
|
|
||||||
returned: success
|
|
||||||
type: complex
|
|
||||||
status:
|
|
||||||
description: Current status details for the object.
|
|
||||||
returned: success
|
|
||||||
type: complex
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
from ansible.errors import AnsibleError
|
from ansible.errors import AnsibleError
|
||||||
from ansible.module_utils.common._collections_compat import KeysView
|
from ansible.module_utils.common._collections_compat import KeysView
|
||||||
from ansible.plugins.lookup import LookupBase
|
from ansible.module_utils.common.validation import check_type_bool
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
||||||
|
get_api_client,
|
||||||
|
)
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.resource import (
|
||||||
|
create_definitions,
|
||||||
|
)
|
||||||
|
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.common import K8sAnsibleMixin, get_api_client
|
try:
|
||||||
|
enable_turbo_mode = check_type_bool(os.environ.get("ENABLE_TURBO_MODE"))
|
||||||
|
except TypeError:
|
||||||
|
enable_turbo_mode = False
|
||||||
|
|
||||||
|
if enable_turbo_mode:
|
||||||
|
try:
|
||||||
|
from ansible_collections.cloud.common.plugins.plugin_utils.turbo.lookup import (
|
||||||
|
TurboLookupBase as LookupBase,
|
||||||
|
)
|
||||||
|
except ImportError:
|
||||||
|
from ansible.plugins.lookup import LookupBase # noqa: F401
|
||||||
|
else:
|
||||||
|
from ansible.plugins.lookup import LookupBase # noqa: F401
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from kubernetes.dynamic.exceptions import NotFoundError
|
from kubernetes.dynamic.exceptions import NotFoundError
|
||||||
|
|
||||||
HAS_K8S_MODULE_HELPER = True
|
HAS_K8S_MODULE_HELPER = True
|
||||||
k8s_import_exception = None
|
k8s_import_exception = None
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
@@ -196,13 +211,13 @@ except ImportError as e:
|
|||||||
k8s_import_exception = e
|
k8s_import_exception = e
|
||||||
|
|
||||||
|
|
||||||
class KubernetesLookup(K8sAnsibleMixin):
|
class KubernetesLookup(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
if not HAS_K8S_MODULE_HELPER:
|
if not HAS_K8S_MODULE_HELPER:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"Requires the Kubernetes Python client. Try `pip install kubernetes`. Detail: {0}".format(k8s_import_exception)
|
"Requires the Kubernetes Python client. Try `pip install kubernetes`. Detail: {0}".format(
|
||||||
|
k8s_import_exception
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.kind = None
|
self.kind = None
|
||||||
@@ -223,31 +238,38 @@ class KubernetesLookup(K8sAnsibleMixin):
|
|||||||
self.params = kwargs
|
self.params = kwargs
|
||||||
self.client = get_api_client(**kwargs)
|
self.client = get_api_client(**kwargs)
|
||||||
|
|
||||||
cluster_info = kwargs.get('cluster_info')
|
cluster_info = kwargs.get("cluster_info")
|
||||||
if cluster_info == 'version':
|
if cluster_info == "version":
|
||||||
return [self.client.version]
|
return [self.client.client.version]
|
||||||
if cluster_info == 'api_groups':
|
if cluster_info == "api_groups":
|
||||||
if isinstance(self.client.resources.api_groups, KeysView):
|
if isinstance(self.client.resources.api_groups, KeysView):
|
||||||
return [list(self.client.resources.api_groups)]
|
return [list(self.client.resources.api_groups)]
|
||||||
return [self.client.resources.api_groups]
|
return [self.client.resources.api_groups]
|
||||||
|
|
||||||
self.kind = kwargs.get('kind')
|
self.kind = kwargs.get("kind")
|
||||||
self.name = kwargs.get('resource_name')
|
self.name = kwargs.get("resource_name")
|
||||||
self.namespace = kwargs.get('namespace')
|
self.namespace = kwargs.get("namespace")
|
||||||
self.api_version = kwargs.get('api_version', 'v1')
|
self.api_version = kwargs.get("api_version", "v1")
|
||||||
self.label_selector = kwargs.get('label_selector')
|
self.label_selector = kwargs.get("label_selector")
|
||||||
self.field_selector = kwargs.get('field_selector')
|
self.field_selector = kwargs.get("field_selector")
|
||||||
self.include_uninitialized = kwargs.get('include_uninitialized', False)
|
self.include_uninitialized = kwargs.get("include_uninitialized", False)
|
||||||
|
|
||||||
resource_definition = kwargs.get('resource_definition')
|
resource_definition = kwargs.get("resource_definition")
|
||||||
src = kwargs.get('src')
|
src = kwargs.get("src")
|
||||||
if src:
|
if src:
|
||||||
resource_definition = self.load_resource_definitions(src)[0]
|
definitions = create_definitions(params=dict(src=src))
|
||||||
|
if definitions:
|
||||||
|
self.kind = definitions[0].kind
|
||||||
|
self.name = definitions[0].name
|
||||||
|
self.namespace = definitions[0].namespace
|
||||||
|
self.api_version = definitions[0].api_version or "v1"
|
||||||
if resource_definition:
|
if resource_definition:
|
||||||
self.kind = resource_definition.get('kind', self.kind)
|
self.kind = resource_definition.get("kind", self.kind)
|
||||||
self.api_version = resource_definition.get('apiVersion', self.api_version)
|
self.api_version = resource_definition.get("apiVersion", self.api_version)
|
||||||
self.name = resource_definition.get('metadata', {}).get('name', self.name)
|
self.name = resource_definition.get("metadata", {}).get("name", self.name)
|
||||||
self.namespace = resource_definition.get('metadata', {}).get('namespace', self.namespace)
|
self.namespace = resource_definition.get("metadata", {}).get(
|
||||||
|
"namespace", self.namespace
|
||||||
|
)
|
||||||
|
|
||||||
if not self.kind:
|
if not self.kind:
|
||||||
raise AnsibleError(
|
raise AnsibleError(
|
||||||
@@ -255,19 +277,26 @@ class KubernetesLookup(K8sAnsibleMixin):
|
|||||||
"using the 'resource_definition' parameter."
|
"using the 'resource_definition' parameter."
|
||||||
)
|
)
|
||||||
|
|
||||||
resource = self.find_resource(self.kind, self.api_version, fail=True)
|
resource = self.client.resource(self.kind, self.api_version)
|
||||||
try:
|
try:
|
||||||
k8s_obj = resource.get(name=self.name, namespace=self.namespace, label_selector=self.label_selector, field_selector=self.field_selector)
|
params = dict(
|
||||||
|
name=self.name,
|
||||||
|
namespace=self.namespace,
|
||||||
|
label_selector=self.label_selector,
|
||||||
|
field_selector=self.field_selector,
|
||||||
|
)
|
||||||
|
k8s_obj = self.client.get(resource, **params)
|
||||||
except NotFoundError:
|
except NotFoundError:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
if self.name:
|
if self.name:
|
||||||
return [k8s_obj.to_dict()]
|
return [k8s_obj.to_dict()]
|
||||||
|
|
||||||
return [k8s_obj.to_dict().get('items')]
|
return k8s_obj.to_dict().get("items")
|
||||||
|
|
||||||
|
|
||||||
class LookupModule(LookupBase):
|
class LookupModule(LookupBase):
|
||||||
|
def _run(self, terms, variables=None, **kwargs):
|
||||||
def run(self, terms, variables=None, **kwargs):
|
|
||||||
return KubernetesLookup().run(terms, variables=variables, **kwargs)
|
return KubernetesLookup().run(terms, variables=variables, **kwargs)
|
||||||
|
|
||||||
|
run = _run if not hasattr(LookupBase, "run_on_daemon") else LookupBase.run_on_daemon
|
||||||
|
|||||||
191
plugins/lookup/kustomize.py
Normal file
191
plugins/lookup/kustomize.py
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2021 Red Hat | Ansible
|
||||||
|
#
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
DOCUMENTATION = """
|
||||||
|
name: kustomize
|
||||||
|
|
||||||
|
short_description: Build a set of kubernetes resources using a 'kustomization.yaml' file.
|
||||||
|
|
||||||
|
version_added: 2.2.0
|
||||||
|
|
||||||
|
author:
|
||||||
|
- Aubin Bikouo (@abikouo)
|
||||||
|
notes:
|
||||||
|
- If both kustomize and kubectl are part of the PATH, kustomize will be used by the plugin.
|
||||||
|
description:
|
||||||
|
- Uses the kustomize or the kubectl tool.
|
||||||
|
- Return the result of C(kustomize build) or C(kubectl kustomize).
|
||||||
|
options:
|
||||||
|
dir:
|
||||||
|
description:
|
||||||
|
- The directory path containing 'kustomization.yaml',
|
||||||
|
or a git repository URL with a path suffix specifying same with respect to the repository root.
|
||||||
|
- If omitted, '.' is assumed.
|
||||||
|
default: "."
|
||||||
|
binary_path:
|
||||||
|
description:
|
||||||
|
- The path of a kustomize or kubectl binary to use.
|
||||||
|
opt_dirs:
|
||||||
|
description:
|
||||||
|
- An optional list of directories to search for the executable in addition to PATH.
|
||||||
|
enable_helm:
|
||||||
|
description:
|
||||||
|
- Enable the helm chart inflation generator
|
||||||
|
default: "False"
|
||||||
|
environment:
|
||||||
|
description:
|
||||||
|
- The environment variables to pass to the kustomize or kubectl command.
|
||||||
|
- This can be a dictionary or a string in the format key=value, multiple pairs separated by space.
|
||||||
|
type: raw
|
||||||
|
default: {}
|
||||||
|
version_added: 6.2.0
|
||||||
|
|
||||||
|
requirements:
|
||||||
|
- "python >= 3.6"
|
||||||
|
"""
|
||||||
|
|
||||||
|
EXAMPLES = """
|
||||||
|
- name: Run lookup using kustomize
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
resources: "{{ lookup('kubernetes.core.kustomize', binary_path='/path/to/kustomize') }}"
|
||||||
|
|
||||||
|
- name: Run lookup using kubectl kustomize
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
resources: "{{ lookup('kubernetes.core.kustomize', binary_path='/path/to/kubectl') }}"
|
||||||
|
|
||||||
|
- name: Create kubernetes resources for lookup output
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
definition: "{{ lookup('kubernetes.core.kustomize', dir='/path/to/kustomization') }}"
|
||||||
|
|
||||||
|
- name: Create kubernetes resources for lookup output with `--enable-helm` set
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
definition: "{{ lookup('kubernetes.core.kustomize', dir='/path/to/kustomization', enable_helm=True) }}"
|
||||||
|
|
||||||
|
- name: Create kubernetes resources for lookup output with environment variables in string format
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
definition: "{{ lookup('kubernetes.core.kustomize', binary_path='/path/to/kubectl', environment='HTTP_PROXY=http://proxy.example.com:3128') }}"
|
||||||
|
|
||||||
|
- name: Create kubernetes resources for lookup output with environment variables in dict format
|
||||||
|
kubernetes.core.k8s:
|
||||||
|
definition: "{{ lookup('kubernetes.core.kustomize', binary_path='/path/to/kubectl', environment={'HTTP_PROXY': 'http://proxy.example.com:3128'}) }}"
|
||||||
|
"""
|
||||||
|
|
||||||
|
RETURN = """
|
||||||
|
_list:
|
||||||
|
description:
|
||||||
|
- YAML string for the object definitions returned from the tool execution.
|
||||||
|
type: str
|
||||||
|
sample:
|
||||||
|
kind: ConfigMap
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: my-config-map
|
||||||
|
namespace: default
|
||||||
|
data:
|
||||||
|
key1: val1
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from ansible.errors import AnsibleLookupError
|
||||||
|
from ansible.module_utils.common.process import get_bin_path
|
||||||
|
from ansible.plugins.lookup import LookupBase
|
||||||
|
|
||||||
|
|
||||||
|
def get_binary_from_path(name, opt_dirs=None):
|
||||||
|
opt_arg = {}
|
||||||
|
try:
|
||||||
|
if opt_dirs is not None:
|
||||||
|
if not isinstance(opt_dirs, list):
|
||||||
|
opt_dirs = [opt_dirs]
|
||||||
|
opt_arg["opt_dirs"] = opt_dirs
|
||||||
|
bin_path = get_bin_path(name, **opt_arg)
|
||||||
|
return bin_path
|
||||||
|
except ValueError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def run_command(command, environ=None):
|
||||||
|
cmd = subprocess.Popen(
|
||||||
|
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=environ
|
||||||
|
)
|
||||||
|
stdout, stderr = cmd.communicate()
|
||||||
|
return cmd.returncode, stdout, stderr
|
||||||
|
|
||||||
|
|
||||||
|
class LookupModule(LookupBase):
|
||||||
|
def run(
|
||||||
|
self,
|
||||||
|
terms,
|
||||||
|
variables=None,
|
||||||
|
dir=".",
|
||||||
|
binary_path=None,
|
||||||
|
opt_dirs=None,
|
||||||
|
enable_helm=False,
|
||||||
|
environment=None,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
|
executable_path = binary_path
|
||||||
|
if executable_path is None:
|
||||||
|
executable_path = get_binary_from_path(name="kustomize", opt_dirs=opt_dirs)
|
||||||
|
if executable_path is None:
|
||||||
|
executable_path = get_binary_from_path(
|
||||||
|
name="kubectl", opt_dirs=opt_dirs
|
||||||
|
)
|
||||||
|
|
||||||
|
# validate that at least one tool was found
|
||||||
|
if executable_path is None:
|
||||||
|
raise AnsibleLookupError(
|
||||||
|
"Failed to find required executable 'kubectl' and 'kustomize' in paths"
|
||||||
|
)
|
||||||
|
|
||||||
|
# check input directory
|
||||||
|
kustomization_dir = dir
|
||||||
|
|
||||||
|
command = [executable_path]
|
||||||
|
if executable_path.endswith("kustomize"):
|
||||||
|
command += ["build", kustomization_dir]
|
||||||
|
elif executable_path.endswith("kubectl"):
|
||||||
|
command += ["kustomize", kustomization_dir]
|
||||||
|
else:
|
||||||
|
raise AnsibleLookupError(
|
||||||
|
"unexpected tool provided as parameter {0}, expected one of kustomize, kubectl.".format(
|
||||||
|
executable_path
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if enable_helm:
|
||||||
|
command += ["--enable-helm"]
|
||||||
|
|
||||||
|
environ = None
|
||||||
|
if environment:
|
||||||
|
environ = os.environ.copy()
|
||||||
|
if isinstance(environment, str):
|
||||||
|
if not all(env.count("=") == 1 for env in environment.split(" ")):
|
||||||
|
raise AnsibleLookupError(
|
||||||
|
"environment should be dict or string in the format key=value, multiple pairs separated by space"
|
||||||
|
)
|
||||||
|
for env in environment.split(" "):
|
||||||
|
key, value = env.split("=")
|
||||||
|
environ[key] = value
|
||||||
|
if isinstance(environment, dict):
|
||||||
|
environ.update(environment)
|
||||||
|
|
||||||
|
(ret, out, err) = run_command(command, environ=environ)
|
||||||
|
if ret != 0:
|
||||||
|
if err:
|
||||||
|
raise AnsibleLookupError(
|
||||||
|
"kustomize command failed. exit code: {0}, error: {1}".format(
|
||||||
|
ret, err.decode("utf-8")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise AnsibleLookupError(
|
||||||
|
"kustomize command failed with unknown error. exit code: {0}".format(
|
||||||
|
ret
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return [out.decode("utf-8")]
|
||||||
344
plugins/module_utils/_version.py
Normal file
344
plugins/module_utils/_version.py
Normal file
@@ -0,0 +1,344 @@
|
|||||||
|
# Vendored copy of distutils/version.py from CPython 3.9.5
|
||||||
|
#
|
||||||
|
# Implements multiple version numbering conventions for the
|
||||||
|
# Python Module Distribution Utilities.
|
||||||
|
#
|
||||||
|
# PSF License (see PSF-license.txt or https://opensource.org/licenses/Python-2.0)
|
||||||
|
#
|
||||||
|
|
||||||
|
"""Provides classes to represent module version numbers (one class for
|
||||||
|
each style of version numbering). There are currently two such classes
|
||||||
|
implemented: StrictVersion and LooseVersion.
|
||||||
|
|
||||||
|
Every version number class implements the following interface:
|
||||||
|
* the 'parse' method takes a string and parses it to some internal
|
||||||
|
representation; if the string is an invalid version number,
|
||||||
|
'parse' raises a ValueError exception
|
||||||
|
* the class constructor takes an optional string argument which,
|
||||||
|
if supplied, is passed to 'parse'
|
||||||
|
* __str__ reconstructs the string that was passed to 'parse' (or
|
||||||
|
an equivalent string -- ie. one that will generate an equivalent
|
||||||
|
version number instance)
|
||||||
|
* __repr__ generates Python code to recreate the version number instance
|
||||||
|
* _cmp compares the current instance with either another instance
|
||||||
|
of the same class or a string (which will be parsed to an instance
|
||||||
|
of the same class, thus must follow the same rules)
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
try:
|
||||||
|
RE_FLAGS = re.VERBOSE | re.ASCII
|
||||||
|
except AttributeError:
|
||||||
|
RE_FLAGS = re.VERBOSE
|
||||||
|
|
||||||
|
|
||||||
|
class Version:
|
||||||
|
"""Abstract base class for version numbering classes. Just provides
|
||||||
|
constructor (__init__) and reproducer (__repr__), because those
|
||||||
|
seem to be the same for all version numbering classes; and route
|
||||||
|
rich comparisons to _cmp.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, vstring=None):
|
||||||
|
if vstring:
|
||||||
|
self.parse(vstring)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "%s ('%s')" % (self.__class__.__name__, str(self))
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
c = self._cmp(other)
|
||||||
|
if c is NotImplemented:
|
||||||
|
return c
|
||||||
|
return c == 0
|
||||||
|
|
||||||
|
def __lt__(self, other):
|
||||||
|
c = self._cmp(other)
|
||||||
|
if c is NotImplemented:
|
||||||
|
return c
|
||||||
|
return c < 0
|
||||||
|
|
||||||
|
def __le__(self, other):
|
||||||
|
c = self._cmp(other)
|
||||||
|
if c is NotImplemented:
|
||||||
|
return c
|
||||||
|
return c <= 0
|
||||||
|
|
||||||
|
def __gt__(self, other):
|
||||||
|
c = self._cmp(other)
|
||||||
|
if c is NotImplemented:
|
||||||
|
return c
|
||||||
|
return c > 0
|
||||||
|
|
||||||
|
def __ge__(self, other):
|
||||||
|
c = self._cmp(other)
|
||||||
|
if c is NotImplemented:
|
||||||
|
return c
|
||||||
|
return c >= 0
|
||||||
|
|
||||||
|
|
||||||
|
# Interface for version-number classes -- must be implemented
|
||||||
|
# by the following classes (the concrete ones -- Version should
|
||||||
|
# be treated as an abstract class).
|
||||||
|
# __init__ (string) - create and take same action as 'parse'
|
||||||
|
# (string parameter is optional)
|
||||||
|
# parse (string) - convert a string representation to whatever
|
||||||
|
# internal representation is appropriate for
|
||||||
|
# this style of version numbering
|
||||||
|
# __str__ (self) - convert back to a string; should be very similar
|
||||||
|
# (if not identical to) the string supplied to parse
|
||||||
|
# __repr__ (self) - generate Python code to recreate
|
||||||
|
# the instance
|
||||||
|
# _cmp (self, other) - compare two version numbers ('other' may
|
||||||
|
# be an unparsed version string, or another
|
||||||
|
# instance of your version class)
|
||||||
|
|
||||||
|
|
||||||
|
class StrictVersion(Version):
|
||||||
|
"""Version numbering for anal retentives and software idealists.
|
||||||
|
Implements the standard interface for version number classes as
|
||||||
|
described above. A version number consists of two or three
|
||||||
|
dot-separated numeric components, with an optional "pre-release" tag
|
||||||
|
on the end. The pre-release tag consists of the letter 'a' or 'b'
|
||||||
|
followed by a number. If the numeric components of two version
|
||||||
|
numbers are equal, then one with a pre-release tag will always
|
||||||
|
be deemed earlier (lesser) than one without.
|
||||||
|
|
||||||
|
The following are valid version numbers (shown in the order that
|
||||||
|
would be obtained by sorting according to the supplied cmp function):
|
||||||
|
|
||||||
|
0.4 0.4.0 (these two are equivalent)
|
||||||
|
0.4.1
|
||||||
|
0.5a1
|
||||||
|
0.5b3
|
||||||
|
0.5
|
||||||
|
0.9.6
|
||||||
|
1.0
|
||||||
|
1.0.4a3
|
||||||
|
1.0.4b1
|
||||||
|
1.0.4
|
||||||
|
|
||||||
|
The following are examples of invalid version numbers:
|
||||||
|
|
||||||
|
1
|
||||||
|
2.7.2.2
|
||||||
|
1.3.a4
|
||||||
|
1.3pl1
|
||||||
|
1.3c4
|
||||||
|
|
||||||
|
The rationale for this version numbering system will be explained
|
||||||
|
in the distutils documentation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
version_re = re.compile(r"^(\d+) \. (\d+) (\. (\d+))? ([ab](\d+))?$", RE_FLAGS)
|
||||||
|
|
||||||
|
def parse(self, vstring):
|
||||||
|
match = self.version_re.match(vstring)
|
||||||
|
if not match:
|
||||||
|
raise ValueError("invalid version number '%s'" % vstring)
|
||||||
|
|
||||||
|
(major, minor, patch, prerelease, prerelease_num) = match.group(1, 2, 4, 5, 6)
|
||||||
|
|
||||||
|
if patch:
|
||||||
|
self.version = tuple(map(int, [major, minor, patch]))
|
||||||
|
else:
|
||||||
|
self.version = tuple(map(int, [major, minor])) + (0,)
|
||||||
|
|
||||||
|
if prerelease:
|
||||||
|
self.prerelease = (prerelease[0], int(prerelease_num))
|
||||||
|
else:
|
||||||
|
self.prerelease = None
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.version[2] == 0:
|
||||||
|
vstring = ".".join(map(str, self.version[0:2]))
|
||||||
|
else:
|
||||||
|
vstring = ".".join(map(str, self.version))
|
||||||
|
|
||||||
|
if self.prerelease:
|
||||||
|
vstring = vstring + self.prerelease[0] + str(self.prerelease[1])
|
||||||
|
|
||||||
|
return vstring
|
||||||
|
|
||||||
|
def _cmp(self, other):
|
||||||
|
if isinstance(other, str):
|
||||||
|
other = StrictVersion(other)
|
||||||
|
elif not isinstance(other, StrictVersion):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
if self.version != other.version:
|
||||||
|
# numeric versions don't match
|
||||||
|
# prerelease stuff doesn't matter
|
||||||
|
if self.version < other.version:
|
||||||
|
return -1
|
||||||
|
else:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
# have to compare prerelease
|
||||||
|
# case 1: neither has prerelease; they're equal
|
||||||
|
# case 2: self has prerelease, other doesn't; other is greater
|
||||||
|
# case 3: self doesn't have prerelease, other does: self is greater
|
||||||
|
# case 4: both have prerelease: must compare them!
|
||||||
|
|
||||||
|
if not self.prerelease and not other.prerelease:
|
||||||
|
return 0
|
||||||
|
elif self.prerelease and not other.prerelease:
|
||||||
|
return -1
|
||||||
|
elif not self.prerelease and other.prerelease:
|
||||||
|
return 1
|
||||||
|
elif self.prerelease and other.prerelease:
|
||||||
|
if self.prerelease == other.prerelease:
|
||||||
|
return 0
|
||||||
|
elif self.prerelease < other.prerelease:
|
||||||
|
return -1
|
||||||
|
else:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
raise AssertionError("never get here")
|
||||||
|
|
||||||
|
|
||||||
|
# end class StrictVersion
|
||||||
|
|
||||||
|
# The rules according to Greg Stein:
|
||||||
|
# 1) a version number has 1 or more numbers separated by a period or by
|
||||||
|
# sequences of letters. If only periods, then these are compared
|
||||||
|
# left-to-right to determine an ordering.
|
||||||
|
# 2) sequences of letters are part of the tuple for comparison and are
|
||||||
|
# compared lexicographically
|
||||||
|
# 3) recognize the numeric components may have leading zeroes
|
||||||
|
#
|
||||||
|
# The LooseVersion class below implements these rules: a version number
|
||||||
|
# string is split up into a tuple of integer and string components, and
|
||||||
|
# comparison is a simple tuple comparison. This means that version
|
||||||
|
# numbers behave in a predictable and obvious way, but a way that might
|
||||||
|
# not necessarily be how people *want* version numbers to behave. There
|
||||||
|
# wouldn't be a problem if people could stick to purely numeric version
|
||||||
|
# numbers: just split on period and compare the numbers as tuples.
|
||||||
|
# However, people insist on putting letters into their version numbers;
|
||||||
|
# the most common purpose seems to be:
|
||||||
|
# - indicating a "pre-release" version
|
||||||
|
# ('alpha', 'beta', 'a', 'b', 'pre', 'p')
|
||||||
|
# - indicating a post-release patch ('p', 'pl', 'patch')
|
||||||
|
# but of course this can't cover all version number schemes, and there's
|
||||||
|
# no way to know what a programmer means without asking him.
|
||||||
|
#
|
||||||
|
# The problem is what to do with letters (and other non-numeric
|
||||||
|
# characters) in a version number. The current implementation does the
|
||||||
|
# obvious and predictable thing: keep them as strings and compare
|
||||||
|
# lexically within a tuple comparison. This has the desired effect if
|
||||||
|
# an appended letter sequence implies something "post-release":
|
||||||
|
# eg. "0.99" < "0.99pl14" < "1.0", and "5.001" < "5.001m" < "5.002".
|
||||||
|
#
|
||||||
|
# However, if letters in a version number imply a pre-release version,
|
||||||
|
# the "obvious" thing isn't correct. Eg. you would expect that
|
||||||
|
# "1.5.1" < "1.5.2a2" < "1.5.2", but under the tuple/lexical comparison
|
||||||
|
# implemented here, this just isn't so.
|
||||||
|
#
|
||||||
|
# Two possible solutions come to mind. The first is to tie the
|
||||||
|
# comparison algorithm to a particular set of semantic rules, as has
|
||||||
|
# been done in the StrictVersion class above. This works great as long
|
||||||
|
# as everyone can go along with bondage and discipline. Hopefully a
|
||||||
|
# (large) subset of Python module programmers will agree that the
|
||||||
|
# particular flavour of bondage and discipline provided by StrictVersion
|
||||||
|
# provides enough benefit to be worth using, and will submit their
|
||||||
|
# version numbering scheme to its domination. The free-thinking
|
||||||
|
# anarchists in the lot will never give in, though, and something needs
|
||||||
|
# to be done to accommodate them.
|
||||||
|
#
|
||||||
|
# Perhaps a "moderately strict" version class could be implemented that
|
||||||
|
# lets almost anything slide (syntactically), and makes some heuristic
|
||||||
|
# assumptions about non-digits in version number strings. This could
|
||||||
|
# sink into special-case-hell, though; if I was as talented and
|
||||||
|
# idiosyncratic as Larry Wall, I'd go ahead and implement a class that
|
||||||
|
# somehow knows that "1.2.1" < "1.2.2a2" < "1.2.2" < "1.2.2pl3", and is
|
||||||
|
# just as happy dealing with things like "2g6" and "1.13++". I don't
|
||||||
|
# think I'm smart enough to do it right though.
|
||||||
|
#
|
||||||
|
# In any case, I've coded the test suite for this module (see
|
||||||
|
# ../test/test_version.py) specifically to fail on things like comparing
|
||||||
|
# "1.2a2" and "1.2". That's not because the *code* is doing anything
|
||||||
|
# wrong, it's because the simple, obvious design doesn't match my
|
||||||
|
# complicated, hairy expectations for real-world version numbers. It
|
||||||
|
# would be a snap to fix the test suite to say, "Yep, LooseVersion does
|
||||||
|
# the Right Thing" (ie. the code matches the conception). But I'd rather
|
||||||
|
# have a conception that matches common notions about version numbers.
|
||||||
|
|
||||||
|
|
||||||
|
class LooseVersion(Version):
|
||||||
|
"""Version numbering for anarchists and software realists.
|
||||||
|
Implements the standard interface for version number classes as
|
||||||
|
described above. A version number consists of a series of numbers,
|
||||||
|
separated by either periods or strings of letters. When comparing
|
||||||
|
version numbers, the numeric components will be compared
|
||||||
|
numerically, and the alphabetic components lexically. The following
|
||||||
|
are all valid version numbers, in no particular order:
|
||||||
|
|
||||||
|
1.5.1
|
||||||
|
1.5.2b2
|
||||||
|
161
|
||||||
|
3.10a
|
||||||
|
8.02
|
||||||
|
3.4j
|
||||||
|
1996.07.12
|
||||||
|
3.2.pl0
|
||||||
|
3.1.1.6
|
||||||
|
2g6
|
||||||
|
11g
|
||||||
|
0.960923
|
||||||
|
2.2beta29
|
||||||
|
1.13++
|
||||||
|
5.5.kw
|
||||||
|
2.0b1pl0
|
||||||
|
|
||||||
|
In fact, there is no such thing as an invalid version number under
|
||||||
|
this scheme; the rules for comparison are simple and predictable,
|
||||||
|
but may not always give the results you want (for some definition
|
||||||
|
of "want").
|
||||||
|
"""
|
||||||
|
|
||||||
|
component_re = re.compile(r"(\d+ | [a-z]+ | \.)", re.VERBOSE)
|
||||||
|
|
||||||
|
def __init__(self, vstring=None):
|
||||||
|
if vstring:
|
||||||
|
self.parse(vstring)
|
||||||
|
|
||||||
|
def parse(self, vstring):
|
||||||
|
# I've given up on thinking I can reconstruct the version string
|
||||||
|
# from the parsed tuple -- so I just store the string here for
|
||||||
|
# use by __str__
|
||||||
|
self.vstring = vstring
|
||||||
|
components = [x for x in self.component_re.split(vstring) if x and x != "."]
|
||||||
|
for i, obj in enumerate(components):
|
||||||
|
try:
|
||||||
|
components[i] = int(obj)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.version = components
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.vstring
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "LooseVersion ('%s')" % str(self)
|
||||||
|
|
||||||
|
def _cmp(self, other):
|
||||||
|
if isinstance(other, str):
|
||||||
|
other = LooseVersion(other)
|
||||||
|
elif not isinstance(other, LooseVersion):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
if self.version == other.version:
|
||||||
|
return 0
|
||||||
|
if self.version < other.version:
|
||||||
|
return -1
|
||||||
|
if self.version > other.version:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
# end class LooseVersion
|
||||||
@@ -1,6 +1,25 @@
|
|||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule # noqa: F401
|
import os
|
||||||
|
|
||||||
|
from ansible.module_utils.common.validation import check_type_bool
|
||||||
|
|
||||||
|
try:
|
||||||
|
enable_turbo_mode = check_type_bool(os.environ.get("ENABLE_TURBO_MODE"))
|
||||||
|
except TypeError:
|
||||||
|
enable_turbo_mode = False
|
||||||
|
|
||||||
|
if enable_turbo_mode:
|
||||||
|
try:
|
||||||
|
from ansible_collections.cloud.common.plugins.module_utils.turbo.module import ( # noqa: F401
|
||||||
|
AnsibleTurboModule as AnsibleModule,
|
||||||
|
)
|
||||||
|
|
||||||
|
AnsibleModule.collection_name = "kubernetes.core"
|
||||||
|
except ImportError:
|
||||||
|
from ansible.module_utils.basic import AnsibleModule # noqa: F401
|
||||||
|
else:
|
||||||
|
from ansible.module_utils.basic import AnsibleModule # noqa: F401
|
||||||
|
|||||||
@@ -14,13 +14,22 @@
|
|||||||
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
from collections import OrderedDict
|
|
||||||
import json
|
import json
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
from ansible.module_utils.common.dict_transformations import dict_merge
|
from ansible.module_utils.common.dict_transformations import dict_merge
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.exceptions import ApplyException
|
from ansible_collections.kubernetes.core.plugins.module_utils.exceptions import (
|
||||||
|
ApplyException,
|
||||||
|
)
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import (
|
||||||
|
gather_versions,
|
||||||
|
)
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
|
||||||
|
LooseVersion,
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from kubernetes.dynamic.exceptions import NotFoundError
|
from kubernetes.dynamic.exceptions import NotFoundError
|
||||||
@@ -28,50 +37,52 @@ except ImportError:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
LAST_APPLIED_CONFIG_ANNOTATION = 'kubectl.kubernetes.io/last-applied-configuration'
|
LAST_APPLIED_CONFIG_ANNOTATION = "kubectl.kubernetes.io/last-applied-configuration"
|
||||||
|
|
||||||
POD_SPEC_SUFFIXES = {
|
POD_SPEC_SUFFIXES = {
|
||||||
'containers': 'name',
|
"containers": "name",
|
||||||
'initContainers': 'name',
|
"initContainers": "name",
|
||||||
'ephemeralContainers': 'name',
|
"ephemeralContainers": "name",
|
||||||
'volumes': 'name',
|
"volumes": "name",
|
||||||
'imagePullSecrets': 'name',
|
"imagePullSecrets": "name",
|
||||||
'containers.volumeMounts': 'mountPath',
|
"containers.volumeMounts": "mountPath",
|
||||||
'containers.volumeDevices': 'devicePath',
|
"containers.volumeDevices": "devicePath",
|
||||||
'containers.env': 'name',
|
"containers.env": "name",
|
||||||
'containers.ports': 'containerPort',
|
"containers.ports": "containerPort",
|
||||||
'initContainers.volumeMounts': 'mountPath',
|
"initContainers.volumeMounts": "mountPath",
|
||||||
'initContainers.volumeDevices': 'devicePath',
|
"initContainers.volumeDevices": "devicePath",
|
||||||
'initContainers.env': 'name',
|
"initContainers.env": "name",
|
||||||
'initContainers.ports': 'containerPort',
|
"initContainers.ports": "containerPort",
|
||||||
'ephemeralContainers.volumeMounts': 'mountPath',
|
"ephemeralContainers.volumeMounts": "mountPath",
|
||||||
'ephemeralContainers.volumeDevices': 'devicePath',
|
"ephemeralContainers.volumeDevices": "devicePath",
|
||||||
'ephemeralContainers.env': 'name',
|
"ephemeralContainers.env": "name",
|
||||||
'ephemeralContainers.ports': 'containerPort',
|
"ephemeralContainers.ports": "containerPort",
|
||||||
}
|
}
|
||||||
|
|
||||||
POD_SPEC_PREFIXES = [
|
POD_SPEC_PREFIXES = [
|
||||||
'Pod.spec',
|
"Pod.spec",
|
||||||
'Deployment.spec.template.spec',
|
"Deployment.spec.template.spec",
|
||||||
'DaemonSet.spec.template.spec',
|
"DaemonSet.spec.template.spec",
|
||||||
'StatefulSet.spec.template.spec',
|
"StatefulSet.spec.template.spec",
|
||||||
'Job.spec.template.spec',
|
"Job.spec.template.spec",
|
||||||
'Cronjob.spec.jobTemplate.spec.template.spec',
|
"Cronjob.spec.jobTemplate.spec.template.spec",
|
||||||
]
|
]
|
||||||
|
|
||||||
# patch merge keys taken from generated.proto files under
|
# patch merge keys taken from generated.proto files under
|
||||||
# staging/src/k8s.io/api in kubernetes/kubernetes
|
# staging/src/k8s.io/api in kubernetes/kubernetes
|
||||||
STRATEGIC_MERGE_PATCH_KEYS = {
|
STRATEGIC_MERGE_PATCH_KEYS = {
|
||||||
'Service.spec.ports': 'port',
|
"Service.spec.ports": "port",
|
||||||
'ServiceAccount.secrets': 'name',
|
"ServiceAccount.secrets": "name",
|
||||||
'ValidatingWebhookConfiguration.webhooks': 'name',
|
"ValidatingWebhookConfiguration.webhooks": "name",
|
||||||
'MutatingWebhookConfiguration.webhooks': 'name',
|
"MutatingWebhookConfiguration.webhooks": "name",
|
||||||
}
|
}
|
||||||
|
|
||||||
STRATEGIC_MERGE_PATCH_KEYS.update(
|
STRATEGIC_MERGE_PATCH_KEYS.update(
|
||||||
{"%s.%s" % (prefix, key): value
|
{
|
||||||
for prefix in POD_SPEC_PREFIXES
|
"%s.%s" % (prefix, key): value
|
||||||
for key, value in POD_SPEC_SUFFIXES.items()}
|
for prefix in POD_SPEC_PREFIXES
|
||||||
|
for key, value in POD_SPEC_SUFFIXES.items()
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -79,21 +90,28 @@ def annotate(desired):
|
|||||||
return dict(
|
return dict(
|
||||||
metadata=dict(
|
metadata=dict(
|
||||||
annotations={
|
annotations={
|
||||||
LAST_APPLIED_CONFIG_ANNOTATION: json.dumps(desired, separators=(',', ':'), indent=None, sort_keys=True)
|
LAST_APPLIED_CONFIG_ANNOTATION: json.dumps(
|
||||||
|
desired, separators=(",", ":"), indent=None, sort_keys=True
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def apply_patch(actual, desired):
|
def apply_patch(actual, desired):
|
||||||
last_applied = actual['metadata'].get('annotations', {}).get(LAST_APPLIED_CONFIG_ANNOTATION)
|
last_applied = (
|
||||||
|
actual["metadata"].get("annotations", {}).get(LAST_APPLIED_CONFIG_ANNOTATION)
|
||||||
|
)
|
||||||
|
|
||||||
if last_applied:
|
if last_applied:
|
||||||
# ensure that last_applied doesn't come back as a dict of unicode key/value pairs
|
# ensure that last_applied doesn't come back as a dict of unicode key/value pairs
|
||||||
# json.loads can be used if we stop supporting python 2
|
# json.loads can be used if we stop supporting python 2
|
||||||
last_applied = json.loads(last_applied)
|
last_applied = json.loads(last_applied)
|
||||||
patch = merge(dict_merge(last_applied, annotate(last_applied)),
|
patch = merge(
|
||||||
dict_merge(desired, annotate(desired)), actual)
|
dict_merge(last_applied, annotate(last_applied)),
|
||||||
|
dict_merge(desired, annotate(desired)),
|
||||||
|
actual,
|
||||||
|
)
|
||||||
if patch:
|
if patch:
|
||||||
return actual, patch
|
return actual, patch
|
||||||
else:
|
else:
|
||||||
@@ -102,24 +120,54 @@ def apply_patch(actual, desired):
|
|||||||
return actual, dict_merge(desired, annotate(desired))
|
return actual, dict_merge(desired, annotate(desired))
|
||||||
|
|
||||||
|
|
||||||
def apply_object(resource, definition):
|
def apply_object(resource, definition, server_side=False):
|
||||||
try:
|
try:
|
||||||
actual = resource.get(name=definition['metadata']['name'], namespace=definition['metadata'].get('namespace'))
|
actual = resource.get(
|
||||||
|
name=definition["metadata"]["name"],
|
||||||
|
namespace=definition["metadata"].get("namespace"),
|
||||||
|
)
|
||||||
|
if server_side:
|
||||||
|
return actual, None
|
||||||
except NotFoundError:
|
except NotFoundError:
|
||||||
return None, dict_merge(definition, annotate(definition))
|
return None, dict_merge(definition, annotate(definition))
|
||||||
return apply_patch(actual.to_dict(), definition)
|
return apply_patch(actual.to_dict(), definition)
|
||||||
|
|
||||||
|
|
||||||
def k8s_apply(resource, definition):
|
def k8s_apply(resource, definition, **kwargs):
|
||||||
existing, desired = apply_object(resource, definition)
|
existing, desired = apply_object(resource, definition)
|
||||||
|
server_side = kwargs.get("server_side", False)
|
||||||
|
if server_side:
|
||||||
|
versions = gather_versions()
|
||||||
|
body = definition
|
||||||
|
if LooseVersion(versions["kubernetes"]) < LooseVersion("25.0.0"):
|
||||||
|
body = json.dumps(definition).encode()
|
||||||
|
# server_side_apply is forces content_type to 'application/apply-patch+yaml'
|
||||||
|
return resource.server_side_apply(
|
||||||
|
body=body,
|
||||||
|
name=definition["metadata"]["name"],
|
||||||
|
namespace=definition["metadata"].get("namespace"),
|
||||||
|
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:
|
if not existing:
|
||||||
return resource.create(body=desired, namespace=definition['metadata'].get('namespace'))
|
return resource.create(
|
||||||
|
body=desired, namespace=definition["metadata"].get("namespace"), **kwargs
|
||||||
|
)
|
||||||
if existing == desired:
|
if existing == desired:
|
||||||
return resource.get(name=definition['metadata']['name'], namespace=definition['metadata'].get('namespace'))
|
return resource.get(
|
||||||
return resource.patch(body=desired,
|
name=definition["metadata"]["name"],
|
||||||
name=definition['metadata']['name'],
|
namespace=definition["metadata"].get("namespace"),
|
||||||
namespace=definition['metadata'].get('namespace'),
|
**kwargs
|
||||||
content_type='application/merge-patch+json')
|
)
|
||||||
|
return resource.patch(
|
||||||
|
body=desired,
|
||||||
|
name=definition["metadata"]["name"],
|
||||||
|
namespace=definition["metadata"].get("namespace"),
|
||||||
|
content_type="application/merge-patch+json",
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# The patch is the difference from actual to desired without deletions, plus deletions
|
# The patch is the difference from actual to desired without deletions, plus deletions
|
||||||
@@ -128,7 +176,7 @@ def k8s_apply(resource, definition):
|
|||||||
# deletions, and then apply delta to deletions as a patch, which should be strictly additive.
|
# deletions, and then apply delta to deletions as a patch, which should be strictly additive.
|
||||||
def merge(last_applied, desired, actual, position=None):
|
def merge(last_applied, desired, actual, position=None):
|
||||||
deletions = get_deletions(last_applied, desired)
|
deletions = get_deletions(last_applied, desired)
|
||||||
delta = get_delta(last_applied, actual, desired, position or desired['kind'])
|
delta = get_delta(last_applied, actual, desired, position or desired["kind"])
|
||||||
return dict_merge(deletions, delta)
|
return dict_merge(deletions, delta)
|
||||||
|
|
||||||
|
|
||||||
@@ -138,7 +186,9 @@ def list_to_dict(lst, key, position):
|
|||||||
try:
|
try:
|
||||||
result[item[key]] = item
|
result[item[key]] = item
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise ApplyException("Expected key '%s' not found in position %s" % (key, position))
|
raise ApplyException(
|
||||||
|
"Expected key '%s' not found in position %s" % (key, position)
|
||||||
|
)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
@@ -157,7 +207,12 @@ def list_merge(last_applied, actual, desired, position):
|
|||||||
if key not in actual_dict or key not in last_applied_dict:
|
if key not in actual_dict or key not in last_applied_dict:
|
||||||
result.append(desired_dict[key])
|
result.append(desired_dict[key])
|
||||||
else:
|
else:
|
||||||
patch = merge(last_applied_dict[key], desired_dict[key], actual_dict[key], position)
|
patch = merge(
|
||||||
|
last_applied_dict[key],
|
||||||
|
desired_dict[key],
|
||||||
|
actual_dict[key],
|
||||||
|
position,
|
||||||
|
)
|
||||||
result.append(dict_merge(actual_dict[key], patch))
|
result.append(dict_merge(actual_dict[key], patch))
|
||||||
for key in actual_dict:
|
for key in actual_dict:
|
||||||
if key not in desired_dict and key not in last_applied_dict:
|
if key not in desired_dict and key not in last_applied_dict:
|
||||||
@@ -197,11 +252,11 @@ def recursive_list_diff(list1, list2, position=None):
|
|||||||
|
|
||||||
def recursive_diff(dict1, dict2, position=None):
|
def recursive_diff(dict1, dict2, position=None):
|
||||||
if not position:
|
if not position:
|
||||||
if 'kind' in dict1 and dict1.get('kind') == dict2.get('kind'):
|
if "kind" in dict1 and dict1.get("kind") == dict2.get("kind"):
|
||||||
position = dict1['kind']
|
position = dict1["kind"]
|
||||||
left = dict((k, v) for (k, v) in dict1.items() if k not in dict2)
|
left = dict((k, v) for (k, v) in dict1.items() if k not in dict2)
|
||||||
right = dict((k, v) for (k, v) in dict2.items() if k not in dict1)
|
right = dict((k, v) for (k, v) in dict2.items() if k not in dict1)
|
||||||
for k in (set(dict1.keys()) & set(dict2.keys())):
|
for k in set(dict1.keys()) & set(dict2.keys()):
|
||||||
if position:
|
if position:
|
||||||
this_position = "%s.%s" % (position, k)
|
this_position = "%s.%s" % (position, k)
|
||||||
if isinstance(dict1[k], dict) and isinstance(dict2[k], dict):
|
if isinstance(dict1[k], dict) and isinstance(dict2[k], dict):
|
||||||
@@ -246,11 +301,15 @@ def get_delta(last_applied, actual, desired, position=None):
|
|||||||
if actual_value is None:
|
if actual_value is None:
|
||||||
patch[k] = desired_value
|
patch[k] = desired_value
|
||||||
elif isinstance(desired_value, dict):
|
elif isinstance(desired_value, dict):
|
||||||
p = get_delta(last_applied.get(k, {}), actual_value, desired_value, this_position)
|
p = get_delta(
|
||||||
|
last_applied.get(k, {}), actual_value, desired_value, this_position
|
||||||
|
)
|
||||||
if p:
|
if p:
|
||||||
patch[k] = p
|
patch[k] = p
|
||||||
elif isinstance(desired_value, list):
|
elif isinstance(desired_value, list):
|
||||||
p = list_merge(last_applied.get(k, []), actual_value, desired_value, this_position)
|
p = list_merge(
|
||||||
|
last_applied.get(k, []), actual_value, desired_value, this_position
|
||||||
|
)
|
||||||
if p:
|
if p:
|
||||||
patch[k] = [item for item in p if item is not None]
|
patch[k] = [item for item in p if item is not None]
|
||||||
elif actual_value != desired_value:
|
elif actual_value != desired_value:
|
||||||
|
|||||||
@@ -1,144 +1,96 @@
|
|||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
from ansible.module_utils.six import string_types
|
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
def list_dict_str(value):
|
def list_dict_str(value):
|
||||||
if isinstance(value, (list, dict, string_types)):
|
if isinstance(value, (list, dict, str)):
|
||||||
return value
|
return value
|
||||||
raise TypeError
|
raise TypeError
|
||||||
|
|
||||||
|
|
||||||
AUTH_PROXY_HEADERS_SPEC = dict(
|
AUTH_PROXY_HEADERS_SPEC = dict(
|
||||||
proxy_basic_auth=dict(type='str', no_log=True),
|
proxy_basic_auth=dict(type="str", no_log=True),
|
||||||
basic_auth=dict(type='str', no_log=True),
|
basic_auth=dict(type="str", no_log=True),
|
||||||
user_agent=dict(type='str')
|
user_agent=dict(type="str"),
|
||||||
)
|
)
|
||||||
|
|
||||||
AUTH_ARG_SPEC = {
|
AUTH_ARG_SPEC = {
|
||||||
'kubeconfig': {
|
"kubeconfig": {"type": "raw", "no_log": True},
|
||||||
'type': 'path',
|
"context": {},
|
||||||
},
|
"host": {},
|
||||||
'context': {},
|
"api_key": {"no_log": True},
|
||||||
'host': {},
|
"username": {},
|
||||||
'api_key': {
|
"password": {"no_log": True},
|
||||||
'no_log': True,
|
"validate_certs": {"type": "bool", "aliases": ["verify_ssl"]},
|
||||||
},
|
"ca_cert": {"type": "path", "aliases": ["ssl_ca_cert"]},
|
||||||
'username': {},
|
"client_cert": {"type": "path", "aliases": ["cert_file"]},
|
||||||
'password': {
|
"client_key": {"type": "path", "aliases": ["key_file"]},
|
||||||
'no_log': True,
|
"proxy": {"type": "str"},
|
||||||
},
|
"no_proxy": {"type": "str"},
|
||||||
'validate_certs': {
|
"proxy_headers": {"type": "dict", "options": AUTH_PROXY_HEADERS_SPEC},
|
||||||
'type': 'bool',
|
"persist_config": {"type": "bool"},
|
||||||
'aliases': ['verify_ssl'],
|
"impersonate_user": {},
|
||||||
},
|
"impersonate_groups": {"type": "list", "elements": "str"},
|
||||||
'ca_cert': {
|
|
||||||
'type': 'path',
|
|
||||||
'aliases': ['ssl_ca_cert'],
|
|
||||||
},
|
|
||||||
'client_cert': {
|
|
||||||
'type': 'path',
|
|
||||||
'aliases': ['cert_file'],
|
|
||||||
},
|
|
||||||
'client_key': {
|
|
||||||
'type': 'path',
|
|
||||||
'aliases': ['key_file'],
|
|
||||||
},
|
|
||||||
'proxy': {
|
|
||||||
'type': 'str',
|
|
||||||
},
|
|
||||||
'proxy_headers': {
|
|
||||||
'type': 'dict',
|
|
||||||
'options': AUTH_PROXY_HEADERS_SPEC
|
|
||||||
},
|
|
||||||
'persist_config': {
|
|
||||||
'type': 'bool',
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WAIT_ARG_SPEC = dict(
|
WAIT_ARG_SPEC = dict(
|
||||||
wait=dict(type='bool', default=False),
|
wait=dict(type="bool", default=False),
|
||||||
wait_sleep=dict(type='int', default=5),
|
wait_sleep=dict(type="int", default=5),
|
||||||
wait_timeout=dict(type='int', default=120),
|
wait_timeout=dict(type="int", default=120),
|
||||||
wait_condition=dict(
|
wait_condition=dict(
|
||||||
type='dict',
|
type="dict",
|
||||||
default=None,
|
default=None,
|
||||||
options=dict(
|
options=dict(
|
||||||
type=dict(),
|
type=dict(),
|
||||||
status=dict(default=True, choices=[True, False, "Unknown"]),
|
status=dict(default=True, choices=[True, False, "Unknown"]),
|
||||||
reason=dict()
|
reason=dict(),
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Map kubernetes-client parameters to ansible parameters
|
# Map kubernetes-client parameters to ansible parameters
|
||||||
AUTH_ARG_MAP = {
|
AUTH_ARG_MAP = {
|
||||||
'kubeconfig': 'kubeconfig',
|
"kubeconfig": "kubeconfig",
|
||||||
'context': 'context',
|
"context": "context",
|
||||||
'host': 'host',
|
"host": "host",
|
||||||
'api_key': 'api_key',
|
"api_key": "api_key",
|
||||||
'username': 'username',
|
"username": "username",
|
||||||
'password': 'password',
|
"password": "password",
|
||||||
'verify_ssl': 'validate_certs',
|
"verify_ssl": "validate_certs",
|
||||||
'ssl_ca_cert': 'ca_cert',
|
"ssl_ca_cert": "ca_cert",
|
||||||
'cert_file': 'client_cert',
|
"cert_file": "client_cert",
|
||||||
'key_file': 'client_key',
|
"key_file": "client_key",
|
||||||
'proxy': 'proxy',
|
"proxy": "proxy",
|
||||||
'proxy_headers': 'proxy_headers',
|
"no_proxy": "no_proxy",
|
||||||
'persist_config': 'persist_config',
|
"proxy_headers": "proxy_headers",
|
||||||
|
"persist_config": "persist_config",
|
||||||
}
|
}
|
||||||
|
|
||||||
NAME_ARG_SPEC = {
|
NAME_ARG_SPEC = {
|
||||||
'kind': {},
|
"kind": {},
|
||||||
'name': {},
|
"name": {},
|
||||||
'namespace': {},
|
"namespace": {},
|
||||||
'api_version': {
|
"api_version": {"default": "v1", "aliases": ["api", "version"]},
|
||||||
'default': 'v1',
|
|
||||||
'aliases': ['api', 'version'],
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
COMMON_ARG_SPEC = {
|
COMMON_ARG_SPEC = {
|
||||||
'state': {
|
"state": {"default": "present", "choices": ["present", "absent"]},
|
||||||
'default': 'present',
|
"force": {"type": "bool", "default": False},
|
||||||
'choices': ['present', 'absent'],
|
|
||||||
},
|
|
||||||
'force': {
|
|
||||||
'type': 'bool',
|
|
||||||
'default': False,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RESOURCE_ARG_SPEC = {
|
RESOURCE_ARG_SPEC = {
|
||||||
'resource_definition': {
|
"resource_definition": {"type": list_dict_str, "aliases": ["definition", "inline"]},
|
||||||
'type': list_dict_str,
|
"src": {"type": "path"},
|
||||||
'aliases': ['definition', 'inline']
|
|
||||||
},
|
|
||||||
'src': {
|
|
||||||
'type': 'path',
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ARG_ATTRIBUTES_BLACKLIST = ('property_path',)
|
ARG_ATTRIBUTES_BLACKLIST = ("property_path",)
|
||||||
|
|
||||||
DELETE_OPTS_ARG_SPEC = {
|
DELETE_OPTS_ARG_SPEC = {
|
||||||
'propagationPolicy': {
|
"propagationPolicy": {"choices": ["Foreground", "Background", "Orphan"]},
|
||||||
'choices': ['Foreground', 'Background', 'Orphan'],
|
"gracePeriodSeconds": {"type": "int"},
|
||||||
|
"preconditions": {
|
||||||
|
"type": "dict",
|
||||||
|
"options": {"resourceVersion": {"type": "str"}, "uid": {"type": "str"}},
|
||||||
},
|
},
|
||||||
'gracePeriodSeconds': {
|
|
||||||
'type': 'int',
|
|
||||||
},
|
|
||||||
'preconditions': {
|
|
||||||
'type': 'dict',
|
|
||||||
'options': {
|
|
||||||
'resourceVersion': {
|
|
||||||
'type': 'str',
|
|
||||||
},
|
|
||||||
'uid': {
|
|
||||||
'type': 'str',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,26 +13,35 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
|
import hashlib
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
from collections import defaultdict
|
|
||||||
import hashlib
|
|
||||||
import tempfile
|
import tempfile
|
||||||
|
from collections import defaultdict
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
import kubernetes.dynamic
|
import kubernetes.dynamic
|
||||||
import kubernetes.dynamic.discovery
|
import kubernetes.dynamic.discovery
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.client.resource import (
|
||||||
|
ResourceList,
|
||||||
|
)
|
||||||
from kubernetes import __version__
|
from kubernetes import __version__
|
||||||
from kubernetes.dynamic.exceptions import (ResourceNotFoundError, ResourceNotUniqueError,
|
from kubernetes.dynamic.exceptions import (
|
||||||
ServiceUnavailableError)
|
ResourceNotFoundError,
|
||||||
|
ResourceNotUniqueError,
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.client.resource import ResourceList
|
ServiceUnavailableError,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Discoverer(kubernetes.dynamic.discovery.Discoverer):
|
class Discoverer(kubernetes.dynamic.discovery.Discoverer):
|
||||||
def __init__(self, client, cache_file):
|
def __init__(self, client, cache_file):
|
||||||
self.client = client
|
self.client = client
|
||||||
default_cache_file_name = 'k8srcp-{0}.json'.format(hashlib.sha256(self.__get_default_cache_id()).hexdigest())
|
default_cache_file_name = "k8srcp-{0}.json".format(
|
||||||
self.__cache_file = cache_file or os.path.join(tempfile.gettempdir(), default_cache_file_name)
|
hashlib.sha256(self.__get_default_cache_id()).hexdigest()
|
||||||
|
)
|
||||||
|
self.__cache_file = cache_file or os.path.join(
|
||||||
|
tempfile.gettempdir(), default_cache_file_name
|
||||||
|
)
|
||||||
self.__init_cache()
|
self.__init_cache()
|
||||||
|
|
||||||
def __get_default_cache_id(self):
|
def __get_default_cache_id(self):
|
||||||
@@ -41,21 +50,21 @@ class Discoverer(kubernetes.dynamic.discovery.Discoverer):
|
|||||||
cache_id = "{0}-{1}".format(self.client.configuration.host, user)
|
cache_id = "{0}-{1}".format(self.client.configuration.host, user)
|
||||||
else:
|
else:
|
||||||
cache_id = self.client.configuration.host
|
cache_id = self.client.configuration.host
|
||||||
return cache_id.encode('utf-8')
|
return cache_id.encode("utf-8")
|
||||||
|
|
||||||
def __get_user(self):
|
def __get_user(self):
|
||||||
# This is intended to provide a portable method for getting a username.
|
# This is intended to provide a portable method for getting a username.
|
||||||
# It could, and maybe should, be replaced by getpass.getuser() but, due
|
# It could, and maybe should, be replaced by getpass.getuser() but, due
|
||||||
# to a lack of portability testing the original code is being left in
|
# to a lack of portability testing the original code is being left in
|
||||||
# place.
|
# place.
|
||||||
if hasattr(os, 'getlogin'):
|
if hasattr(os, "getlogin"):
|
||||||
try:
|
try:
|
||||||
user = os.getlogin()
|
user = os.getlogin()
|
||||||
if user:
|
if user:
|
||||||
return str(user)
|
return str(user)
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
if hasattr(os, 'getuid'):
|
if hasattr(os, "getuid"):
|
||||||
try:
|
try:
|
||||||
user = os.getuid()
|
user = os.getuid()
|
||||||
if user:
|
if user:
|
||||||
@@ -69,13 +78,13 @@ class Discoverer(kubernetes.dynamic.discovery.Discoverer):
|
|||||||
|
|
||||||
def __init_cache(self, refresh=False):
|
def __init_cache(self, refresh=False):
|
||||||
if refresh or not os.path.exists(self.__cache_file):
|
if refresh or not os.path.exists(self.__cache_file):
|
||||||
self._cache = {'library_version': __version__}
|
self._cache = {"library_version": __version__}
|
||||||
refresh = True
|
refresh = True
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
with open(self.__cache_file, 'r') as f:
|
with open(self.__cache_file, "r") as f:
|
||||||
self._cache = json.load(f, cls=CacheDecoder(self.client))
|
self._cache = json.load(f, cls=partial(CacheDecoder, self.client))
|
||||||
if self._cache.get('library_version') != __version__:
|
if self._cache.get("library_version") != __version__:
|
||||||
# Version mismatch, need to refresh cache
|
# Version mismatch, need to refresh cache
|
||||||
self.invalidate_cache()
|
self.invalidate_cache()
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -86,26 +95,30 @@ class Discoverer(kubernetes.dynamic.discovery.Discoverer):
|
|||||||
self._write_cache()
|
self._write_cache()
|
||||||
|
|
||||||
def get_resources_for_api_version(self, prefix, group, version, preferred):
|
def get_resources_for_api_version(self, prefix, group, version, preferred):
|
||||||
""" returns a dictionary of resources associated with provided (prefix, group, version)"""
|
"""returns a dictionary of resources associated with provided (prefix, group, version)"""
|
||||||
|
|
||||||
resources = defaultdict(list)
|
resources = defaultdict(list)
|
||||||
subresources = defaultdict(dict)
|
subresources = defaultdict(dict)
|
||||||
|
|
||||||
path = '/'.join(filter(None, [prefix, group, version]))
|
path = "/".join(filter(None, [prefix, group, version]))
|
||||||
try:
|
try:
|
||||||
resources_response = self.client.request('GET', path).resources or []
|
resources_response = self.client.request("GET", path).resources or []
|
||||||
except ServiceUnavailableError:
|
except ServiceUnavailableError:
|
||||||
resources_response = []
|
resources_response = []
|
||||||
|
|
||||||
resources_raw = list(filter(lambda resource: '/' not in resource['name'], resources_response))
|
resources_raw = list(
|
||||||
subresources_raw = list(filter(lambda resource: '/' in resource['name'], resources_response))
|
filter(lambda resource: "/" not in resource["name"], resources_response)
|
||||||
|
)
|
||||||
|
subresources_raw = list(
|
||||||
|
filter(lambda resource: "/" in resource["name"], resources_response)
|
||||||
|
)
|
||||||
for subresource in subresources_raw:
|
for subresource in subresources_raw:
|
||||||
resource, name = subresource['name'].split('/')
|
resource, name = subresource["name"].split("/", 1)
|
||||||
subresources[resource][name] = subresource
|
subresources[resource][name] = subresource
|
||||||
|
|
||||||
for resource in resources_raw:
|
for resource in resources_raw:
|
||||||
# Prevent duplicate keys
|
# Prevent duplicate keys
|
||||||
for key in ('prefix', 'group', 'api_version', 'client', 'preferred'):
|
for key in ("prefix", "group", "api_version", "client", "preferred"):
|
||||||
resource.pop(key, None)
|
resource.pop(key, None)
|
||||||
|
|
||||||
resourceobj = kubernetes.dynamic.Resource(
|
resourceobj = kubernetes.dynamic.Resource(
|
||||||
@@ -114,19 +127,25 @@ class Discoverer(kubernetes.dynamic.discovery.Discoverer):
|
|||||||
api_version=version,
|
api_version=version,
|
||||||
client=self.client,
|
client=self.client,
|
||||||
preferred=preferred,
|
preferred=preferred,
|
||||||
subresources=subresources.get(resource['name']),
|
subresources=subresources.get(resource["name"]),
|
||||||
**resource
|
**resource
|
||||||
)
|
)
|
||||||
resources[resource['kind']].append(resourceobj)
|
resources[resource["kind"]].append(resourceobj)
|
||||||
|
|
||||||
resource_lookup = {
|
resource_lookup = {
|
||||||
'prefix': prefix,
|
"prefix": prefix,
|
||||||
'group': group,
|
"group": group,
|
||||||
'api_version': version,
|
"api_version": version,
|
||||||
'kind': resourceobj.kind,
|
"kind": resourceobj.kind,
|
||||||
'name': resourceobj.name
|
"name": resourceobj.name,
|
||||||
}
|
}
|
||||||
resource_list = ResourceList(self.client, group=group, api_version=version, base_kind=resource['kind'], base_resource_lookup=resource_lookup)
|
resource_list = ResourceList(
|
||||||
|
self.client,
|
||||||
|
group=group,
|
||||||
|
api_version=version,
|
||||||
|
base_kind=resource["kind"],
|
||||||
|
base_resource_lookup=resource_lookup,
|
||||||
|
)
|
||||||
resources[resource_list.kind].append(resource_list)
|
resources[resource_list.kind].append(resource_list)
|
||||||
return resources
|
return resources
|
||||||
|
|
||||||
@@ -138,23 +157,32 @@ class Discoverer(kubernetes.dynamic.discovery.Discoverer):
|
|||||||
"""
|
"""
|
||||||
results = self.search(**kwargs)
|
results = self.search(**kwargs)
|
||||||
# If there are multiple matches, prefer exact matches on api_version
|
# If there are multiple matches, prefer exact matches on api_version
|
||||||
if len(results) > 1 and kwargs.get('api_version'):
|
if len(results) > 1 and kwargs.get("api_version"):
|
||||||
results = [
|
results = [
|
||||||
result for result in results if result.group_version == kwargs['api_version']
|
result
|
||||||
|
for result in results
|
||||||
|
if result.group_version == kwargs["api_version"]
|
||||||
]
|
]
|
||||||
# If there are multiple matches, prefer non-List kinds
|
# If there are multiple matches, prefer non-List kinds
|
||||||
if len(results) > 1 and not all([isinstance(x, ResourceList) for x in results]):
|
if len(results) > 1 and not all(isinstance(x, ResourceList) for x in results):
|
||||||
results = [result for result in results if not isinstance(result, ResourceList)]
|
results = [
|
||||||
|
result for result in results if not isinstance(result, ResourceList)
|
||||||
|
]
|
||||||
# if multiple resources are found that share a GVK, prefer the one with the most supported verbs
|
# if multiple resources are found that share a GVK, prefer the one with the most supported verbs
|
||||||
if len(results) > 1 and len(set((x.group_version, x.kind) for x in results)) == 1:
|
if (
|
||||||
|
len(results) > 1
|
||||||
|
and len(set((x.group_version, x.kind) for x in results)) == 1
|
||||||
|
):
|
||||||
if len(set(len(x.verbs) for x in results)) != 1:
|
if len(set(len(x.verbs) for x in results)) != 1:
|
||||||
results = [max(results, key=lambda x: len(x.verbs))]
|
results = [max(results, key=lambda x: len(x.verbs))]
|
||||||
if len(results) == 1:
|
if len(results) == 1:
|
||||||
return results[0]
|
return results[0]
|
||||||
elif not results:
|
elif not results:
|
||||||
raise ResourceNotFoundError('No matches found for {0}'.format(kwargs))
|
raise ResourceNotFoundError("No matches found for {0}".format(kwargs))
|
||||||
else:
|
else:
|
||||||
raise ResourceNotUniqueError('Multiple matches found for {0}: {1}'.format(kwargs, results))
|
raise ResourceNotUniqueError(
|
||||||
|
"Multiple matches found for {0}: {1}".format(kwargs, results)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class LazyDiscoverer(Discoverer, kubernetes.dynamic.LazyDiscoverer):
|
class LazyDiscoverer(Discoverer, kubernetes.dynamic.LazyDiscoverer):
|
||||||
@@ -162,6 +190,10 @@ class LazyDiscoverer(Discoverer, kubernetes.dynamic.LazyDiscoverer):
|
|||||||
Discoverer.__init__(self, client, cache_file)
|
Discoverer.__init__(self, client, cache_file)
|
||||||
self.__update_cache = False
|
self.__update_cache = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def update_cache(self):
|
||||||
|
self.__update_cache
|
||||||
|
|
||||||
|
|
||||||
class CacheDecoder(json.JSONDecoder):
|
class CacheDecoder(json.JSONDecoder):
|
||||||
def __init__(self, client, *args, **kwargs):
|
def __init__(self, client, *args, **kwargs):
|
||||||
@@ -169,13 +201,15 @@ class CacheDecoder(json.JSONDecoder):
|
|||||||
json.JSONDecoder.__init__(self, object_hook=self.object_hook, *args, **kwargs)
|
json.JSONDecoder.__init__(self, object_hook=self.object_hook, *args, **kwargs)
|
||||||
|
|
||||||
def object_hook(self, obj):
|
def object_hook(self, obj):
|
||||||
if '_type' not in obj:
|
if "_type" not in obj:
|
||||||
return obj
|
return obj
|
||||||
_type = obj.pop('_type')
|
_type = obj.pop("_type")
|
||||||
if _type == 'Resource':
|
if _type == "Resource":
|
||||||
return kubernetes.dynamic.Resource(client=self.client, **obj)
|
return kubernetes.dynamic.Resource(client=self.client, **obj)
|
||||||
elif _type == 'ResourceList':
|
elif _type == "ResourceList":
|
||||||
return ResourceList(self.client, **obj)
|
return ResourceList(self.client, **obj)
|
||||||
elif _type == 'ResourceGroup':
|
elif _type == "ResourceGroup":
|
||||||
return kubernetes.dynamic.discovery.ResourceGroup(obj['preferred'], resources=self.object_hook(obj['resources']))
|
return kubernetes.dynamic.discovery.ResourceGroup(
|
||||||
|
obj["preferred"], resources=self.object_hook(obj["resources"])
|
||||||
|
)
|
||||||
return obj
|
return obj
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
@@ -21,11 +22,19 @@ import kubernetes.dynamic
|
|||||||
|
|
||||||
|
|
||||||
class ResourceList(kubernetes.dynamic.resource.ResourceList):
|
class ResourceList(kubernetes.dynamic.resource.ResourceList):
|
||||||
def __init__(self, client, group='', api_version='v1', base_kind='', kind=None, base_resource_lookup=None):
|
def __init__(
|
||||||
|
self,
|
||||||
|
client,
|
||||||
|
group="",
|
||||||
|
api_version="v1",
|
||||||
|
base_kind="",
|
||||||
|
kind=None,
|
||||||
|
base_resource_lookup=None,
|
||||||
|
):
|
||||||
self.client = client
|
self.client = client
|
||||||
self.group = group
|
self.group = group
|
||||||
self.api_version = api_version
|
self.api_version = api_version
|
||||||
self.kind = kind or '{0}List'.format(base_kind)
|
self.kind = kind or "{0}List".format(base_kind)
|
||||||
self.base_kind = base_kind
|
self.base_kind = base_kind
|
||||||
self.base_resource_lookup = base_resource_lookup
|
self.base_resource_lookup = base_resource_lookup
|
||||||
self.__base_resource = None
|
self.__base_resource = None
|
||||||
@@ -34,16 +43,18 @@ class ResourceList(kubernetes.dynamic.resource.ResourceList):
|
|||||||
if self.__base_resource:
|
if self.__base_resource:
|
||||||
return self.__base_resource
|
return self.__base_resource
|
||||||
elif self.base_resource_lookup:
|
elif self.base_resource_lookup:
|
||||||
self.__base_resource = self.client.resources.get(**self.base_resource_lookup)
|
self.__base_resource = self.client.resources.get(
|
||||||
|
**self.base_resource_lookup
|
||||||
|
)
|
||||||
return self.__base_resource
|
return self.__base_resource
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
return {
|
return {
|
||||||
'_type': 'ResourceList',
|
"_type": "ResourceList",
|
||||||
'group': self.group,
|
"group": self.group,
|
||||||
'api_version': self.api_version,
|
"api_version": self.api_version,
|
||||||
'kind': self.kind,
|
"kind": self.kind,
|
||||||
'base_kind': self.base_kind,
|
"base_kind": self.base_kind,
|
||||||
'base_resource_lookup': self.base_resource_lookup
|
"base_resource_lookup": self.base_resource_lookup,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,866 +16,50 @@
|
|||||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
import time
|
|
||||||
import os
|
import os
|
||||||
import traceback
|
from tempfile import NamedTemporaryFile
|
||||||
import sys
|
|
||||||
import hashlib
|
|
||||||
from datetime import datetime
|
|
||||||
from distutils.version import LooseVersion
|
|
||||||
|
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (AUTH_ARG_MAP, AUTH_ARG_SPEC, AUTH_PROXY_HEADERS_SPEC)
|
from ansible.module_utils._text import to_bytes, to_native, to_text
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.hashes import generate_hash
|
from ansible.module_utils.urls import Request
|
||||||
|
|
||||||
from ansible.module_utils.basic import missing_required_lib
|
|
||||||
from ansible.module_utils.six import iteritems, string_types
|
|
||||||
from ansible.module_utils._text import to_native, to_bytes, to_text
|
|
||||||
from ansible.module_utils.common.dict_transformations import dict_merge
|
|
||||||
from ansible.module_utils.parsing.convert_bool import boolean
|
|
||||||
|
|
||||||
K8S_IMP_ERR = None
|
|
||||||
try:
|
|
||||||
import kubernetes
|
|
||||||
from kubernetes.dynamic.exceptions import (
|
|
||||||
NotFoundError, ResourceNotFoundError, ResourceNotUniqueError, DynamicApiError,
|
|
||||||
ConflictError, ForbiddenError, MethodNotAllowedError, BadRequestError,
|
|
||||||
KubernetesValidateMissing
|
|
||||||
)
|
|
||||||
HAS_K8S_MODULE_HELPER = True
|
|
||||||
k8s_import_exception = None
|
|
||||||
except ImportError as e:
|
|
||||||
HAS_K8S_MODULE_HELPER = False
|
|
||||||
k8s_import_exception = e
|
|
||||||
K8S_IMP_ERR = traceback.format_exc()
|
|
||||||
|
|
||||||
IMP_K8S_CLIENT = None
|
|
||||||
try:
|
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.k8sdynamicclient import K8SDynamicClient
|
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.client.discovery import LazyDiscoverer
|
|
||||||
IMP_K8S_CLIENT = True
|
|
||||||
except ImportError as e:
|
|
||||||
IMP_K8S_CLIENT = False
|
|
||||||
k8s_client_import_exception = e
|
|
||||||
IMP_K8S_CLIENT_ERR = traceback.format_exc()
|
|
||||||
|
|
||||||
YAML_IMP_ERR = None
|
|
||||||
try:
|
|
||||||
import yaml
|
|
||||||
HAS_YAML = True
|
|
||||||
except ImportError:
|
|
||||||
YAML_IMP_ERR = traceback.format_exc()
|
|
||||||
HAS_YAML = False
|
|
||||||
|
|
||||||
HAS_K8S_APPLY = None
|
|
||||||
try:
|
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.apply import apply_object
|
|
||||||
HAS_K8S_APPLY = True
|
|
||||||
except ImportError:
|
|
||||||
HAS_K8S_APPLY = False
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import urllib3
|
import urllib3
|
||||||
|
|
||||||
urllib3.disable_warnings()
|
urllib3.disable_warnings()
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.apply import recursive_diff
|
|
||||||
except ImportError:
|
|
||||||
from ansible.module_utils.common.dict_transformations import recursive_diff
|
|
||||||
|
|
||||||
try:
|
def fetch_file_from_url(module, url):
|
||||||
from kubernetes.dynamic.resource import ResourceInstance
|
# Download file
|
||||||
HAS_K8S_INSTANCE_HELPER = True
|
bufsize = 65536
|
||||||
k8s_import_exception = None
|
file_name, file_ext = os.path.splitext(str(url.rsplit("/", 1)[1]))
|
||||||
except ImportError as e:
|
temp_file = NamedTemporaryFile(
|
||||||
HAS_K8S_INSTANCE_HELPER = False
|
dir=module.tmpdir, prefix=file_name, suffix=file_ext, delete=False
|
||||||
k8s_import_exception = e
|
)
|
||||||
K8S_IMP_ERR = traceback.format_exc()
|
module.add_cleanup_file(temp_file.name)
|
||||||
|
|
||||||
|
|
||||||
def configuration_digest(configuration):
|
|
||||||
m = hashlib.sha256()
|
|
||||||
for k in AUTH_ARG_MAP:
|
|
||||||
if not hasattr(configuration, k):
|
|
||||||
v = None
|
|
||||||
else:
|
|
||||||
v = getattr(configuration, k)
|
|
||||||
if v and k in ["ssl_ca_cert", "cert_file", "key_file"]:
|
|
||||||
with open(str(v), "r") as fd:
|
|
||||||
content = fd.read()
|
|
||||||
m.update(content.encode())
|
|
||||||
else:
|
|
||||||
m.update(str(v).encode())
|
|
||||||
digest = m.hexdigest()
|
|
||||||
return digest
|
|
||||||
|
|
||||||
|
|
||||||
def get_api_client(module=None, **kwargs):
|
|
||||||
auth = {}
|
|
||||||
|
|
||||||
def _raise_or_fail(exc, msg):
|
|
||||||
if module:
|
|
||||||
module.fail_json(msg % to_native(exc))
|
|
||||||
raise exc
|
|
||||||
|
|
||||||
# If authorization variables aren't defined, look for them in environment variables
|
|
||||||
for true_name, arg_name in AUTH_ARG_MAP.items():
|
|
||||||
if module and module.params.get(arg_name):
|
|
||||||
auth[true_name] = module.params.get(arg_name)
|
|
||||||
elif arg_name in kwargs and kwargs.get(arg_name) is not None:
|
|
||||||
auth[true_name] = kwargs.get(arg_name)
|
|
||||||
elif arg_name == "proxy_headers":
|
|
||||||
# specific case for 'proxy_headers' which is a dictionary
|
|
||||||
proxy_headers = {}
|
|
||||||
for key in AUTH_PROXY_HEADERS_SPEC.keys():
|
|
||||||
env_value = os.getenv('K8S_AUTH_PROXY_HEADERS_{0}'.format(key.upper()), None)
|
|
||||||
if env_value is not None:
|
|
||||||
if AUTH_PROXY_HEADERS_SPEC[key].get('type') == 'bool':
|
|
||||||
env_value = env_value.lower() not in ['0', 'false', 'no']
|
|
||||||
proxy_headers[key] = env_value
|
|
||||||
if proxy_headers is not {}:
|
|
||||||
auth[true_name] = proxy_headers
|
|
||||||
else:
|
|
||||||
env_value = os.getenv('K8S_AUTH_{0}'.format(arg_name.upper()), None) or os.getenv('K8S_AUTH_{0}'.format(true_name.upper()), None)
|
|
||||||
if env_value is not None:
|
|
||||||
if AUTH_ARG_SPEC[arg_name].get('type') == 'bool':
|
|
||||||
env_value = env_value.lower() not in ['0', 'false', 'no']
|
|
||||||
auth[true_name] = env_value
|
|
||||||
|
|
||||||
def auth_set(*names):
|
|
||||||
return all([auth.get(name) for name in names])
|
|
||||||
|
|
||||||
if auth_set('host'):
|
|
||||||
# Removing trailing slashes if any from hostname
|
|
||||||
auth['host'] = auth.get('host').rstrip('/')
|
|
||||||
|
|
||||||
if auth_set('username', 'password', 'host') or auth_set('api_key', 'host'):
|
|
||||||
# We have enough in the parameters to authenticate, no need to load incluster or kubeconfig
|
|
||||||
pass
|
|
||||||
elif auth_set('kubeconfig') or auth_set('context'):
|
|
||||||
try:
|
|
||||||
kubernetes.config.load_kube_config(auth.get('kubeconfig'), auth.get('context'), persist_config=auth.get('persist_config'))
|
|
||||||
except Exception as err:
|
|
||||||
_raise_or_fail(err, 'Failed to load kubeconfig due to %s')
|
|
||||||
|
|
||||||
else:
|
|
||||||
# First try to do incluster config, then kubeconfig
|
|
||||||
try:
|
|
||||||
kubernetes.config.load_incluster_config()
|
|
||||||
except kubernetes.config.ConfigException:
|
|
||||||
try:
|
|
||||||
kubernetes.config.load_kube_config(auth.get('kubeconfig'), auth.get('context'), persist_config=auth.get('persist_config'))
|
|
||||||
except Exception as err:
|
|
||||||
_raise_or_fail(err, 'Failed to load kubeconfig due to %s')
|
|
||||||
|
|
||||||
# Override any values in the default configuration with Ansible parameters
|
|
||||||
# As of kubernetes-client v12.0.0, get_default_copy() is required here
|
|
||||||
try:
|
try:
|
||||||
configuration = kubernetes.client.Configuration().get_default_copy()
|
rsp = Request().open("GET", url)
|
||||||
except AttributeError:
|
if not rsp:
|
||||||
configuration = kubernetes.client.Configuration()
|
module.fail_json(msg="Failure downloading %s" % url)
|
||||||
|
data = rsp.read(bufsize)
|
||||||
for key, value in iteritems(auth):
|
while data:
|
||||||
if key in AUTH_ARG_MAP.keys() and value is not None:
|
temp_file.write(data)
|
||||||
if key == 'api_key':
|
data = rsp.read(bufsize)
|
||||||
setattr(configuration, key, {'authorization': "Bearer {0}".format(value)})
|
temp_file.close()
|
||||||
elif key == 'proxy_headers':
|
except Exception as e:
|
||||||
headers = urllib3.util.make_headers(**value)
|
module.fail_json(msg="Failure downloading %s, %s" % (url, to_native(e)))
|
||||||
setattr(configuration, key, headers)
|
return temp_file.name
|
||||||
else:
|
|
||||||
setattr(configuration, key, value)
|
|
||||||
|
|
||||||
digest = configuration_digest(configuration)
|
|
||||||
if digest in get_api_client._pool:
|
|
||||||
client = get_api_client._pool[digest]
|
|
||||||
return client
|
|
||||||
|
|
||||||
try:
|
|
||||||
client = K8SDynamicClient(kubernetes.client.ApiClient(configuration), discoverer=LazyDiscoverer)
|
|
||||||
except Exception as err:
|
|
||||||
_raise_or_fail(err, 'Failed to get client due to %s')
|
|
||||||
|
|
||||||
get_api_client._pool[digest] = client
|
|
||||||
return client
|
|
||||||
|
|
||||||
|
|
||||||
get_api_client._pool = {}
|
|
||||||
|
|
||||||
|
|
||||||
class K8sAnsibleMixin(object):
|
|
||||||
|
|
||||||
def __init__(self, module, *args, **kwargs):
|
|
||||||
if not HAS_K8S_MODULE_HELPER:
|
|
||||||
module.fail_json(msg=missing_required_lib('kubernetes'), exception=K8S_IMP_ERR,
|
|
||||||
error=to_native(k8s_import_exception))
|
|
||||||
self.kubernetes_version = kubernetes.__version__
|
|
||||||
|
|
||||||
if not HAS_YAML:
|
|
||||||
module.fail_json(msg=missing_required_lib("PyYAML"), exception=YAML_IMP_ERR)
|
|
||||||
|
|
||||||
def find_resource(self, kind, api_version, fail=False):
|
|
||||||
for attribute in ['kind', 'name', 'singular_name']:
|
|
||||||
try:
|
|
||||||
return self.client.resources.get(**{'api_version': api_version, attribute: kind})
|
|
||||||
except (ResourceNotFoundError, ResourceNotUniqueError):
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
return self.client.resources.get(api_version=api_version, short_names=[kind])
|
|
||||||
except (ResourceNotFoundError, ResourceNotUniqueError):
|
|
||||||
if fail:
|
|
||||||
self.fail(msg='Failed to find exact match for {0}.{1} by [kind, name, singularName, shortNames]'.format(api_version, kind))
|
|
||||||
|
|
||||||
def kubernetes_facts(self, kind, api_version, name=None, namespace=None, label_selectors=None, field_selectors=None,
|
|
||||||
wait=False, wait_sleep=5, wait_timeout=120, state='present', condition=None):
|
|
||||||
resource = self.find_resource(kind, api_version)
|
|
||||||
api_found = bool(resource)
|
|
||||||
if not api_found:
|
|
||||||
return dict(resources=[], msg='Failed to find API for resource with apiVersion "{0}" and kind "{1}"'.format(api_version, kind), api_found=False)
|
|
||||||
|
|
||||||
if not label_selectors:
|
|
||||||
label_selectors = []
|
|
||||||
if not field_selectors:
|
|
||||||
field_selectors = []
|
|
||||||
|
|
||||||
result = None
|
|
||||||
try:
|
|
||||||
result = resource.get(name=name, namespace=namespace,
|
|
||||||
label_selector=','.join(label_selectors),
|
|
||||||
field_selector=','.join(field_selectors))
|
|
||||||
except BadRequestError:
|
|
||||||
return dict(resources=[], api_found=True)
|
|
||||||
except NotFoundError:
|
|
||||||
if not wait or name is None:
|
|
||||||
return dict(resources=[], api_found=True)
|
|
||||||
|
|
||||||
if not wait:
|
|
||||||
result = result.to_dict()
|
|
||||||
if 'items' in result:
|
|
||||||
return dict(resources=result['items'], api_found=True)
|
|
||||||
return dict(resources=[result], api_found=True)
|
|
||||||
|
|
||||||
start = datetime.now()
|
|
||||||
|
|
||||||
def _elapsed():
|
|
||||||
return (datetime.now() - start).seconds
|
|
||||||
|
|
||||||
if result is None:
|
|
||||||
while _elapsed() < wait_timeout:
|
|
||||||
try:
|
|
||||||
result = resource.get(name=name, namespace=namespace,
|
|
||||||
label_selector=','.join(label_selectors),
|
|
||||||
field_selector=','.join(field_selectors))
|
|
||||||
break
|
|
||||||
except NotFoundError:
|
|
||||||
pass
|
|
||||||
time.sleep(wait_sleep)
|
|
||||||
if result is None:
|
|
||||||
return dict(resources=[], api_found=True)
|
|
||||||
|
|
||||||
if isinstance(result, ResourceInstance):
|
|
||||||
satisfied_by = []
|
|
||||||
# We have a list of ResourceInstance
|
|
||||||
resource_list = result.get('items', [])
|
|
||||||
if not resource_list:
|
|
||||||
resource_list = [result]
|
|
||||||
|
|
||||||
for resource_instance in resource_list:
|
|
||||||
success, res, duration = self.wait(resource, resource_instance,
|
|
||||||
sleep=wait_sleep, timeout=wait_timeout,
|
|
||||||
state=state, condition=condition)
|
|
||||||
if not success:
|
|
||||||
self.fail(msg="Failed to gather information about %s(s) even"
|
|
||||||
" after waiting for %s seconds" % (res.get('kind'), duration))
|
|
||||||
satisfied_by.append(res)
|
|
||||||
return dict(resources=satisfied_by, api_found=True)
|
|
||||||
result = result.to_dict()
|
|
||||||
|
|
||||||
if 'items' in result:
|
|
||||||
return dict(resources=result['items'], api_found=True)
|
|
||||||
return dict(resources=[result], api_found=True)
|
|
||||||
|
|
||||||
def remove_aliases(self):
|
|
||||||
"""
|
|
||||||
The helper doesn't know what to do with aliased keys
|
|
||||||
"""
|
|
||||||
for k, v in iteritems(self.argspec):
|
|
||||||
if 'aliases' in v:
|
|
||||||
for alias in v['aliases']:
|
|
||||||
if alias in self.params:
|
|
||||||
self.params.pop(alias)
|
|
||||||
|
|
||||||
def load_resource_definitions(self, src):
|
|
||||||
""" Load the requested src path """
|
|
||||||
result = None
|
|
||||||
path = os.path.normpath(src)
|
|
||||||
if not os.path.exists(path):
|
|
||||||
self.fail(msg="Error accessing {0}. Does the file exist?".format(path))
|
|
||||||
try:
|
|
||||||
with open(path, 'r') as f:
|
|
||||||
result = list(yaml.safe_load_all(f))
|
|
||||||
except (IOError, yaml.YAMLError) as exc:
|
|
||||||
self.fail(msg="Error loading resource_definition: {0}".format(exc))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def diff_objects(self, existing, new):
|
|
||||||
result = dict()
|
|
||||||
diff = recursive_diff(existing, new)
|
|
||||||
if not diff:
|
|
||||||
return True, result
|
|
||||||
|
|
||||||
result['before'] = diff[0]
|
|
||||||
result['after'] = diff[1]
|
|
||||||
|
|
||||||
# If only metadata.generation and metadata.resourceVersion changed, ignore it
|
|
||||||
ignored_keys = set(['generation', 'resourceVersion'])
|
|
||||||
|
|
||||||
if list(result['after'].keys()) != ['metadata'] or list(result['before'].keys()) != ['metadata']:
|
|
||||||
return False, result
|
|
||||||
|
|
||||||
if not set(result['after']['metadata'].keys()).issubset(ignored_keys):
|
|
||||||
return False, result
|
|
||||||
if not set(result['before']['metadata'].keys()).issubset(ignored_keys):
|
|
||||||
return False, result
|
|
||||||
|
|
||||||
if hasattr(self, 'warn'):
|
|
||||||
self.warn('No meaningful diff was generated, but the API may not be idempotent (only metadata.generation or metadata.resourceVersion were changed)')
|
|
||||||
|
|
||||||
return True, result
|
|
||||||
|
|
||||||
def fail(self, msg=None):
|
|
||||||
self.fail_json(msg=msg)
|
|
||||||
|
|
||||||
def _wait_for(self, resource, name, namespace, predicate, sleep, timeout, state):
|
|
||||||
start = datetime.now()
|
|
||||||
|
|
||||||
def _wait_for_elapsed():
|
|
||||||
return (datetime.now() - start).seconds
|
|
||||||
|
|
||||||
response = None
|
|
||||||
while _wait_for_elapsed() < timeout:
|
|
||||||
try:
|
|
||||||
response = resource.get(name=name, namespace=namespace)
|
|
||||||
if predicate(response):
|
|
||||||
if response:
|
|
||||||
return True, response.to_dict(), _wait_for_elapsed()
|
|
||||||
return True, {}, _wait_for_elapsed()
|
|
||||||
time.sleep(sleep)
|
|
||||||
except NotFoundError:
|
|
||||||
if state == 'absent':
|
|
||||||
return True, {}, _wait_for_elapsed()
|
|
||||||
if response:
|
|
||||||
response = response.to_dict()
|
|
||||||
return False, response, _wait_for_elapsed()
|
|
||||||
|
|
||||||
def wait(self, resource, definition, sleep, timeout, state='present', condition=None):
|
|
||||||
|
|
||||||
def _deployment_ready(deployment):
|
|
||||||
# FIXME: frustratingly bool(deployment.status) is True even if status is empty
|
|
||||||
# Furthermore deployment.status.availableReplicas == deployment.status.replicas == None if status is empty
|
|
||||||
# deployment.status.replicas is None is perfectly ok if desired replicas == 0
|
|
||||||
# Scaling up means that we also need to check that we're not in a
|
|
||||||
# situation where status.replicas == status.availableReplicas
|
|
||||||
# but spec.replicas != status.replicas
|
|
||||||
return (deployment.status
|
|
||||||
and deployment.spec.replicas == (deployment.status.replicas or 0)
|
|
||||||
and deployment.status.availableReplicas == deployment.status.replicas
|
|
||||||
and deployment.status.observedGeneration == deployment.metadata.generation
|
|
||||||
and not deployment.status.unavailableReplicas)
|
|
||||||
|
|
||||||
def _pod_ready(pod):
|
|
||||||
return (pod.status and pod.status.containerStatuses is not None
|
|
||||||
and all([container.ready for container in pod.status.containerStatuses]))
|
|
||||||
|
|
||||||
def _daemonset_ready(daemonset):
|
|
||||||
return (daemonset.status and daemonset.status.desiredNumberScheduled is not None
|
|
||||||
and daemonset.status.updatedNumberScheduled == daemonset.status.desiredNumberScheduled
|
|
||||||
and daemonset.status.numberReady == daemonset.status.desiredNumberScheduled
|
|
||||||
and daemonset.status.observedGeneration == daemonset.metadata.generation
|
|
||||||
and not daemonset.status.unavailableReplicas)
|
|
||||||
|
|
||||||
def _custom_condition(resource):
|
|
||||||
if not resource.status or not resource.status.conditions:
|
|
||||||
return False
|
|
||||||
match = [x for x in resource.status.conditions if x.type == condition['type']]
|
|
||||||
if not match:
|
|
||||||
return False
|
|
||||||
# There should never be more than one condition of a specific type
|
|
||||||
match = match[0]
|
|
||||||
if match.status == 'Unknown':
|
|
||||||
if match.status == condition['status']:
|
|
||||||
if 'reason' not in condition:
|
|
||||||
return True
|
|
||||||
if condition['reason']:
|
|
||||||
return match.reason == condition['reason']
|
|
||||||
return False
|
|
||||||
status = True if match.status == 'True' else False
|
|
||||||
if status == boolean(condition['status'], strict=False):
|
|
||||||
if condition.get('reason'):
|
|
||||||
return match.reason == condition['reason']
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _resource_absent(resource):
|
|
||||||
return not resource
|
|
||||||
|
|
||||||
waiter = dict(
|
|
||||||
Deployment=_deployment_ready,
|
|
||||||
DaemonSet=_daemonset_ready,
|
|
||||||
Pod=_pod_ready
|
|
||||||
)
|
|
||||||
kind = definition['kind']
|
|
||||||
if state == 'present' and not condition:
|
|
||||||
predicate = waiter.get(kind, lambda x: x)
|
|
||||||
elif state == 'present' and condition:
|
|
||||||
predicate = _custom_condition
|
|
||||||
else:
|
|
||||||
predicate = _resource_absent
|
|
||||||
return self._wait_for(resource, definition['metadata']['name'], definition['metadata'].get('namespace'), predicate, sleep, timeout, state)
|
|
||||||
|
|
||||||
def set_resource_definitions(self, module):
|
|
||||||
resource_definition = module.params.get('resource_definition')
|
|
||||||
|
|
||||||
self.resource_definitions = []
|
|
||||||
if resource_definition:
|
|
||||||
if isinstance(resource_definition, string_types):
|
|
||||||
try:
|
|
||||||
self.resource_definitions = yaml.safe_load_all(resource_definition)
|
|
||||||
except (IOError, yaml.YAMLError) as exc:
|
|
||||||
self.fail(msg="Error loading resource_definition: {0}".format(exc))
|
|
||||||
elif isinstance(resource_definition, list):
|
|
||||||
for resource in resource_definition:
|
|
||||||
if isinstance(resource, string_types):
|
|
||||||
yaml_data = yaml.safe_load_all(resource)
|
|
||||||
for item in yaml_data:
|
|
||||||
if item is not None:
|
|
||||||
self.resource_definitions.append(item)
|
|
||||||
else:
|
|
||||||
self.resource_definitions.append(resource)
|
|
||||||
else:
|
|
||||||
self.resource_definitions = [resource_definition]
|
|
||||||
|
|
||||||
src = module.params.get('src')
|
|
||||||
if src:
|
|
||||||
self.resource_definitions = self.load_resource_definitions(src)
|
|
||||||
try:
|
|
||||||
self.resource_definitions = [item for item in self.resource_definitions if item]
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if not resource_definition and not src:
|
|
||||||
implicit_definition = dict(
|
|
||||||
kind=module.params['kind'],
|
|
||||||
apiVersion=module.params['api_version'],
|
|
||||||
metadata=dict(name=module.params['name'])
|
|
||||||
)
|
|
||||||
if module.params.get('namespace'):
|
|
||||||
implicit_definition['metadata']['namespace'] = module.params.get('namespace')
|
|
||||||
self.resource_definitions = [implicit_definition]
|
|
||||||
|
|
||||||
def check_library_version(self):
|
|
||||||
if LooseVersion(self.kubernetes_version) < LooseVersion("12.0.0"):
|
|
||||||
self.fail_json(msg="kubernetes >= 12.0.0 is required")
|
|
||||||
|
|
||||||
def flatten_list_kind(self, list_resource, definitions):
|
|
||||||
flattened = []
|
|
||||||
parent_api_version = list_resource.group_version if list_resource else None
|
|
||||||
parent_kind = list_resource.kind[:-4] if list_resource else None
|
|
||||||
for definition in definitions.get('items', []):
|
|
||||||
resource = self.find_resource(definition.get('kind', parent_kind), definition.get('apiVersion', parent_api_version), fail=True)
|
|
||||||
flattened.append((resource, self.set_defaults(resource, definition)))
|
|
||||||
return flattened
|
|
||||||
|
|
||||||
def execute_module(self):
|
|
||||||
changed = False
|
|
||||||
results = []
|
|
||||||
try:
|
|
||||||
self.client = get_api_client(self.module)
|
|
||||||
# Hopefully the kubernetes client will provide its own exception class one day
|
|
||||||
except (urllib3.exceptions.RequestError) as e:
|
|
||||||
self.fail_json(msg="Couldn't connect to Kubernetes: %s" % str(e))
|
|
||||||
|
|
||||||
flattened_definitions = []
|
|
||||||
for definition in self.resource_definitions:
|
|
||||||
if definition is None:
|
|
||||||
continue
|
|
||||||
kind = definition.get('kind', self.kind)
|
|
||||||
api_version = definition.get('apiVersion', self.api_version)
|
|
||||||
if kind and kind.endswith('List'):
|
|
||||||
resource = self.find_resource(kind, api_version, fail=False)
|
|
||||||
flattened_definitions.extend(self.flatten_list_kind(resource, definition))
|
|
||||||
else:
|
|
||||||
resource = self.find_resource(kind, api_version, fail=True)
|
|
||||||
flattened_definitions.append((resource, definition))
|
|
||||||
|
|
||||||
for (resource, definition) in flattened_definitions:
|
|
||||||
kind = definition.get('kind', self.kind)
|
|
||||||
api_version = definition.get('apiVersion', self.api_version)
|
|
||||||
definition = self.set_defaults(resource, definition)
|
|
||||||
self.warnings = []
|
|
||||||
if self.params['validate'] is not None:
|
|
||||||
self.warnings = self.validate(definition)
|
|
||||||
result = self.perform_action(resource, definition)
|
|
||||||
if self.warnings:
|
|
||||||
result['warnings'] = self.warnings
|
|
||||||
changed = changed or result['changed']
|
|
||||||
results.append(result)
|
|
||||||
|
|
||||||
if len(results) == 1:
|
|
||||||
self.exit_json(**results[0])
|
|
||||||
|
|
||||||
self.exit_json(**{
|
|
||||||
'changed': changed,
|
|
||||||
'result': {
|
|
||||||
'results': results
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
def validate(self, resource):
|
|
||||||
def _prepend_resource_info(resource, msg):
|
|
||||||
return "%s %s: %s" % (resource['kind'], resource['metadata']['name'], msg)
|
|
||||||
|
|
||||||
try:
|
|
||||||
warnings, errors = self.client.validate(resource, self.params['validate'].get('version'), self.params['validate'].get('strict'))
|
|
||||||
except KubernetesValidateMissing:
|
|
||||||
self.fail_json(msg="kubernetes-validate python library is required to validate resources")
|
|
||||||
|
|
||||||
if errors and self.params['validate']['fail_on_error']:
|
|
||||||
self.fail_json(msg="\n".join([_prepend_resource_info(resource, error) for error in errors]))
|
|
||||||
else:
|
|
||||||
return [_prepend_resource_info(resource, msg) for msg in warnings + errors]
|
|
||||||
|
|
||||||
def set_defaults(self, resource, definition):
|
|
||||||
definition['kind'] = resource.kind
|
|
||||||
definition['apiVersion'] = resource.group_version
|
|
||||||
metadata = definition.get('metadata', {})
|
|
||||||
if self.name and not metadata.get('name'):
|
|
||||||
metadata['name'] = self.name
|
|
||||||
if resource.namespaced and self.namespace and not metadata.get('namespace'):
|
|
||||||
metadata['namespace'] = self.namespace
|
|
||||||
definition['metadata'] = metadata
|
|
||||||
return definition
|
|
||||||
|
|
||||||
def perform_action(self, resource, definition):
|
|
||||||
append_hash = self.params.get('append_hash', False)
|
|
||||||
apply = self.params.get('apply', False)
|
|
||||||
delete_options = self.params.get('delete_options')
|
|
||||||
result = {'changed': False, 'result': {}}
|
|
||||||
state = self.params.get('state', None)
|
|
||||||
force = self.params.get('force', False)
|
|
||||||
name = definition['metadata'].get('name')
|
|
||||||
origin_name = definition['metadata'].get('name')
|
|
||||||
namespace = definition['metadata'].get('namespace')
|
|
||||||
existing = None
|
|
||||||
wait = self.params.get('wait')
|
|
||||||
wait_sleep = self.params.get('wait_sleep')
|
|
||||||
wait_timeout = self.params.get('wait_timeout')
|
|
||||||
wait_condition = None
|
|
||||||
continue_on_error = self.params.get('continue_on_error')
|
|
||||||
if self.params.get('wait_condition') and self.params['wait_condition'].get('type'):
|
|
||||||
wait_condition = self.params['wait_condition']
|
|
||||||
|
|
||||||
def build_error_msg(kind, name, msg):
|
|
||||||
return "%s %s: %s" % (kind, name, msg)
|
|
||||||
|
|
||||||
self.remove_aliases()
|
|
||||||
|
|
||||||
try:
|
|
||||||
# ignore append_hash for resources other than ConfigMap and Secret
|
|
||||||
if append_hash and definition['kind'] in ['ConfigMap', 'Secret']:
|
|
||||||
name = '%s-%s' % (name, generate_hash(definition))
|
|
||||||
definition['metadata']['name'] = name
|
|
||||||
params = dict(name=name)
|
|
||||||
if namespace:
|
|
||||||
params['namespace'] = namespace
|
|
||||||
existing = resource.get(**params)
|
|
||||||
except (NotFoundError, MethodNotAllowedError):
|
|
||||||
# Remove traceback so that it doesn't show up in later failures
|
|
||||||
try:
|
|
||||||
sys.exc_clear()
|
|
||||||
except AttributeError:
|
|
||||||
# no sys.exc_clear on python3
|
|
||||||
pass
|
|
||||||
except ForbiddenError as exc:
|
|
||||||
if definition['kind'] in ['Project', 'ProjectRequest'] and state != 'absent':
|
|
||||||
return self.create_project_request(definition)
|
|
||||||
msg = 'Failed to retrieve requested object: {0}'.format(exc.body)
|
|
||||||
if continue_on_error:
|
|
||||||
result['error'] = dict(msg=build_error_msg(definition['kind'], origin_name, msg), error=exc.status, status=exc.status, reason=exc.reason)
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
self.fail_json(msg=build_error_msg(definition['kind'], origin_name, msg), error=exc.status, status=exc.status, reason=exc.reason)
|
|
||||||
except DynamicApiError as exc:
|
|
||||||
msg = 'Failed to retrieve requested object: {0}'.format(exc.body)
|
|
||||||
if continue_on_error:
|
|
||||||
result['error'] = dict(msg=build_error_msg(definition['kind'], origin_name, msg), error=exc.status, status=exc.status, reason=exc.reason)
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
self.fail_json(msg=build_error_msg(definition['kind'], origin_name, msg), error=exc.status, status=exc.status, reason=exc.reason)
|
|
||||||
except ValueError as value_exc:
|
|
||||||
msg = 'Failed to retrieve requested object: {0}'.format(to_native(value_exc))
|
|
||||||
if continue_on_error:
|
|
||||||
result['error'] = dict(msg=build_error_msg(definition['kind'], origin_name, msg), error='', status='', reason='')
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
self.fail_json(msg=build_error_msg(definition['kind'], origin_name, msg), error='', status='', reason='')
|
|
||||||
|
|
||||||
if state == 'absent':
|
|
||||||
result['method'] = "delete"
|
|
||||||
if not existing:
|
|
||||||
# The object already does not exist
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
# Delete the object
|
|
||||||
result['changed'] = True
|
|
||||||
if not self.check_mode:
|
|
||||||
if delete_options:
|
|
||||||
body = {
|
|
||||||
'apiVersion': 'v1',
|
|
||||||
'kind': 'DeleteOptions',
|
|
||||||
}
|
|
||||||
body.update(delete_options)
|
|
||||||
params['body'] = body
|
|
||||||
try:
|
|
||||||
k8s_obj = resource.delete(**params)
|
|
||||||
result['result'] = k8s_obj.to_dict()
|
|
||||||
except DynamicApiError as exc:
|
|
||||||
msg = "Failed to delete object: {0}".format(exc.body)
|
|
||||||
if continue_on_error:
|
|
||||||
result['error'] = dict(msg=build_error_msg(definition['kind'], origin_name, msg),
|
|
||||||
error=exc.status, status=exc.status, reason=exc.reason)
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
self.fail_json(msg=build_error_msg(definition['kind'], origin_name, msg), error=exc.status, status=exc.status, reason=exc.reason)
|
|
||||||
if wait:
|
|
||||||
success, resource, duration = self.wait(resource, definition, wait_sleep, wait_timeout, 'absent')
|
|
||||||
result['duration'] = duration
|
|
||||||
if not success:
|
|
||||||
msg = "Resource deletion timed out"
|
|
||||||
if continue_on_error:
|
|
||||||
result['error'] = dict(msg=build_error_msg(definition['kind'], origin_name, msg), **result)
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
self.fail_json(msg=build_error_msg(definition['kind'], origin_name, msg), **result)
|
|
||||||
return result
|
|
||||||
|
|
||||||
else:
|
|
||||||
if apply:
|
|
||||||
if self.check_mode:
|
|
||||||
ignored, patch = apply_object(resource, _encode_stringdata(definition))
|
|
||||||
if existing:
|
|
||||||
k8s_obj = dict_merge(existing.to_dict(), patch)
|
|
||||||
else:
|
|
||||||
k8s_obj = patch
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
k8s_obj = resource.apply(definition, namespace=namespace).to_dict()
|
|
||||||
except DynamicApiError as exc:
|
|
||||||
msg = "Failed to apply object: {0}".format(exc.body)
|
|
||||||
if self.warnings:
|
|
||||||
msg += "\n" + "\n ".join(self.warnings)
|
|
||||||
if continue_on_error:
|
|
||||||
result['error'] = dict(msg=build_error_msg(definition['kind'],
|
|
||||||
origin_name, msg), error=exc.status, status=exc.status, reason=exc.reason)
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
self.fail_json(msg=build_error_msg(definition['kind'], origin_name, msg), error=exc.status, status=exc.status, reason=exc.reason)
|
|
||||||
success = True
|
|
||||||
result['result'] = k8s_obj
|
|
||||||
if wait and not self.check_mode:
|
|
||||||
success, result['result'], result['duration'] = self.wait(resource, definition, wait_sleep, wait_timeout, condition=wait_condition)
|
|
||||||
if existing:
|
|
||||||
existing = existing.to_dict()
|
|
||||||
else:
|
|
||||||
existing = {}
|
|
||||||
match, diffs = self.diff_objects(existing, result['result'])
|
|
||||||
result['changed'] = not match
|
|
||||||
result['diff'] = diffs
|
|
||||||
result['method'] = 'apply'
|
|
||||||
if not success:
|
|
||||||
msg = "Resource apply timed out"
|
|
||||||
if continue_on_error:
|
|
||||||
result['error'] = dict(msg=build_error_msg(definition['kind'], origin_name, msg), **result)
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
self.fail_json(msg=build_error_msg(definition['kind'], origin_name, msg), **result)
|
|
||||||
return result
|
|
||||||
|
|
||||||
if not existing:
|
|
||||||
if state == 'patched':
|
|
||||||
# Silently skip this resource (do not raise an error) as 'patch_only' is set to true
|
|
||||||
result['changed'] = False
|
|
||||||
result['warning'] = "resource 'kind={kind},name={name}' was not found but will not be created as 'state'\
|
|
||||||
parameter has been set to '{state}'".format(
|
|
||||||
kind=definition['kind'], name=origin_name, state=state)
|
|
||||||
return result
|
|
||||||
elif self.check_mode:
|
|
||||||
k8s_obj = _encode_stringdata(definition)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
k8s_obj = resource.create(definition, namespace=namespace).to_dict()
|
|
||||||
except ConflictError:
|
|
||||||
# Some resources, like ProjectRequests, can't be created multiple times,
|
|
||||||
# because the resources that they create don't match their kind
|
|
||||||
# In this case we'll mark it as unchanged and warn the user
|
|
||||||
self.warn("{0} was not found, but creating it returned a 409 Conflict error. This can happen \
|
|
||||||
if the resource you are creating does not directly create a resource of the same kind.".format(name))
|
|
||||||
return result
|
|
||||||
except DynamicApiError as exc:
|
|
||||||
msg = "Failed to create object: {0}".format(exc.body)
|
|
||||||
if self.warnings:
|
|
||||||
msg += "\n" + "\n ".join(self.warnings)
|
|
||||||
if continue_on_error:
|
|
||||||
result['error'] = dict(msg=build_error_msg(definition['kind'], origin_name, msg),
|
|
||||||
error=exc.status, status=exc.status, reason=exc.reason)
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
self.fail_json(msg=build_error_msg(definition['kind'], origin_name, msg), error=exc.status, status=exc.status, reason=exc.reason)
|
|
||||||
except Exception as exc:
|
|
||||||
msg = "Failed to create object: {0}".format(exc)
|
|
||||||
if self.warnings:
|
|
||||||
msg += "\n" + "\n ".join(self.warnings)
|
|
||||||
if continue_on_error:
|
|
||||||
result['error'] = dict(msg=build_error_msg(definition['kind'], origin_name, msg), error='', status='', reason='')
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
self.fail_json(msg=msg, error='', status='', reason='')
|
|
||||||
success = True
|
|
||||||
result['result'] = k8s_obj
|
|
||||||
if wait and not self.check_mode:
|
|
||||||
success, result['result'], result['duration'] = self.wait(resource, definition, wait_sleep, wait_timeout, condition=wait_condition)
|
|
||||||
result['changed'] = True
|
|
||||||
result['method'] = 'create'
|
|
||||||
if not success:
|
|
||||||
msg = "Resource creation timed out"
|
|
||||||
if continue_on_error:
|
|
||||||
result['error'] = dict(msg=build_error_msg(definition['kind'], origin_name, msg), **result)
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
self.fail_json(msg=msg, **result)
|
|
||||||
return result
|
|
||||||
|
|
||||||
match = False
|
|
||||||
diffs = []
|
|
||||||
|
|
||||||
if state == 'present' and existing and force:
|
|
||||||
if self.check_mode:
|
|
||||||
k8s_obj = _encode_stringdata(definition)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
k8s_obj = resource.replace(definition, name=name, namespace=namespace, append_hash=append_hash).to_dict()
|
|
||||||
except DynamicApiError as exc:
|
|
||||||
msg = "Failed to replace object: {0}".format(exc.body)
|
|
||||||
if self.warnings:
|
|
||||||
msg += "\n" + "\n ".join(self.warnings)
|
|
||||||
if continue_on_error:
|
|
||||||
result['error'] = dict(msg=build_error_msg(definition['kind'], origin_name, msg),
|
|
||||||
error=exc.status, status=exc.status, reason=exc.reason)
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
self.fail_json(msg=msg, error=exc.status, status=exc.status, reason=exc.reason)
|
|
||||||
match, diffs = self.diff_objects(existing.to_dict(), k8s_obj)
|
|
||||||
success = True
|
|
||||||
result['result'] = k8s_obj
|
|
||||||
if wait and not self.check_mode:
|
|
||||||
success, result['result'], result['duration'] = self.wait(resource, definition, wait_sleep, wait_timeout, condition=wait_condition)
|
|
||||||
match, diffs = self.diff_objects(existing.to_dict(), result['result'])
|
|
||||||
result['changed'] = not match
|
|
||||||
result['method'] = 'replace'
|
|
||||||
result['diff'] = diffs
|
|
||||||
if not success:
|
|
||||||
msg = "Resource replacement timed out"
|
|
||||||
if continue_on_error:
|
|
||||||
result['error'] = dict(msg=build_error_msg(definition['kind'], origin_name, msg), **result)
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
self.fail_json(msg=msg, **result)
|
|
||||||
return result
|
|
||||||
|
|
||||||
# Differences exist between the existing obj and requested params
|
|
||||||
if self.check_mode:
|
|
||||||
k8s_obj = dict_merge(existing.to_dict(), _encode_stringdata(definition))
|
|
||||||
else:
|
|
||||||
for merge_type in self.params['merge_type'] or ['strategic-merge', 'merge']:
|
|
||||||
k8s_obj, error = self.patch_resource(resource, definition, existing, name,
|
|
||||||
namespace, merge_type=merge_type)
|
|
||||||
if not error:
|
|
||||||
break
|
|
||||||
if error:
|
|
||||||
if continue_on_error:
|
|
||||||
result['error'] = error
|
|
||||||
result['error']['msg'] = build_error_msg(definition['kind'], origin_name, result['error'].get('msg'))
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
self.fail_json(**error)
|
|
||||||
|
|
||||||
success = True
|
|
||||||
result['result'] = k8s_obj
|
|
||||||
if wait and not self.check_mode:
|
|
||||||
success, result['result'], result['duration'] = self.wait(resource, definition, wait_sleep, wait_timeout, condition=wait_condition)
|
|
||||||
match, diffs = self.diff_objects(existing.to_dict(), result['result'])
|
|
||||||
result['changed'] = not match
|
|
||||||
result['method'] = 'patch'
|
|
||||||
result['diff'] = diffs
|
|
||||||
|
|
||||||
if not success:
|
|
||||||
msg = "Resource update timed out"
|
|
||||||
if continue_on_error:
|
|
||||||
result['error'] = dict(msg=build_error_msg(definition['kind'], origin_name, msg), **result)
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
self.fail_json(msg=msg, **result)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def patch_resource(self, resource, definition, existing, name, namespace, merge_type=None):
|
|
||||||
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="3.0.0", collection_name="kubernetes.core")
|
|
||||||
try:
|
|
||||||
params = dict(name=name, namespace=namespace)
|
|
||||||
if merge_type:
|
|
||||||
params['content_type'] = 'application/{0}-patch+json'.format(merge_type)
|
|
||||||
k8s_obj = resource.patch(definition, **params).to_dict()
|
|
||||||
match, diffs = self.diff_objects(existing.to_dict(), k8s_obj)
|
|
||||||
error = {}
|
|
||||||
return k8s_obj, {}
|
|
||||||
except DynamicApiError as exc:
|
|
||||||
msg = "Failed to patch object: {0}".format(exc.body)
|
|
||||||
if self.warnings:
|
|
||||||
msg += "\n" + "\n ".join(self.warnings)
|
|
||||||
error = dict(msg=msg, error=exc.status, status=exc.status, reason=exc.reason, warnings=self.warnings)
|
|
||||||
return None, error
|
|
||||||
except Exception as exc:
|
|
||||||
msg = "Failed to patch object: {0}".format(exc)
|
|
||||||
if self.warnings:
|
|
||||||
msg += "\n" + "\n ".join(self.warnings)
|
|
||||||
error = dict(msg=msg, error=to_native(exc), status='', reason='', warnings=self.warnings)
|
|
||||||
return None, error
|
|
||||||
|
|
||||||
def create_project_request(self, definition):
|
|
||||||
definition['kind'] = 'ProjectRequest'
|
|
||||||
result = {'changed': False, 'result': {}}
|
|
||||||
resource = self.find_resource('ProjectRequest', definition['apiVersion'], fail=True)
|
|
||||||
if not self.check_mode:
|
|
||||||
try:
|
|
||||||
k8s_obj = resource.create(definition)
|
|
||||||
result['result'] = k8s_obj.to_dict()
|
|
||||||
except DynamicApiError as exc:
|
|
||||||
self.fail_json(msg="Failed to create object: {0}".format(exc.body),
|
|
||||||
error=exc.status, status=exc.status, reason=exc.reason)
|
|
||||||
result['changed'] = True
|
|
||||||
result['method'] = 'create'
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def _encode_stringdata(definition):
|
def _encode_stringdata(definition):
|
||||||
if definition['kind'] == 'Secret' and 'stringData' in definition:
|
if definition["kind"] == "Secret" and "stringData" in definition:
|
||||||
for k, v in definition['stringData'].items():
|
for k, v in definition["stringData"].items():
|
||||||
encoded = base64.b64encode(to_bytes(v))
|
encoded = base64.b64encode(to_bytes(v))
|
||||||
definition.setdefault('data', {})[k] = to_text(encoded)
|
definition.setdefault("data", {})[k] = to_text(encoded)
|
||||||
del definition['stringData']
|
del definition["stringData"]
|
||||||
return definition
|
return definition
|
||||||
|
|||||||
455
plugins/module_utils/copy.py
Normal file
455
plugins/module_utils/copy.py
Normal file
@@ -0,0 +1,455 @@
|
|||||||
|
# Copyright [2021] [Red Hat, Inc.]
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import os
|
||||||
|
import tarfile
|
||||||
|
from abc import ABCMeta, abstractmethod
|
||||||
|
from select import select
|
||||||
|
from tempfile import NamedTemporaryFile, TemporaryFile
|
||||||
|
|
||||||
|
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.k8s.exceptions import (
|
||||||
|
CoreException,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
from kubernetes.client.api import core_v1_api
|
||||||
|
from kubernetes.stream import stream
|
||||||
|
from kubernetes.stream.ws_client import (
|
||||||
|
ABNF,
|
||||||
|
ERROR_CHANNEL,
|
||||||
|
STDERR_CHANNEL,
|
||||||
|
STDOUT_CHANNEL,
|
||||||
|
)
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
import yaml
|
||||||
|
except ImportError:
|
||||||
|
# ImportError are managed by the common module already.
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class K8SCopy(metaclass=ABCMeta):
|
||||||
|
def __init__(self, module, client):
|
||||||
|
self.client = client
|
||||||
|
self.module = module
|
||||||
|
self.api_instance = core_v1_api.CoreV1Api(client.client)
|
||||||
|
|
||||||
|
self.local_path = module.params.get("local_path")
|
||||||
|
self.name = module.params.get("pod")
|
||||||
|
self.namespace = module.params.get("namespace")
|
||||||
|
self.remote_path = module.params.get("remote_path")
|
||||||
|
self.content = module.params.get("content")
|
||||||
|
|
||||||
|
self.no_preserve = module.params.get("no_preserve")
|
||||||
|
self.container_arg = {}
|
||||||
|
if module.params.get("container"):
|
||||||
|
self.container_arg["container"] = module.params.get("container")
|
||||||
|
self.check_mode = self.module.check_mode
|
||||||
|
|
||||||
|
def _run_from_pod(self, cmd):
|
||||||
|
try:
|
||||||
|
resp = stream(
|
||||||
|
self.api_instance.connect_get_namespaced_pod_exec,
|
||||||
|
self.name,
|
||||||
|
self.namespace,
|
||||||
|
command=cmd,
|
||||||
|
async_req=False,
|
||||||
|
stderr=True,
|
||||||
|
stdin=False,
|
||||||
|
stdout=True,
|
||||||
|
tty=False,
|
||||||
|
_preload_content=False,
|
||||||
|
**self.container_arg,
|
||||||
|
)
|
||||||
|
|
||||||
|
stderr, stdout = [], []
|
||||||
|
while resp.is_open():
|
||||||
|
resp.update(timeout=1)
|
||||||
|
if resp.peek_stdout():
|
||||||
|
stdout.extend(resp.read_stdout().rstrip("\n").split("\n"))
|
||||||
|
if resp.peek_stderr():
|
||||||
|
stderr.extend(resp.read_stderr().rstrip("\n").split("\n"))
|
||||||
|
error = resp.read_channel(ERROR_CHANNEL)
|
||||||
|
resp.close()
|
||||||
|
error = yaml.safe_load(error)
|
||||||
|
return error, stdout, stderr
|
||||||
|
except Exception as e:
|
||||||
|
self.module.fail_json(
|
||||||
|
msg="Error while running/parsing from pod {0}/{1} command='{2}' : {3}".format(
|
||||||
|
self.namespace, self.name, cmd, to_native(e)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def is_directory_path_from_pod(self, file_path, failed_if_not_exists=True):
|
||||||
|
# check if file exists
|
||||||
|
error, out, err = self._run_from_pod(cmd=["test", "-e", file_path])
|
||||||
|
if error.get("status") != "Success":
|
||||||
|
if failed_if_not_exists:
|
||||||
|
return None, "%s does not exist in remote pod filesystem" % file_path
|
||||||
|
return False, None
|
||||||
|
error, out, err = self._run_from_pod(cmd=["test", "-d", file_path])
|
||||||
|
return error.get("status") == "Success", None
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def run(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class K8SCopyFromPod(K8SCopy):
|
||||||
|
"""
|
||||||
|
Copy files/directory from Pod into local filesystem
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, module, client):
|
||||||
|
super(K8SCopyFromPod, self).__init__(module, client)
|
||||||
|
self.is_remote_path_dir = None
|
||||||
|
self.files_to_copy = []
|
||||||
|
self._shellname = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pod_shell(self):
|
||||||
|
if self._shellname is None:
|
||||||
|
for s in ("/bin/sh", "/bin/bash"):
|
||||||
|
error, out, err = self._run_from_pod(s)
|
||||||
|
if error.get("status") == "Success":
|
||||||
|
self._shellname = s
|
||||||
|
break
|
||||||
|
return self._shellname
|
||||||
|
|
||||||
|
def listfiles_with_find(self, path):
|
||||||
|
find_cmd = ["find", path, "-type", "f"]
|
||||||
|
error, files, err = self._run_from_pod(cmd=find_cmd)
|
||||||
|
if error.get("status") != "Success":
|
||||||
|
self.module.fail_json(msg=error.get("message"))
|
||||||
|
return files
|
||||||
|
|
||||||
|
def listfile_with_echo(self, path):
|
||||||
|
echo_cmd = [
|
||||||
|
self.pod_shell,
|
||||||
|
"-c",
|
||||||
|
"echo {path}/* {path}/.*".format(
|
||||||
|
path=path.translate(str.maketrans({" ": r"\ "}))
|
||||||
|
),
|
||||||
|
]
|
||||||
|
error, out, err = self._run_from_pod(cmd=echo_cmd)
|
||||||
|
if error.get("status") != "Success":
|
||||||
|
self.module.fail_json(msg=error.get("message"))
|
||||||
|
|
||||||
|
files = []
|
||||||
|
if out:
|
||||||
|
output = out[0] + " "
|
||||||
|
files = [
|
||||||
|
os.path.join(path, p[:-1])
|
||||||
|
for p in output.split(f"{path}/")
|
||||||
|
if p and p[:-1] not in (".", "..")
|
||||||
|
]
|
||||||
|
|
||||||
|
result = []
|
||||||
|
for f in files:
|
||||||
|
is_dir, err = self.is_directory_path_from_pod(f)
|
||||||
|
if err:
|
||||||
|
continue
|
||||||
|
if not is_dir:
|
||||||
|
result.append(f)
|
||||||
|
continue
|
||||||
|
result += self.listfile_with_echo(f)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def list_remote_files(self):
|
||||||
|
"""
|
||||||
|
This method will check if the remote path is a dir or file
|
||||||
|
if it is a directory the file list will be updated accordingly
|
||||||
|
"""
|
||||||
|
# check is remote path exists and is a file or directory
|
||||||
|
is_dir, error = self.is_directory_path_from_pod(self.remote_path)
|
||||||
|
if error:
|
||||||
|
self.module.fail_json(msg=error)
|
||||||
|
|
||||||
|
if not is_dir:
|
||||||
|
return [self.remote_path]
|
||||||
|
else:
|
||||||
|
# find executable to list dir with
|
||||||
|
executables = dict(
|
||||||
|
find=self.listfiles_with_find,
|
||||||
|
echo=self.listfile_with_echo,
|
||||||
|
)
|
||||||
|
for item in executables:
|
||||||
|
error, out, err = self._run_from_pod(item)
|
||||||
|
if error.get("status") == "Success":
|
||||||
|
return executables.get(item)(self.remote_path)
|
||||||
|
|
||||||
|
def read(self):
|
||||||
|
self.stdout = None
|
||||||
|
self.stderr = None
|
||||||
|
|
||||||
|
if self.response.is_open():
|
||||||
|
if not self.response.sock.connected:
|
||||||
|
self.response._connected = False
|
||||||
|
else:
|
||||||
|
ret, out, err = select((self.response.sock.sock,), (), (), 0)
|
||||||
|
if ret:
|
||||||
|
code, frame = self.response.sock.recv_data_frame(True)
|
||||||
|
if code == ABNF.OPCODE_CLOSE:
|
||||||
|
self.response._connected = False
|
||||||
|
elif (
|
||||||
|
code in (ABNF.OPCODE_BINARY, ABNF.OPCODE_TEXT)
|
||||||
|
and len(frame.data) > 1
|
||||||
|
):
|
||||||
|
channel = frame.data[0]
|
||||||
|
content = frame.data[1:]
|
||||||
|
if content:
|
||||||
|
if channel == STDOUT_CHANNEL:
|
||||||
|
self.stdout = content
|
||||||
|
elif channel == STDERR_CHANNEL:
|
||||||
|
self.stderr = content.decode("utf-8", "replace")
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
is_remote_path_dir = (
|
||||||
|
len(self.files_to_copy) > 1 or self.files_to_copy[0] != self.remote_path
|
||||||
|
)
|
||||||
|
relpath_start = self.remote_path
|
||||||
|
if is_remote_path_dir and os.path.isdir(self.local_path):
|
||||||
|
relpath_start = os.path.dirname(self.remote_path)
|
||||||
|
|
||||||
|
if not self.check_mode:
|
||||||
|
for remote_file in self.files_to_copy:
|
||||||
|
dest_file = self.local_path
|
||||||
|
if is_remote_path_dir:
|
||||||
|
dest_file = os.path.join(
|
||||||
|
self.local_path,
|
||||||
|
os.path.relpath(remote_file, start=relpath_start),
|
||||||
|
)
|
||||||
|
# create directory to copy file in
|
||||||
|
os.makedirs(os.path.dirname(dest_file), exist_ok=True)
|
||||||
|
|
||||||
|
pod_command = ["cat", remote_file]
|
||||||
|
self.response = stream(
|
||||||
|
self.api_instance.connect_get_namespaced_pod_exec,
|
||||||
|
self.name,
|
||||||
|
self.namespace,
|
||||||
|
command=pod_command,
|
||||||
|
stderr=True,
|
||||||
|
stdin=True,
|
||||||
|
stdout=True,
|
||||||
|
tty=False,
|
||||||
|
_preload_content=False,
|
||||||
|
**self.container_arg,
|
||||||
|
)
|
||||||
|
errors = []
|
||||||
|
with open(dest_file, "wb") as fh:
|
||||||
|
while self.response._connected:
|
||||||
|
self.read()
|
||||||
|
if self.stdout:
|
||||||
|
fh.write(self.stdout)
|
||||||
|
if self.stderr:
|
||||||
|
errors.append(self.stderr)
|
||||||
|
if errors:
|
||||||
|
self.module.fail_json(
|
||||||
|
msg="Failed to copy file from Pod: {0}".format("".join(errors))
|
||||||
|
)
|
||||||
|
self.module.exit_json(
|
||||||
|
changed=True,
|
||||||
|
result="{0} successfully copied locally into {1}".format(
|
||||||
|
self.remote_path, self.local_path
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.files_to_copy = self.list_remote_files()
|
||||||
|
if self.files_to_copy == []:
|
||||||
|
self.module.exit_json(
|
||||||
|
changed=False,
|
||||||
|
warning="No file found from directory '{0}' into remote Pod.".format(
|
||||||
|
self.remote_path
|
||||||
|
),
|
||||||
|
)
|
||||||
|
self.copy()
|
||||||
|
|
||||||
|
|
||||||
|
class K8SCopyToPod(K8SCopy):
|
||||||
|
"""
|
||||||
|
Copy files/directory from local filesystem into remote Pod
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, module, client):
|
||||||
|
super(K8SCopyToPod, self).__init__(module, client)
|
||||||
|
self.files_to_copy = list()
|
||||||
|
|
||||||
|
def close_temp_file(self):
|
||||||
|
if self.named_temp_file:
|
||||||
|
self.named_temp_file.close()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
# remove trailing slash from destination path
|
||||||
|
dest_file = self.remote_path.rstrip("/")
|
||||||
|
src_file = self.local_path
|
||||||
|
self.named_temp_file = None
|
||||||
|
if self.content:
|
||||||
|
self.named_temp_file = NamedTemporaryFile(mode="w")
|
||||||
|
self.named_temp_file.write(self.content)
|
||||||
|
self.named_temp_file.flush()
|
||||||
|
src_file = self.named_temp_file.name
|
||||||
|
else:
|
||||||
|
if not os.path.exists(self.local_path):
|
||||||
|
self.module.fail_json(
|
||||||
|
msg="{0} does not exist in local filesystem".format(self.local_path)
|
||||||
|
)
|
||||||
|
if not os.access(self.local_path, os.R_OK):
|
||||||
|
self.module.fail_json(msg="{0} not readable".format(self.local_path))
|
||||||
|
|
||||||
|
is_dir, err = self.is_directory_path_from_pod(
|
||||||
|
self.remote_path, failed_if_not_exists=False
|
||||||
|
)
|
||||||
|
if err:
|
||||||
|
self.module.fail_json(msg=err)
|
||||||
|
if is_dir:
|
||||||
|
if self.content:
|
||||||
|
self.module.fail_json(
|
||||||
|
msg="When content is specified, remote path should not be an existing directory"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
dest_file = os.path.join(dest_file, os.path.basename(src_file))
|
||||||
|
|
||||||
|
if not self.check_mode:
|
||||||
|
if self.no_preserve:
|
||||||
|
tar_command = [
|
||||||
|
"tar",
|
||||||
|
"--no-same-permissions",
|
||||||
|
"--no-same-owner",
|
||||||
|
"-xmf",
|
||||||
|
"-",
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
tar_command = ["tar", "-xmf", "-"]
|
||||||
|
|
||||||
|
if dest_file.startswith("/"):
|
||||||
|
tar_command.extend(["-C", "/"])
|
||||||
|
|
||||||
|
response = stream(
|
||||||
|
self.api_instance.connect_get_namespaced_pod_exec,
|
||||||
|
self.name,
|
||||||
|
self.namespace,
|
||||||
|
command=tar_command,
|
||||||
|
stderr=True,
|
||||||
|
stdin=True,
|
||||||
|
stdout=True,
|
||||||
|
tty=False,
|
||||||
|
_preload_content=False,
|
||||||
|
**self.container_arg,
|
||||||
|
)
|
||||||
|
with TemporaryFile() as tar_buffer:
|
||||||
|
with tarfile.open(fileobj=tar_buffer, mode="w") as tar:
|
||||||
|
tar.add(src_file, dest_file)
|
||||||
|
tar_buffer.seek(0)
|
||||||
|
commands = []
|
||||||
|
# push command in chunk mode
|
||||||
|
size = 1024 * 1024
|
||||||
|
while True:
|
||||||
|
data = tar_buffer.read(size)
|
||||||
|
if not data:
|
||||||
|
break
|
||||||
|
commands.append(data)
|
||||||
|
|
||||||
|
stderr, stdout = [], []
|
||||||
|
while response.is_open():
|
||||||
|
if response.peek_stdout():
|
||||||
|
stdout.append(response.read_stdout().rstrip("\n"))
|
||||||
|
if response.peek_stderr():
|
||||||
|
stderr.append(response.read_stderr().rstrip("\n"))
|
||||||
|
if commands:
|
||||||
|
cmd = commands.pop(0)
|
||||||
|
response.write_stdin(cmd)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
response.close()
|
||||||
|
if stderr:
|
||||||
|
self.close_temp_file()
|
||||||
|
self.module.fail_json(
|
||||||
|
command=tar_command,
|
||||||
|
msg="Failed to copy local file/directory into Pod due to: {0}".format(
|
||||||
|
"".join(stderr)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
self.close_temp_file()
|
||||||
|
if self.content:
|
||||||
|
self.module.exit_json(
|
||||||
|
changed=True,
|
||||||
|
result="Content successfully copied into {0} on remote Pod".format(
|
||||||
|
self.remote_path
|
||||||
|
),
|
||||||
|
)
|
||||||
|
self.module.exit_json(
|
||||||
|
changed=True,
|
||||||
|
result="{0} successfully copied into remote Pod into {1}".format(
|
||||||
|
self.local_path, self.remote_path
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def check_pod(svc):
|
||||||
|
module = svc.module
|
||||||
|
namespace = module.params.get("namespace")
|
||||||
|
name = module.params.get("pod")
|
||||||
|
container = module.params.get("container")
|
||||||
|
|
||||||
|
try:
|
||||||
|
resource = svc.find_resource("Pod", None, True)
|
||||||
|
except CoreException as e:
|
||||||
|
module.fail_json(msg=to_native(e))
|
||||||
|
|
||||||
|
def _fail(exc):
|
||||||
|
arg = {}
|
||||||
|
if hasattr(exc, "body"):
|
||||||
|
msg = (
|
||||||
|
"Namespace={0} Kind=Pod Name={1}: Failed requested object: {2}".format(
|
||||||
|
namespace, name, exc.body
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
msg = to_native(exc)
|
||||||
|
for attr in ["status", "reason"]:
|
||||||
|
if hasattr(exc, attr):
|
||||||
|
arg[attr] = getattr(exc, attr)
|
||||||
|
module.fail_json(msg=msg, **arg)
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = svc.client.get(resource, name=name, namespace=namespace)
|
||||||
|
containers = dict(
|
||||||
|
{
|
||||||
|
c["name"]: c
|
||||||
|
for cl in ["initContainerStatuses", "containerStatuses"]
|
||||||
|
for c in result.to_dict()["status"].get(cl, [])
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if container and container not in containers.keys():
|
||||||
|
module.fail_json(msg="Pod has no container {0}".format(container))
|
||||||
|
if (
|
||||||
|
container
|
||||||
|
and container in containers
|
||||||
|
and not bool(containers[container].get("started", False))
|
||||||
|
):
|
||||||
|
module.fail_json(msg="Pod container {0} is not started".format(container))
|
||||||
|
return containers.keys()
|
||||||
|
except Exception as exc:
|
||||||
|
_fail(exc)
|
||||||
@@ -14,8 +14,9 @@
|
|||||||
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
class ApplyException(Exception):
|
class ApplyException(Exception):
|
||||||
""" Could not apply patch """
|
"""Could not apply patch"""
|
||||||
|
|||||||
@@ -15,14 +15,16 @@
|
|||||||
# Implement ConfigMapHash and SecretHash equivalents
|
# Implement ConfigMapHash and SecretHash equivalents
|
||||||
# Based on https://github.com/kubernetes/kubernetes/pull/49961
|
# Based on https://github.com/kubernetes/kubernetes/pull/49961
|
||||||
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
import json
|
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import json
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import string
|
import string
|
||||||
|
|
||||||
maketrans = string.maketrans
|
maketrans = string.maketrans
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
maketrans = str.maketrans
|
maketrans = str.maketrans
|
||||||
@@ -35,7 +37,7 @@ except ImportError:
|
|||||||
|
|
||||||
def sorted_dict(unsorted_dict):
|
def sorted_dict(unsorted_dict):
|
||||||
result = OrderedDict()
|
result = OrderedDict()
|
||||||
for (k, v) in sorted(unsorted_dict.items()):
|
for k, v in sorted(unsorted_dict.items()):
|
||||||
if isinstance(v, dict):
|
if isinstance(v, dict):
|
||||||
v = sorted_dict(v)
|
v = sorted_dict(v)
|
||||||
result[k] = v
|
result[k] = v
|
||||||
@@ -44,14 +46,21 @@ def sorted_dict(unsorted_dict):
|
|||||||
|
|
||||||
def generate_hash(resource):
|
def generate_hash(resource):
|
||||||
# Get name from metadata
|
# Get name from metadata
|
||||||
resource['name'] = resource.get('metadata', {}).get('name', '')
|
metada = resource.get("metadata", {})
|
||||||
if resource['kind'] == 'ConfigMap':
|
key = "name"
|
||||||
marshalled = marshal(sorted_dict(resource), ['data', 'kind', 'name'])
|
resource["name"] = metada.get("name", "")
|
||||||
del(resource['name'])
|
generate_name = metada.get("generateName", "")
|
||||||
|
if resource["name"] == "" and generate_name:
|
||||||
|
del resource["name"]
|
||||||
|
key = "generateName"
|
||||||
|
resource["generateName"] = generate_name
|
||||||
|
if resource["kind"] == "ConfigMap":
|
||||||
|
marshalled = marshal(sorted_dict(resource), ["data", "kind", key])
|
||||||
|
del resource[key]
|
||||||
return encode(marshalled)
|
return encode(marshalled)
|
||||||
if resource['kind'] == 'Secret':
|
if resource["kind"] == "Secret":
|
||||||
marshalled = marshal(sorted_dict(resource), ['data', 'kind', 'name', 'type'])
|
marshalled = marshal(sorted_dict(resource), ["data", "kind", key, "type"])
|
||||||
del(resource['name'])
|
del resource[key]
|
||||||
return encode(marshalled)
|
return encode(marshalled)
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@@ -60,8 +69,10 @@ def marshal(data, keys):
|
|||||||
ordered = OrderedDict()
|
ordered = OrderedDict()
|
||||||
for key in keys:
|
for key in keys:
|
||||||
ordered[key] = data.get(key, "")
|
ordered[key] = data.get(key, "")
|
||||||
return json.dumps(ordered, separators=(',', ':')).encode('utf-8')
|
return json.dumps(ordered, separators=(",", ":")).encode("utf-8")
|
||||||
|
|
||||||
|
|
||||||
def encode(resource):
|
def encode(resource):
|
||||||
return hashlib.sha256(resource).hexdigest()[:10].translate(maketrans("013ae", "ghkmt"))
|
return (
|
||||||
|
hashlib.sha256(resource).hexdigest()[:10].translate(maketrans("013ae", "ghkmt"))
|
||||||
|
)
|
||||||
|
|||||||
@@ -7,138 +7,29 @@ from __future__ import absolute_import, division, print_function
|
|||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
from contextlib import contextmanager
|
import copy
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import tempfile
|
import tempfile
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from ansible.module_utils.basic import missing_required_lib
|
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
|
||||||
|
LooseVersion,
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
HAS_YAML = True
|
HAS_YAML = True
|
||||||
|
YAML_IMP_ERR = None
|
||||||
except ImportError:
|
except ImportError:
|
||||||
YAML_IMP_ERR = traceback.format_exc()
|
YAML_IMP_ERR = traceback.format_exc()
|
||||||
HAS_YAML = False
|
HAS_YAML = False
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
def parse_helm_plugin_list(output=None):
|
||||||
def prepare_helm_environ_update(module):
|
|
||||||
environ_update = {}
|
|
||||||
file_to_cleam_up = None
|
|
||||||
kubeconfig_path = module.params.get('kubeconfig')
|
|
||||||
if module.params.get('context') is not None:
|
|
||||||
environ_update["HELM_KUBECONTEXT"] = module.params.get('context')
|
|
||||||
if module.params.get('release_namespace'):
|
|
||||||
environ_update["HELM_NAMESPACE"] = module.params.get('release_namespace')
|
|
||||||
if module.params.get("api_key"):
|
|
||||||
environ_update["HELM_KUBETOKEN"] = module.params["api_key"]
|
|
||||||
if module.params.get("host"):
|
|
||||||
environ_update["HELM_KUBEAPISERVER"] = module.params["host"]
|
|
||||||
if module.params.get("validate_certs") is False or module.params.get("ca_cert"):
|
|
||||||
kubeconfig_path = write_temp_kubeconfig(
|
|
||||||
module.params["host"],
|
|
||||||
validate_certs=module.params["validate_certs"],
|
|
||||||
ca_cert=module.params["ca_cert"])
|
|
||||||
file_to_cleam_up = kubeconfig_path
|
|
||||||
if kubeconfig_path is not None:
|
|
||||||
environ_update["KUBECONFIG"] = kubeconfig_path
|
|
||||||
|
|
||||||
try:
|
|
||||||
yield environ_update
|
|
||||||
finally:
|
|
||||||
if file_to_cleam_up:
|
|
||||||
os.remove(file_to_cleam_up)
|
|
||||||
|
|
||||||
|
|
||||||
def run_helm(module, command, fails_on_error=True):
|
|
||||||
if not HAS_YAML:
|
|
||||||
module.fail_json(msg=missing_required_lib("PyYAML"), exception=YAML_IMP_ERR)
|
|
||||||
|
|
||||||
with prepare_helm_environ_update(module) as environ_update:
|
|
||||||
rc, out, err = module.run_command(command, environ_update=environ_update)
|
|
||||||
if fails_on_error and rc != 0:
|
|
||||||
module.fail_json(
|
|
||||||
msg="Failure when executing Helm command. Exited {0}.\nstdout: {1}\nstderr: {2}".format(rc, out, err),
|
|
||||||
stdout=out,
|
|
||||||
stderr=err,
|
|
||||||
command=command,
|
|
||||||
)
|
|
||||||
return rc, out, err
|
|
||||||
|
|
||||||
|
|
||||||
def get_values(module, command, release_name):
|
|
||||||
"""
|
|
||||||
Get Values from deployed release
|
|
||||||
"""
|
|
||||||
if not HAS_YAML:
|
|
||||||
module.fail_json(msg=missing_required_lib("PyYAML"), exception=YAML_IMP_ERR)
|
|
||||||
|
|
||||||
get_command = command + " get values --output=yaml " + release_name
|
|
||||||
|
|
||||||
rc, out, err = run_helm(module, get_command)
|
|
||||||
# Helm 3 return "null" string when no values are set
|
|
||||||
if out.rstrip("\n") == "null":
|
|
||||||
return {}
|
|
||||||
return yaml.safe_load(out)
|
|
||||||
|
|
||||||
|
|
||||||
def write_temp_kubeconfig(server, validate_certs=True, ca_cert=None):
|
|
||||||
# Workaround until https://github.com/helm/helm/pull/8622 is merged
|
|
||||||
content = {
|
|
||||||
"apiVersion": "v1",
|
|
||||||
"kind": "Config",
|
|
||||||
"clusters": [
|
|
||||||
{
|
|
||||||
"cluster": {
|
|
||||||
"server": server,
|
|
||||||
},
|
|
||||||
"name": "generated-cluster"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"contexts": [
|
|
||||||
{
|
|
||||||
"context": {
|
|
||||||
"cluster": "generated-cluster"
|
|
||||||
},
|
|
||||||
"name": "generated-context"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"current-context": "generated-context"
|
|
||||||
}
|
|
||||||
|
|
||||||
if not validate_certs:
|
|
||||||
content["clusters"][0]["cluster"]["insecure-skip-tls-verify"] = True
|
|
||||||
if ca_cert:
|
|
||||||
content["clusters"][0]["cluster"]["certificate-authority"] = ca_cert
|
|
||||||
|
|
||||||
_fd, file_name = tempfile.mkstemp()
|
|
||||||
with os.fdopen(_fd, 'w') as fp:
|
|
||||||
yaml.dump(content, fp)
|
|
||||||
return file_name
|
|
||||||
|
|
||||||
|
|
||||||
def get_helm_plugin_list(module, helm_bin=None):
|
|
||||||
"""
|
|
||||||
Return `helm plugin list`
|
|
||||||
"""
|
|
||||||
if not helm_bin:
|
|
||||||
return []
|
|
||||||
helm_plugin_list = helm_bin + " list"
|
|
||||||
rc, out, err = run_helm(module, helm_plugin_list)
|
|
||||||
if rc != 0 or (out == '' and err == ''):
|
|
||||||
module.fail_json(
|
|
||||||
msg="Failed to get Helm plugin info",
|
|
||||||
command=helm_plugin_list,
|
|
||||||
stdout=out,
|
|
||||||
stderr=err,
|
|
||||||
rc=rc,
|
|
||||||
)
|
|
||||||
return (rc, out, err)
|
|
||||||
|
|
||||||
|
|
||||||
def parse_helm_plugin_list(module, output=None):
|
|
||||||
"""
|
"""
|
||||||
Parse `helm plugin list`, return list of plugins
|
Parse `helm plugin list`, return list of plugins
|
||||||
"""
|
"""
|
||||||
@@ -149,12 +40,258 @@ def parse_helm_plugin_list(module, output=None):
|
|||||||
for line in output:
|
for line in output:
|
||||||
if line.startswith("NAME"):
|
if line.startswith("NAME"):
|
||||||
continue
|
continue
|
||||||
name, version, description = line.split('\t', 3)
|
name, version, description = line.split("\t", 3)
|
||||||
name = name.strip()
|
name = name.strip()
|
||||||
version = version.strip()
|
version = version.strip()
|
||||||
description = description.strip()
|
description = description.strip()
|
||||||
if name == '':
|
if name == "":
|
||||||
continue
|
continue
|
||||||
ret.append((name, version, description))
|
ret.append((name, version, description))
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def write_temp_kubeconfig(server, validate_certs=True, ca_cert=None, kubeconfig=None):
|
||||||
|
# Workaround until https://github.com/helm/helm/pull/8622 is merged
|
||||||
|
content = {
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "Config",
|
||||||
|
"clusters": [{"cluster": {"server": server}, "name": "generated-cluster"}],
|
||||||
|
"contexts": [
|
||||||
|
{"context": {"cluster": "generated-cluster"}, "name": "generated-context"}
|
||||||
|
],
|
||||||
|
"current-context": "generated-context",
|
||||||
|
}
|
||||||
|
if kubeconfig:
|
||||||
|
content = copy.deepcopy(kubeconfig)
|
||||||
|
|
||||||
|
for cluster in content["clusters"]:
|
||||||
|
if server:
|
||||||
|
cluster["cluster"]["server"] = server
|
||||||
|
if not validate_certs:
|
||||||
|
cluster["cluster"]["insecure-skip-tls-verify"] = True
|
||||||
|
if ca_cert:
|
||||||
|
cluster["cluster"]["certificate-authority"] = ca_cert
|
||||||
|
return content
|
||||||
|
|
||||||
|
|
||||||
|
class AnsibleHelmModule(object):
|
||||||
|
"""
|
||||||
|
An Ansible module class for Kubernetes.core helm modules
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
self._module = None
|
||||||
|
if "module" in kwargs:
|
||||||
|
self._module = kwargs.get("module")
|
||||||
|
else:
|
||||||
|
self._module = AnsibleModule(**kwargs)
|
||||||
|
|
||||||
|
self.helm_env = None
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
return getattr(self._module, name)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def params(self):
|
||||||
|
return self._module.params
|
||||||
|
|
||||||
|
def _prepare_helm_environment(self):
|
||||||
|
param_to_env_mapping = [
|
||||||
|
("context", "HELM_KUBECONTEXT"),
|
||||||
|
("release_namespace", "HELM_NAMESPACE"),
|
||||||
|
("api_key", "HELM_KUBETOKEN"),
|
||||||
|
("host", "HELM_KUBEAPISERVER"),
|
||||||
|
]
|
||||||
|
|
||||||
|
env_update = {}
|
||||||
|
for p, env in param_to_env_mapping:
|
||||||
|
if self.params.get(p):
|
||||||
|
env_update[env] = self.params.get(p)
|
||||||
|
|
||||||
|
kubeconfig_content = None
|
||||||
|
kubeconfig = self.params.get("kubeconfig")
|
||||||
|
if kubeconfig:
|
||||||
|
if isinstance(kubeconfig, str):
|
||||||
|
with open(os.path.expanduser(kubeconfig)) as fd:
|
||||||
|
kubeconfig_content = yaml.safe_load(fd)
|
||||||
|
elif isinstance(kubeconfig, dict):
|
||||||
|
kubeconfig_content = kubeconfig
|
||||||
|
|
||||||
|
if self.params.get("ca_cert"):
|
||||||
|
ca_cert = self.params.get("ca_cert")
|
||||||
|
if LooseVersion(self.get_helm_version()) < LooseVersion("3.5.0"):
|
||||||
|
# update certs from kubeconfig
|
||||||
|
kubeconfig_content = write_temp_kubeconfig(
|
||||||
|
server=self.params.get("host"),
|
||||||
|
ca_cert=ca_cert,
|
||||||
|
kubeconfig=kubeconfig_content,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
env_update["HELM_KUBECAFILE"] = ca_cert
|
||||||
|
|
||||||
|
if self.params.get("validate_certs") is False:
|
||||||
|
validate_certs = self.params.get("validate_certs")
|
||||||
|
if LooseVersion(self.get_helm_version()) < LooseVersion("3.10.0"):
|
||||||
|
# update certs from kubeconfig
|
||||||
|
kubeconfig_content = write_temp_kubeconfig(
|
||||||
|
server=self.params.get("host"),
|
||||||
|
validate_certs=validate_certs,
|
||||||
|
kubeconfig=kubeconfig_content,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
env_update["HELM_KUBEINSECURE_SKIP_TLS_VERIFY"] = "true"
|
||||||
|
|
||||||
|
if kubeconfig_content:
|
||||||
|
fd, kubeconfig_path = tempfile.mkstemp()
|
||||||
|
with os.fdopen(fd, "w") as fp:
|
||||||
|
json.dump(kubeconfig_content, fp)
|
||||||
|
|
||||||
|
env_update["KUBECONFIG"] = kubeconfig_path
|
||||||
|
self.add_cleanup_file(kubeconfig_path)
|
||||||
|
|
||||||
|
return env_update
|
||||||
|
|
||||||
|
@property
|
||||||
|
def env_update(self):
|
||||||
|
if self.helm_env is None:
|
||||||
|
self.helm_env = self._prepare_helm_environment()
|
||||||
|
return self.helm_env
|
||||||
|
|
||||||
|
def run_helm_command(self, command, fails_on_error=True, data=None):
|
||||||
|
if not HAS_YAML:
|
||||||
|
self.fail_json(msg=missing_required_lib("PyYAML"), exception=YAML_IMP_ERR)
|
||||||
|
|
||||||
|
rc, out, err = self.run_command(
|
||||||
|
command, environ_update=self.env_update, data=data
|
||||||
|
)
|
||||||
|
if fails_on_error and rc != 0:
|
||||||
|
self.fail_json(
|
||||||
|
msg="Failure when executing Helm command. Exited {0}.\nstdout: {1}\nstderr: {2}".format(
|
||||||
|
rc, out, err
|
||||||
|
),
|
||||||
|
stdout=out,
|
||||||
|
stderr=err,
|
||||||
|
command=command,
|
||||||
|
)
|
||||||
|
return rc, out, err
|
||||||
|
|
||||||
|
def get_helm_binary(self):
|
||||||
|
return self.params.get("binary_path") or self.get_bin_path(
|
||||||
|
"helm", required=True
|
||||||
|
)
|
||||||
|
|
||||||
|
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)
|
||||||
|
if m:
|
||||||
|
return m.group(1)
|
||||||
|
m = re.match(r'Client: &version.Version{SemVer:"v(.*?)", ', out)
|
||||||
|
if m:
|
||||||
|
return m.group(1)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_values(self, release_name, get_all=False):
|
||||||
|
"""
|
||||||
|
Get Values from deployed release
|
||||||
|
"""
|
||||||
|
if not HAS_YAML:
|
||||||
|
self.fail_json(msg=missing_required_lib("PyYAML"), exception=YAML_IMP_ERR)
|
||||||
|
|
||||||
|
get_command = (
|
||||||
|
self.get_helm_binary() + " get values --output=yaml " + release_name
|
||||||
|
)
|
||||||
|
|
||||||
|
if get_all:
|
||||||
|
get_command += " -a"
|
||||||
|
|
||||||
|
rc, out, err = self.run_helm_command(get_command)
|
||||||
|
# Helm 3 return "null" string when no values are set
|
||||||
|
if out.rstrip("\n") == "null":
|
||||||
|
return {}
|
||||||
|
return yaml.safe_load(out)
|
||||||
|
|
||||||
|
def parse_yaml_content(self, content):
|
||||||
|
if not HAS_YAML:
|
||||||
|
self.fail_json(msg=missing_required_lib("yaml"), exception=HAS_YAML)
|
||||||
|
|
||||||
|
try:
|
||||||
|
return list(yaml.safe_load_all(content))
|
||||||
|
except (IOError, yaml.YAMLError) as exc:
|
||||||
|
self.fail_json(
|
||||||
|
msg="Error parsing YAML content: {0}".format(exc), raw_data=content
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_manifest(self, release_name):
|
||||||
|
command = [
|
||||||
|
self.get_helm_binary(),
|
||||||
|
"get",
|
||||||
|
"manifest",
|
||||||
|
release_name,
|
||||||
|
]
|
||||||
|
rc, out, err = self.run_helm_command(" ".join(command))
|
||||||
|
if rc != 0:
|
||||||
|
self.fail_json(msg=err)
|
||||||
|
return self.parse_yaml_content(out)
|
||||||
|
|
||||||
|
def get_notes(self, release_name):
|
||||||
|
command = [
|
||||||
|
self.get_helm_binary(),
|
||||||
|
"get",
|
||||||
|
"notes",
|
||||||
|
release_name,
|
||||||
|
]
|
||||||
|
rc, out, err = self.run_helm_command(" ".join(command))
|
||||||
|
if rc != 0:
|
||||||
|
self.fail_json(msg=err)
|
||||||
|
return out
|
||||||
|
|
||||||
|
def get_hooks(self, release_name):
|
||||||
|
command = [
|
||||||
|
self.get_helm_binary(),
|
||||||
|
"get",
|
||||||
|
"hooks",
|
||||||
|
release_name,
|
||||||
|
]
|
||||||
|
rc, out, err = self.run_helm_command(" ".join(command))
|
||||||
|
if rc != 0:
|
||||||
|
self.fail_json(msg=err)
|
||||||
|
return self.parse_yaml_content(out)
|
||||||
|
|
||||||
|
def get_helm_plugin_list(self):
|
||||||
|
"""
|
||||||
|
Return `helm plugin list`
|
||||||
|
"""
|
||||||
|
helm_plugin_list = self.get_helm_binary() + " plugin list"
|
||||||
|
rc, out, err = self.run_helm_command(helm_plugin_list)
|
||||||
|
if rc != 0 or (out == "" and err == ""):
|
||||||
|
self.fail_json(
|
||||||
|
msg="Failed to get Helm plugin info",
|
||||||
|
command=helm_plugin_list,
|
||||||
|
stdout=out,
|
||||||
|
stderr=err,
|
||||||
|
rc=rc,
|
||||||
|
)
|
||||||
|
return (rc, out, err, helm_plugin_list)
|
||||||
|
|
||||||
|
def get_helm_set_values_args(self, set_values):
|
||||||
|
if any(v.get("value_type") == "json" for v in set_values):
|
||||||
|
if LooseVersion(self.get_helm_version()) < LooseVersion("3.10.0"):
|
||||||
|
self.fail_json(
|
||||||
|
msg="This module requires helm >= 3.10.0, to use set_values parameter with value type set to 'json'. current version is {0}".format(
|
||||||
|
self.get_helm_version()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
options = []
|
||||||
|
for opt in set_values:
|
||||||
|
value_type = opt.get("value_type", "raw")
|
||||||
|
value = opt.get("value")
|
||||||
|
|
||||||
|
if value_type == "raw":
|
||||||
|
options.append("--set " + value)
|
||||||
|
else:
|
||||||
|
options.append("--set-{0} '{1}'".format(value_type, value))
|
||||||
|
|
||||||
|
return " ".join(options)
|
||||||
|
|||||||
43
plugins/module_utils/helm_args_common.py
Normal file
43
plugins/module_utils/helm_args_common.py
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
from ansible.module_utils.basic import env_fallback
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
|
HELM_AUTH_ARG_SPEC = dict(
|
||||||
|
binary_path=dict(type="path"),
|
||||||
|
context=dict(
|
||||||
|
type="str",
|
||||||
|
aliases=["kube_context"],
|
||||||
|
fallback=(env_fallback, ["K8S_AUTH_CONTEXT"]),
|
||||||
|
),
|
||||||
|
kubeconfig=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(
|
||||||
|
type="path",
|
||||||
|
aliases=["ssl_ca_cert"],
|
||||||
|
fallback=(env_fallback, ["K8S_AUTH_SSL_CA_CERT"]),
|
||||||
|
),
|
||||||
|
validate_certs=dict(
|
||||||
|
type="bool",
|
||||||
|
default=True,
|
||||||
|
aliases=["verify_ssl"],
|
||||||
|
fallback=(env_fallback, ["K8S_AUTH_VERIFY_SSL"]),
|
||||||
|
),
|
||||||
|
api_key=dict(
|
||||||
|
type="str",
|
||||||
|
no_log=True,
|
||||||
|
fallback=(env_fallback, ["K8S_AUTH_API_KEY"]),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
HELM_AUTH_MUTUALLY_EXCLUSIVE = [
|
||||||
|
("context", "ca_cert"),
|
||||||
|
("context", "validate_certs"),
|
||||||
|
]
|
||||||
366
plugins/module_utils/k8s/client.py
Normal file
366
plugins/module_utils/k8s/client.py
Normal file
@@ -0,0 +1,366 @@
|
|||||||
|
# Copyright: (c) 2021, Red Hat | Ansible
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import os
|
||||||
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.args_common import (
|
||||||
|
AUTH_ARG_MAP,
|
||||||
|
AUTH_ARG_SPEC,
|
||||||
|
AUTH_PROXY_HEADERS_SPEC,
|
||||||
|
)
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import (
|
||||||
|
requires as _requires,
|
||||||
|
)
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||||
|
CoreException,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils import (
|
||||||
|
k8sdynamicclient,
|
||||||
|
)
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.client.discovery import (
|
||||||
|
LazyDiscoverer,
|
||||||
|
)
|
||||||
|
except ImportError:
|
||||||
|
# Handled in module setup
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
import kubernetes
|
||||||
|
from kubernetes.dynamic.exceptions import (
|
||||||
|
ResourceNotFoundError,
|
||||||
|
ResourceNotUniqueError,
|
||||||
|
)
|
||||||
|
from kubernetes.dynamic.resource import Resource
|
||||||
|
except ImportError:
|
||||||
|
# kubernetes import error is handled in module setup
|
||||||
|
# This is defined only for the sake of Ansible's checked import requirement
|
||||||
|
Resource = Any # type: ignore
|
||||||
|
|
||||||
|
try:
|
||||||
|
import urllib3
|
||||||
|
|
||||||
|
urllib3.disable_warnings()
|
||||||
|
except ImportError:
|
||||||
|
# Handled in module setup
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
_pool = {}
|
||||||
|
|
||||||
|
|
||||||
|
class unique_string(str):
|
||||||
|
_low = None
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
return id(self)
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self is other
|
||||||
|
|
||||||
|
def lower(self):
|
||||||
|
if self._low is None:
|
||||||
|
lower = str.lower(self)
|
||||||
|
if str.__eq__(lower, self):
|
||||||
|
self._low = self
|
||||||
|
else:
|
||||||
|
self._low = unique_string(lower)
|
||||||
|
return self._low
|
||||||
|
|
||||||
|
|
||||||
|
def _create_auth_spec(module=None, **kwargs) -> Dict:
|
||||||
|
auth: Dict = {}
|
||||||
|
# If authorization variables aren't defined, look for them in environment variables
|
||||||
|
for true_name, arg_name in AUTH_ARG_MAP.items():
|
||||||
|
if module and module.params.get(arg_name) is not None:
|
||||||
|
auth[true_name] = module.params.get(arg_name)
|
||||||
|
elif arg_name in kwargs and kwargs.get(arg_name) is not None:
|
||||||
|
auth[true_name] = kwargs.get(arg_name)
|
||||||
|
elif true_name in kwargs and kwargs.get(true_name) is not None:
|
||||||
|
# Aliases in kwargs
|
||||||
|
auth[true_name] = kwargs.get(true_name)
|
||||||
|
elif arg_name == "proxy_headers":
|
||||||
|
# specific case for 'proxy_headers' which is a dictionary
|
||||||
|
proxy_headers = {}
|
||||||
|
for key in AUTH_PROXY_HEADERS_SPEC.keys():
|
||||||
|
env_value = os.getenv(
|
||||||
|
"K8S_AUTH_PROXY_HEADERS_{0}".format(key.upper()), None
|
||||||
|
)
|
||||||
|
if env_value is not None:
|
||||||
|
if AUTH_PROXY_HEADERS_SPEC[key].get("type") == "bool":
|
||||||
|
env_value = env_value.lower() not in ["0", "false", "no"]
|
||||||
|
proxy_headers[key] = env_value
|
||||||
|
if proxy_headers is not {}:
|
||||||
|
auth[true_name] = proxy_headers
|
||||||
|
else:
|
||||||
|
env_value = os.getenv(
|
||||||
|
"K8S_AUTH_{0}".format(arg_name.upper()), None
|
||||||
|
) or os.getenv("K8S_AUTH_{0}".format(true_name.upper()), None)
|
||||||
|
if env_value is not None:
|
||||||
|
if AUTH_ARG_SPEC[arg_name].get("type") == "bool":
|
||||||
|
env_value = env_value.lower() not in ["0", "false", "no"]
|
||||||
|
auth[true_name] = env_value
|
||||||
|
|
||||||
|
return auth
|
||||||
|
|
||||||
|
|
||||||
|
def _load_config(auth: Dict) -> None:
|
||||||
|
kubeconfig = auth.get("kubeconfig")
|
||||||
|
optional_arg = {
|
||||||
|
"context": auth.get("context"),
|
||||||
|
"persist_config": auth.get("persist_config"),
|
||||||
|
}
|
||||||
|
if kubeconfig:
|
||||||
|
if isinstance(kubeconfig, str):
|
||||||
|
kubernetes.config.load_kube_config(config_file=kubeconfig, **optional_arg)
|
||||||
|
elif isinstance(kubeconfig, dict):
|
||||||
|
kubernetes.config.load_kube_config_from_dict(
|
||||||
|
config_dict=kubeconfig, **optional_arg
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
kubernetes.config.load_kube_config(config_file=None, **optional_arg)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_configuration(auth: Dict):
|
||||||
|
def auth_set(*names: list) -> bool:
|
||||||
|
return all(auth.get(name) for name in names)
|
||||||
|
|
||||||
|
if auth_set("host"):
|
||||||
|
# Removing trailing slashes if any from hostname
|
||||||
|
auth["host"] = auth.get("host").rstrip("/")
|
||||||
|
|
||||||
|
if (
|
||||||
|
auth_set("username", "password", "host")
|
||||||
|
or auth_set("api_key", "host")
|
||||||
|
or auth_set("cert_file", "key_file", "host")
|
||||||
|
):
|
||||||
|
# We have enough in the parameters to authenticate, no need to load incluster or kubeconfig
|
||||||
|
pass
|
||||||
|
elif auth_set("kubeconfig") or auth_set("context"):
|
||||||
|
try:
|
||||||
|
_load_config(auth)
|
||||||
|
except Exception as err:
|
||||||
|
raise err
|
||||||
|
|
||||||
|
else:
|
||||||
|
# First try to do incluster config, then kubeconfig
|
||||||
|
try:
|
||||||
|
kubernetes.config.load_incluster_config()
|
||||||
|
except kubernetes.config.ConfigException:
|
||||||
|
try:
|
||||||
|
_load_config(auth)
|
||||||
|
except Exception as err:
|
||||||
|
raise err
|
||||||
|
|
||||||
|
# Override any values in the default configuration with Ansible parameters
|
||||||
|
# As of kubernetes-client v12.0.0, get_default_copy() is required here
|
||||||
|
try:
|
||||||
|
configuration = kubernetes.client.Configuration().get_default_copy()
|
||||||
|
except AttributeError:
|
||||||
|
configuration = kubernetes.client.Configuration()
|
||||||
|
|
||||||
|
for key, value in auth.items():
|
||||||
|
if key in AUTH_ARG_MAP.keys() and value is not None:
|
||||||
|
if key == "api_key":
|
||||||
|
setattr(
|
||||||
|
configuration, key, {"authorization": "Bearer {0}".format(value)}
|
||||||
|
)
|
||||||
|
elif key == "proxy_headers":
|
||||||
|
headers = urllib3.util.make_headers(**value)
|
||||||
|
setattr(configuration, key, headers)
|
||||||
|
else:
|
||||||
|
setattr(configuration, key, value)
|
||||||
|
|
||||||
|
return configuration
|
||||||
|
|
||||||
|
|
||||||
|
def _create_headers(module=None, **kwargs):
|
||||||
|
header_map = {
|
||||||
|
"impersonate_user": "Impersonate-User",
|
||||||
|
"impersonate_groups": "Impersonate-Group",
|
||||||
|
}
|
||||||
|
|
||||||
|
headers = {}
|
||||||
|
for arg_name, header_name in header_map.items():
|
||||||
|
value = None
|
||||||
|
if module and module.params.get(arg_name) is not None:
|
||||||
|
value = module.params.get(arg_name)
|
||||||
|
elif arg_name in kwargs and kwargs.get(arg_name) is not None:
|
||||||
|
value = kwargs.get(arg_name)
|
||||||
|
else:
|
||||||
|
value = os.getenv("K8S_AUTH_{0}".format(arg_name.upper()), None)
|
||||||
|
if value is not None:
|
||||||
|
if AUTH_ARG_SPEC[arg_name].get("type") == "list":
|
||||||
|
value = [x for x in value.split(",") if x != ""]
|
||||||
|
if value:
|
||||||
|
headers[header_name] = value
|
||||||
|
return headers
|
||||||
|
|
||||||
|
|
||||||
|
def _configuration_digest(configuration, **kwargs) -> str:
|
||||||
|
m = hashlib.sha256()
|
||||||
|
for k in AUTH_ARG_MAP:
|
||||||
|
if not hasattr(configuration, k):
|
||||||
|
v = None
|
||||||
|
else:
|
||||||
|
v = getattr(configuration, k)
|
||||||
|
if v and k in ["ssl_ca_cert", "cert_file", "key_file"]:
|
||||||
|
with open(str(v), "r") as fd:
|
||||||
|
content = fd.read()
|
||||||
|
m.update(content.encode())
|
||||||
|
else:
|
||||||
|
m.update(str(v).encode())
|
||||||
|
for k, v in kwargs.items():
|
||||||
|
content = "{0}: {1}".format(k, v)
|
||||||
|
m.update(content.encode())
|
||||||
|
digest = m.hexdigest()
|
||||||
|
|
||||||
|
return digest
|
||||||
|
|
||||||
|
|
||||||
|
def _set_header(client, header, value):
|
||||||
|
if isinstance(value, list):
|
||||||
|
for v in value:
|
||||||
|
client.set_default_header(header_name=unique_string(header), header_value=v)
|
||||||
|
else:
|
||||||
|
client.set_default_header(header_name=header, header_value=value)
|
||||||
|
|
||||||
|
|
||||||
|
def cache(func):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
client = None
|
||||||
|
hashable_kwargs = {}
|
||||||
|
for k, v in kwargs.items():
|
||||||
|
if isinstance(v, list):
|
||||||
|
hashable_kwargs[k] = ",".join(sorted(v))
|
||||||
|
else:
|
||||||
|
hashable_kwargs[k] = v
|
||||||
|
digest = _configuration_digest(*args, **hashable_kwargs)
|
||||||
|
if digest in _pool:
|
||||||
|
client = _pool[digest]
|
||||||
|
else:
|
||||||
|
client = func(*args, **kwargs)
|
||||||
|
_pool[digest] = client
|
||||||
|
|
||||||
|
return client
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def create_api_client(configuration, **headers):
|
||||||
|
client = kubernetes.client.ApiClient(configuration)
|
||||||
|
for header, value in headers.items():
|
||||||
|
_set_header(client, header, value)
|
||||||
|
return k8sdynamicclient.K8SDynamicClient(client, discoverer=LazyDiscoverer)
|
||||||
|
|
||||||
|
|
||||||
|
class K8SClient:
|
||||||
|
"""A Client class for K8S modules.
|
||||||
|
|
||||||
|
This class has the primary purpose to proxy the kubernetes client and resource objects.
|
||||||
|
If there is a need for other methods or attributes to be proxied, they can be added here.
|
||||||
|
"""
|
||||||
|
|
||||||
|
K8S_SERVER_DRY_RUN = "All"
|
||||||
|
|
||||||
|
def __init__(self, configuration, client, dry_run: bool = False) -> None:
|
||||||
|
self.configuration = configuration
|
||||||
|
self.client = client
|
||||||
|
self.dry_run = dry_run
|
||||||
|
|
||||||
|
@property
|
||||||
|
def resources(self) -> List[Any]:
|
||||||
|
return self.client.resources
|
||||||
|
|
||||||
|
def _find_resource_with_prefix(
|
||||||
|
self, prefix: str, kind: str, api_version: str
|
||||||
|
) -> Resource:
|
||||||
|
for attribute in ["kind", "name", "singular_name"]:
|
||||||
|
try:
|
||||||
|
return self.client.resources.get(
|
||||||
|
**{"prefix": prefix, "api_version": api_version, attribute: kind}
|
||||||
|
)
|
||||||
|
except (ResourceNotFoundError, ResourceNotUniqueError):
|
||||||
|
pass
|
||||||
|
return self.client.resources.get(
|
||||||
|
prefix=prefix, api_version=api_version, short_names=[kind]
|
||||||
|
)
|
||||||
|
|
||||||
|
def resource(self, kind: str, api_version: str) -> Resource:
|
||||||
|
"""Fetch a kubernetes client resource.
|
||||||
|
|
||||||
|
This will attempt to find a kubernetes resource trying, in order, kind,
|
||||||
|
name, singular_name and short_names.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if api_version == "v1":
|
||||||
|
return self._find_resource_with_prefix("api", kind, api_version)
|
||||||
|
except ResourceNotFoundError:
|
||||||
|
pass
|
||||||
|
return self._find_resource_with_prefix(None, kind, api_version)
|
||||||
|
|
||||||
|
def _ensure_dry_run(self, params: Dict) -> Dict:
|
||||||
|
if self.dry_run:
|
||||||
|
params["dry_run"] = self.K8S_SERVER_DRY_RUN
|
||||||
|
return params
|
||||||
|
|
||||||
|
def validate(
|
||||||
|
self, resource, version: Optional[str] = None, strict: Optional[bool] = False
|
||||||
|
):
|
||||||
|
return self.client.validate(resource, version, strict)
|
||||||
|
|
||||||
|
def get(self, resource, **params):
|
||||||
|
return resource.get(**params)
|
||||||
|
|
||||||
|
def delete(self, resource, **params):
|
||||||
|
return resource.delete(**self._ensure_dry_run(params))
|
||||||
|
|
||||||
|
def apply(self, resource, definition, namespace, **params):
|
||||||
|
return resource.apply(
|
||||||
|
definition, namespace=namespace, **self._ensure_dry_run(params)
|
||||||
|
)
|
||||||
|
|
||||||
|
def create(self, resource, definition, **params):
|
||||||
|
return resource.create(definition, **self._ensure_dry_run(params))
|
||||||
|
|
||||||
|
def replace(self, resource, definition, **params):
|
||||||
|
return resource.replace(definition, **self._ensure_dry_run(params))
|
||||||
|
|
||||||
|
def patch(self, resource, definition, **params):
|
||||||
|
return resource.patch(definition, **self._ensure_dry_run(params))
|
||||||
|
|
||||||
|
|
||||||
|
def get_api_client(module=None, **kwargs: Optional[Any]) -> K8SClient:
|
||||||
|
auth_spec = _create_auth_spec(module, **kwargs)
|
||||||
|
if module:
|
||||||
|
requires = module.requires
|
||||||
|
else:
|
||||||
|
requires = _requires
|
||||||
|
if isinstance(auth_spec.get("kubeconfig"), dict):
|
||||||
|
requires("kubernetes", "17.17.0", "to use in-memory config")
|
||||||
|
if auth_spec.get("no_proxy"):
|
||||||
|
requires("kubernetes", "19.15.0", "to use the no_proxy feature")
|
||||||
|
|
||||||
|
try:
|
||||||
|
configuration = _create_configuration(auth_spec)
|
||||||
|
headers = _create_headers(module, **kwargs)
|
||||||
|
client = create_api_client(configuration, **headers)
|
||||||
|
except kubernetes.config.ConfigException as e:
|
||||||
|
msg = "Could not create API client: {0}".format(e)
|
||||||
|
raise CoreException(msg) from e
|
||||||
|
|
||||||
|
dry_run = False
|
||||||
|
if module and module.server_side_dry_run:
|
||||||
|
dry_run = True
|
||||||
|
|
||||||
|
k8s_client = K8SClient(
|
||||||
|
configuration=configuration,
|
||||||
|
client=client,
|
||||||
|
dry_run=dry_run,
|
||||||
|
)
|
||||||
|
|
||||||
|
return k8s_client
|
||||||
172
plugins/module_utils/k8s/core.py
Normal file
172
plugins/module_utils/k8s/core.py
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
import traceback
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||||
|
from ansible.module_utils.common.text.converters import to_text
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
|
||||||
|
LooseVersion,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AnsibleK8SModule:
|
||||||
|
"""A base module class for K8S modules.
|
||||||
|
|
||||||
|
This class should be used instead of directly using AnsibleModule. If there
|
||||||
|
is a need for other methods or attributes to be proxied, they can be added
|
||||||
|
here.
|
||||||
|
"""
|
||||||
|
|
||||||
|
default_settings = {
|
||||||
|
"check_k8s": True,
|
||||||
|
"check_pyyaml": True,
|
||||||
|
"module_class": AnsibleModule,
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, **kwargs) -> None:
|
||||||
|
local_settings = {}
|
||||||
|
for key in AnsibleK8SModule.default_settings:
|
||||||
|
try:
|
||||||
|
local_settings[key] = kwargs.pop(key)
|
||||||
|
except KeyError:
|
||||||
|
local_settings[key] = AnsibleK8SModule.default_settings[key]
|
||||||
|
self.settings = local_settings
|
||||||
|
|
||||||
|
self._module = self.settings["module_class"](**kwargs)
|
||||||
|
|
||||||
|
if self.settings["check_k8s"]:
|
||||||
|
self.requires("kubernetes")
|
||||||
|
self.has_at_least("kubernetes", "24.2.0", warn=True)
|
||||||
|
|
||||||
|
if self.settings["check_pyyaml"]:
|
||||||
|
self.requires("pyyaml")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def check_mode(self):
|
||||||
|
return self._module.check_mode
|
||||||
|
|
||||||
|
@property
|
||||||
|
def server_side_dry_run(self):
|
||||||
|
return self.check_mode and self.has_at_least("kubernetes", "18.20.0")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _diff(self):
|
||||||
|
return self._module._diff
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _name(self):
|
||||||
|
return self._module._name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def params(self):
|
||||||
|
return self._module.params
|
||||||
|
|
||||||
|
def warn(self, *args, **kwargs):
|
||||||
|
return self._module.warn(*args, **kwargs)
|
||||||
|
|
||||||
|
def deprecate(self, *args, **kwargs):
|
||||||
|
return self._module.deprecate(*args, **kwargs)
|
||||||
|
|
||||||
|
def debug(self, *args, **kwargs):
|
||||||
|
return self._module.debug(*args, **kwargs)
|
||||||
|
|
||||||
|
def exit_json(self, *args, **kwargs):
|
||||||
|
return self._module.exit_json(*args, **kwargs)
|
||||||
|
|
||||||
|
def fail_json(self, *args, **kwargs):
|
||||||
|
return self._module.fail_json(*args, **kwargs)
|
||||||
|
|
||||||
|
def fail_from_exception(self, exception):
|
||||||
|
msg = to_text(exception)
|
||||||
|
tb = "".join(
|
||||||
|
traceback.format_exception(None, exception, exception.__traceback__)
|
||||||
|
)
|
||||||
|
return self.fail_json(msg=msg, exception=tb)
|
||||||
|
|
||||||
|
def has_at_least(
|
||||||
|
self, dependency: str, minimum: Optional[str] = None, warn: bool = False
|
||||||
|
) -> bool:
|
||||||
|
supported = has_at_least(dependency, minimum)
|
||||||
|
if not supported and warn:
|
||||||
|
self.warn(
|
||||||
|
"{0}<{1} is not supported or tested. Some features may not work.".format(
|
||||||
|
dependency, minimum
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return supported
|
||||||
|
|
||||||
|
def requires(
|
||||||
|
self,
|
||||||
|
dependency: str,
|
||||||
|
minimum: Optional[str] = None,
|
||||||
|
reason: Optional[str] = None,
|
||||||
|
) -> None:
|
||||||
|
try:
|
||||||
|
requires(dependency, minimum, reason=reason)
|
||||||
|
except Exception as e:
|
||||||
|
self.fail_json(msg=to_text(e))
|
||||||
|
|
||||||
|
|
||||||
|
def gather_versions() -> dict:
|
||||||
|
versions = {}
|
||||||
|
try:
|
||||||
|
import jsonpatch
|
||||||
|
|
||||||
|
versions["jsonpatch"] = jsonpatch.__version__
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
import kubernetes
|
||||||
|
|
||||||
|
versions["kubernetes"] = kubernetes.__version__
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
import kubernetes_validate
|
||||||
|
|
||||||
|
versions["kubernetes-validate"] = kubernetes_validate.__version__
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
versions["pyyaml"] = yaml.__version__
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return versions
|
||||||
|
|
||||||
|
|
||||||
|
def has_at_least(dependency: str, minimum: Optional[str] = None) -> bool:
|
||||||
|
"""Check if a specific dependency is present at a minimum version.
|
||||||
|
|
||||||
|
If a minimum version is not specified it will check only that the
|
||||||
|
dependency is present.
|
||||||
|
"""
|
||||||
|
dependencies = gather_versions()
|
||||||
|
current = dependencies.get(dependency)
|
||||||
|
if current is not None:
|
||||||
|
if minimum is None:
|
||||||
|
return True
|
||||||
|
supported = LooseVersion(current) >= LooseVersion(minimum)
|
||||||
|
return supported
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def requires(
|
||||||
|
dependency: str, minimum: Optional[str] = None, reason: Optional[str] = None
|
||||||
|
) -> None:
|
||||||
|
"""Fail if a specific dependency is not present at a minimum version.
|
||||||
|
|
||||||
|
If a minimum version is not specified it will require only that the
|
||||||
|
dependency is present. This function raises an exception when the
|
||||||
|
dependency is not found at the required version.
|
||||||
|
"""
|
||||||
|
if not has_at_least(dependency, minimum):
|
||||||
|
if minimum is not None:
|
||||||
|
lib = "{0}>={1}".format(dependency, minimum)
|
||||||
|
else:
|
||||||
|
lib = dependency
|
||||||
|
raise Exception(missing_required_lib(lib, reason=reason))
|
||||||
12
plugins/module_utils/k8s/exceptions.py
Normal file
12
plugins/module_utils/k8s/exceptions.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# Copyright: (c) 2021, Red Hat | Ansible
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
|
||||||
|
class CoreException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceTimeout(CoreException):
|
||||||
|
def __init__(self, message="", result=None):
|
||||||
|
self.result = result or {}
|
||||||
|
super().__init__(message)
|
||||||
133
plugins/module_utils/k8s/resource.py
Normal file
133
plugins/module_utils/k8s/resource.py
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
# Copyright: (c) 2021, Red Hat | Ansible
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
import os
|
||||||
|
from typing import Dict, Iterable, List, Optional, Union, cast
|
||||||
|
|
||||||
|
from ansible.module_utils.urls import Request
|
||||||
|
|
||||||
|
try:
|
||||||
|
import yaml
|
||||||
|
except ImportError:
|
||||||
|
# Handled in module setup
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceDefinition(dict):
|
||||||
|
"""Representation of a resource definition.
|
||||||
|
|
||||||
|
This is a thin wrapper around a dictionary representation of a resource
|
||||||
|
definition, with a few properties defined for conveniently accessing the
|
||||||
|
commonly used fields.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def kind(self) -> Optional[str]:
|
||||||
|
return self.get("kind")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def api_version(self) -> Optional[str]:
|
||||||
|
return self.get("apiVersion")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def namespace(self) -> Optional[str]:
|
||||||
|
metadata = self.get("metadata", {})
|
||||||
|
return metadata.get("namespace")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self) -> Optional[str]:
|
||||||
|
metadata = self.get("metadata", {})
|
||||||
|
return metadata.get("name")
|
||||||
|
|
||||||
|
|
||||||
|
def create_definitions(params: Dict) -> List[ResourceDefinition]:
|
||||||
|
"""Create a list of ResourceDefinitions from module inputs.
|
||||||
|
|
||||||
|
This will take the module's inputs and return a list of ResourceDefintion
|
||||||
|
objects. The resource definitions returned by this function should be as
|
||||||
|
complete a definition as we can create based on the input. Any *List kinds
|
||||||
|
will be removed and replaced by the resources contained in it.
|
||||||
|
"""
|
||||||
|
if params.get("resource_definition"):
|
||||||
|
d = cast(Union[str, List, Dict], params.get("resource_definition"))
|
||||||
|
definitions = from_yaml(d)
|
||||||
|
elif params.get("src"):
|
||||||
|
d = cast(str, params.get("src"))
|
||||||
|
if hasattr(d, "startswith") and d.startswith(("https://", "http://", "ftp://")):
|
||||||
|
data = Request().open("GET", d).read().decode("utf8")
|
||||||
|
definitions = from_yaml(data)
|
||||||
|
else:
|
||||||
|
definitions = from_file(d)
|
||||||
|
else:
|
||||||
|
# We'll create an empty definition and let merge_params set values
|
||||||
|
# from the module parameters.
|
||||||
|
definitions = [{}]
|
||||||
|
|
||||||
|
resource_definitions: List[Dict] = []
|
||||||
|
for definition in definitions:
|
||||||
|
merge_params(definition, params)
|
||||||
|
kind = cast(Optional[str], definition.get("kind"))
|
||||||
|
if kind and kind.endswith("List"):
|
||||||
|
resource_definitions += flatten_list_kind(definition, params)
|
||||||
|
else:
|
||||||
|
resource_definitions.append(definition)
|
||||||
|
return list(map(ResourceDefinition, resource_definitions))
|
||||||
|
|
||||||
|
|
||||||
|
def from_yaml(definition: Union[str, List, Dict]) -> Iterable[Dict]:
|
||||||
|
"""Load resource definitions from a yaml definition."""
|
||||||
|
definitions: List[Dict] = []
|
||||||
|
if isinstance(definition, str):
|
||||||
|
definitions += yaml.safe_load_all(definition)
|
||||||
|
elif isinstance(definition, list):
|
||||||
|
for item in definition:
|
||||||
|
if isinstance(item, str):
|
||||||
|
definitions += yaml.safe_load_all(item)
|
||||||
|
else:
|
||||||
|
definitions.append(item)
|
||||||
|
else:
|
||||||
|
definition = cast(Dict, definition)
|
||||||
|
definitions.append(definition)
|
||||||
|
return filter(None, definitions)
|
||||||
|
|
||||||
|
|
||||||
|
def from_file(filepath: str) -> Iterable[Dict]:
|
||||||
|
"""Load resource definitions from a path to a yaml file."""
|
||||||
|
path = os.path.normpath(filepath)
|
||||||
|
with open(path, "rb") as f:
|
||||||
|
definitions = list(yaml.safe_load_all(f))
|
||||||
|
return filter(None, definitions)
|
||||||
|
|
||||||
|
|
||||||
|
def merge_params(definition: Dict, params: Dict) -> Dict:
|
||||||
|
"""Merge module parameters with the resource definition.
|
||||||
|
|
||||||
|
Fields in the resource definition take precedence over module parameters.
|
||||||
|
"""
|
||||||
|
definition.setdefault("kind", params.get("kind"))
|
||||||
|
definition.setdefault("apiVersion", params.get("api_version"))
|
||||||
|
metadata = definition.setdefault("metadata", {})
|
||||||
|
# The following should only be set if we have values for them
|
||||||
|
if params.get("namespace"):
|
||||||
|
metadata.setdefault("namespace", params.get("namespace"))
|
||||||
|
if params.get("name"):
|
||||||
|
metadata.setdefault("name", params.get("name"))
|
||||||
|
if params.get("generate_name"):
|
||||||
|
metadata.setdefault("generateName", params.get("generate_name"))
|
||||||
|
return definition
|
||||||
|
|
||||||
|
|
||||||
|
def flatten_list_kind(definition: Dict, params: Dict) -> List[Dict]:
|
||||||
|
"""Replace *List kind with the items it contains.
|
||||||
|
|
||||||
|
This will take a definition for a *List resource and return a list of
|
||||||
|
definitions for the items contained within the List.
|
||||||
|
"""
|
||||||
|
items = []
|
||||||
|
kind = cast(str, definition.get("kind"))[:-4]
|
||||||
|
api_version = definition.get("apiVersion")
|
||||||
|
for item in definition.get("items", []):
|
||||||
|
item.setdefault("kind", kind)
|
||||||
|
item.setdefault("apiVersion", api_version)
|
||||||
|
items.append(merge_params(item, params))
|
||||||
|
return items
|
||||||
237
plugins/module_utils/k8s/runner.py
Normal file
237
plugins/module_utils/k8s/runner.py
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
# Copyright: (c) 2021, Red Hat | Ansible
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
from ansible.module_utils._text import to_native
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.client import (
|
||||||
|
get_api_client,
|
||||||
|
)
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||||
|
CoreException,
|
||||||
|
ResourceTimeout,
|
||||||
|
)
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.resource import (
|
||||||
|
create_definitions,
|
||||||
|
)
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.service import (
|
||||||
|
K8sService,
|
||||||
|
diff_objects,
|
||||||
|
hide_fields,
|
||||||
|
)
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.waiter import exists
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.selector import (
|
||||||
|
LabelSelectorFilter,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def validate(client, module, resource):
|
||||||
|
def _prepend_resource_info(resource, msg):
|
||||||
|
return "%s %s: %s" % (resource["kind"], resource["metadata"]["name"], msg)
|
||||||
|
|
||||||
|
module.requires("kubernetes-validate")
|
||||||
|
|
||||||
|
warnings, errors = client.validate(
|
||||||
|
resource,
|
||||||
|
module.params["validate"].get("version"),
|
||||||
|
module.params["validate"].get("strict"),
|
||||||
|
)
|
||||||
|
|
||||||
|
if errors and module.params["validate"]["fail_on_error"]:
|
||||||
|
module.fail_json(
|
||||||
|
msg="\n".join([_prepend_resource_info(resource, error) for error in errors])
|
||||||
|
)
|
||||||
|
return [_prepend_resource_info(resource, msg) for msg in warnings + errors]
|
||||||
|
|
||||||
|
|
||||||
|
def get_definitions(svc, params):
|
||||||
|
try:
|
||||||
|
definitions = create_definitions(params)
|
||||||
|
except Exception as e:
|
||||||
|
msg = "Failed to load resource definition: {0}".format(e)
|
||||||
|
raise CoreException(msg) from e
|
||||||
|
|
||||||
|
delete_all = params.get("delete_all")
|
||||||
|
src = params.get("src")
|
||||||
|
resource_definition = params.get("resource_definition")
|
||||||
|
name = params.get("name")
|
||||||
|
state = params.get("state")
|
||||||
|
|
||||||
|
if (
|
||||||
|
delete_all
|
||||||
|
and state == "absent"
|
||||||
|
and name is None
|
||||||
|
and resource_definition is None
|
||||||
|
and src is None
|
||||||
|
):
|
||||||
|
# Delete all resources in the namespace for the specified resource type
|
||||||
|
if params.get("kind") is None:
|
||||||
|
raise CoreException(
|
||||||
|
"'kind' option is required to specify the resource type."
|
||||||
|
)
|
||||||
|
|
||||||
|
resource = svc.find_resource(
|
||||||
|
params.get("kind"), params.get("api_version"), fail=True
|
||||||
|
)
|
||||||
|
definitions = svc.retrieve_all(
|
||||||
|
resource,
|
||||||
|
params.get("namespace"),
|
||||||
|
params.get("label_selectors"),
|
||||||
|
)
|
||||||
|
|
||||||
|
return definitions
|
||||||
|
|
||||||
|
|
||||||
|
def run_module(module) -> None:
|
||||||
|
results = []
|
||||||
|
changed = False
|
||||||
|
client = get_api_client(module)
|
||||||
|
svc = K8sService(client, module)
|
||||||
|
|
||||||
|
definitions = get_definitions(svc, module.params)
|
||||||
|
|
||||||
|
for definition in definitions:
|
||||||
|
result = {"changed": False, "result": {}}
|
||||||
|
warnings = []
|
||||||
|
|
||||||
|
if module.params.get("validate") is not None:
|
||||||
|
warnings = validate(client, module, definition)
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = perform_action(svc, definition, module.params)
|
||||||
|
except Exception as e:
|
||||||
|
try:
|
||||||
|
error = e.result
|
||||||
|
except AttributeError:
|
||||||
|
error = {}
|
||||||
|
try:
|
||||||
|
error["reason"] = e.__cause__.reason
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
error["msg"] = to_native(e)
|
||||||
|
if warnings:
|
||||||
|
error.setdefault("warnings", []).extend(warnings)
|
||||||
|
|
||||||
|
if module.params.get("continue_on_error"):
|
||||||
|
result["error"] = error
|
||||||
|
else:
|
||||||
|
module.fail_json(**error)
|
||||||
|
|
||||||
|
if warnings:
|
||||||
|
result.setdefault("warnings", []).extend(warnings)
|
||||||
|
changed |= result["changed"]
|
||||||
|
results.append(result)
|
||||||
|
|
||||||
|
if len(results) == 1:
|
||||||
|
module.exit_json(**results[0])
|
||||||
|
|
||||||
|
module.exit_json(**{"changed": changed, "result": {"results": results}})
|
||||||
|
|
||||||
|
|
||||||
|
def perform_action(svc, definition: Dict, params: Dict) -> Dict:
|
||||||
|
origin_name = definition["metadata"].get("name")
|
||||||
|
namespace = definition["metadata"].get("namespace")
|
||||||
|
label_selectors = params.get("label_selectors")
|
||||||
|
state = params.get("state", None)
|
||||||
|
kind = definition.get("kind")
|
||||||
|
api_version = definition.get("apiVersion")
|
||||||
|
hidden_fields = params.get("hidden_fields")
|
||||||
|
|
||||||
|
result = {"changed": False, "result": {}}
|
||||||
|
instance = {}
|
||||||
|
warnings = []
|
||||||
|
|
||||||
|
resource = svc.find_resource(kind, api_version, fail=True)
|
||||||
|
definition["kind"] = resource.kind
|
||||||
|
definition["apiVersion"] = resource.group_version
|
||||||
|
existing = svc.retrieve(resource, definition)
|
||||||
|
|
||||||
|
if state == "absent":
|
||||||
|
if exists(existing) and existing.kind.endswith("List"):
|
||||||
|
instance = []
|
||||||
|
for item in existing.items:
|
||||||
|
r = svc.delete(resource, item, existing)
|
||||||
|
instance.append(r)
|
||||||
|
else:
|
||||||
|
instance = svc.delete(resource, definition, existing)
|
||||||
|
result["method"] = "delete"
|
||||||
|
if exists(existing):
|
||||||
|
result["changed"] = True
|
||||||
|
else:
|
||||||
|
if label_selectors:
|
||||||
|
filter_selector = LabelSelectorFilter(label_selectors)
|
||||||
|
if not filter_selector.isMatching(definition):
|
||||||
|
result["changed"] = False
|
||||||
|
result["msg"] = (
|
||||||
|
"resource 'kind={kind},name={name},namespace={namespace}' "
|
||||||
|
"filtered by label_selectors.".format(
|
||||||
|
kind=kind,
|
||||||
|
name=origin_name,
|
||||||
|
namespace=namespace,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
|
||||||
|
if params.get("apply"):
|
||||||
|
instance, warnings = svc.apply(resource, definition, existing)
|
||||||
|
result["method"] = "apply"
|
||||||
|
elif not existing:
|
||||||
|
if state == "patched":
|
||||||
|
result.setdefault("warnings", []).append(
|
||||||
|
"resource 'kind={kind},name={name}' was not found but will not be "
|
||||||
|
"created as 'state' parameter has been set to '{state}'".format(
|
||||||
|
kind=kind, name=definition["metadata"].get("name"), state=state
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
instance, warnings = svc.create(resource, definition)
|
||||||
|
result["method"] = "create"
|
||||||
|
result["changed"] = True
|
||||||
|
elif params.get("force", False):
|
||||||
|
instance, warnings = svc.replace(resource, definition, existing)
|
||||||
|
result["method"] = "replace"
|
||||||
|
else:
|
||||||
|
instance, warnings = svc.update(resource, definition, existing)
|
||||||
|
result["method"] = "update"
|
||||||
|
|
||||||
|
if warnings:
|
||||||
|
result["warnings"] = warnings
|
||||||
|
|
||||||
|
# If needed, wait and/or create diff
|
||||||
|
success = True
|
||||||
|
|
||||||
|
if result["method"] == "delete":
|
||||||
|
# wait logic is a bit different for delete as `instance` may be a status object
|
||||||
|
if params.get("wait") and not svc.module.check_mode:
|
||||||
|
success, waited, duration = svc.wait(resource, definition)
|
||||||
|
result["duration"] = duration
|
||||||
|
else:
|
||||||
|
if params.get("wait") and not svc.module.check_mode:
|
||||||
|
success, instance, duration = svc.wait(resource, instance)
|
||||||
|
result["duration"] = duration
|
||||||
|
|
||||||
|
if result["method"] not in ("create", "delete"):
|
||||||
|
if existing:
|
||||||
|
existing = existing.to_dict()
|
||||||
|
else:
|
||||||
|
existing = {}
|
||||||
|
match, diffs = diff_objects(existing, instance, hidden_fields)
|
||||||
|
if match and diffs:
|
||||||
|
result.setdefault("warnings", []).append(
|
||||||
|
"No meaningful diff was generated, but the API may not be idempotent "
|
||||||
|
"(only metadata.generation or metadata.resourceVersion were changed)"
|
||||||
|
)
|
||||||
|
result["changed"] = not match
|
||||||
|
if svc.module._diff:
|
||||||
|
result["diff"] = diffs
|
||||||
|
|
||||||
|
result["result"] = hide_fields(instance, hidden_fields)
|
||||||
|
if not success:
|
||||||
|
raise ResourceTimeout(
|
||||||
|
'"{0}" "{1}": Timed out waiting on resource'.format(
|
||||||
|
definition["kind"], origin_name
|
||||||
|
),
|
||||||
|
result,
|
||||||
|
)
|
||||||
|
|
||||||
|
return result
|
||||||
711
plugins/module_utils/k8s/service.py
Normal file
711
plugins/module_utils/k8s/service.py
Normal file
@@ -0,0 +1,711 @@
|
|||||||
|
# Copyright: (c) 2021, Red Hat | Ansible
|
||||||
|
# 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, Union
|
||||||
|
|
||||||
|
from ansible.module_utils.common.dict_transformations import dict_merge
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.hashes import (
|
||||||
|
generate_hash,
|
||||||
|
)
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.core import requires
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.exceptions import (
|
||||||
|
CoreException,
|
||||||
|
)
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.k8s.waiter import (
|
||||||
|
Waiter,
|
||||||
|
exists,
|
||||||
|
get_waiter,
|
||||||
|
resource_absent,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
from kubernetes.dynamic.exceptions import (
|
||||||
|
BadRequestError,
|
||||||
|
ConflictError,
|
||||||
|
ForbiddenError,
|
||||||
|
MethodNotAllowedError,
|
||||||
|
NotFoundError,
|
||||||
|
ResourceNotFoundError,
|
||||||
|
ResourceNotUniqueError,
|
||||||
|
)
|
||||||
|
except ImportError:
|
||||||
|
# Handled in module setup
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
from kubernetes.dynamic.resource import Resource, ResourceInstance
|
||||||
|
except ImportError:
|
||||||
|
# These are defined only for the sake of Ansible's checked import requirement
|
||||||
|
Resource = Any # type: ignore
|
||||||
|
ResourceInstance = Any # type: ignore
|
||||||
|
|
||||||
|
try:
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.apply import (
|
||||||
|
apply_object,
|
||||||
|
)
|
||||||
|
except ImportError:
|
||||||
|
# Handled in module setup
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.apply import (
|
||||||
|
recursive_diff,
|
||||||
|
)
|
||||||
|
except ImportError:
|
||||||
|
from ansible.module_utils.common.dict_transformations import recursive_diff
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
from ansible_collections.kubernetes.core.plugins.module_utils.common import (
|
||||||
|
_encode_stringdata,
|
||||||
|
)
|
||||||
|
except ImportError:
|
||||||
|
# Handled in module setup
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class K8sService:
|
||||||
|
"""A Service class for K8S modules.
|
||||||
|
This class has the primary purpose is to perform work on the cluster (e.g., create, apply, replace, update, delete).
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, client, module) -> None:
|
||||||
|
self.client = client
|
||||||
|
self.module = module
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _client_side_dry_run(self):
|
||||||
|
return self.module.check_mode and not self.client.dry_run
|
||||||
|
|
||||||
|
def find_resource(
|
||||||
|
self, kind: str, api_version: str, fail: bool = False
|
||||||
|
) -> Optional[Resource]:
|
||||||
|
try:
|
||||||
|
return self.client.resource(kind, api_version)
|
||||||
|
except (ResourceNotFoundError, ResourceNotUniqueError):
|
||||||
|
if fail:
|
||||||
|
raise CoreException(
|
||||||
|
"Failed to find exact match for %s.%s by [kind, name, singularName, shortNames]"
|
||||||
|
% (api_version, kind)
|
||||||
|
)
|
||||||
|
|
||||||
|
def wait(
|
||||||
|
self, resource: Resource, instance: Dict
|
||||||
|
) -> Tuple[bool, Optional[Dict], int]:
|
||||||
|
wait_sleep = self.module.params.get("wait_sleep")
|
||||||
|
wait_timeout = self.module.params.get("wait_timeout")
|
||||||
|
wait_condition = None
|
||||||
|
if self.module.params.get("wait_condition") and self.module.params[
|
||||||
|
"wait_condition"
|
||||||
|
].get("type"):
|
||||||
|
wait_condition = self.module.params["wait_condition"]
|
||||||
|
state = "present"
|
||||||
|
if self.module.params.get("state") == "absent":
|
||||||
|
state = "absent"
|
||||||
|
label_selectors = self.module.params.get("label_selectors")
|
||||||
|
|
||||||
|
waiter = get_waiter(
|
||||||
|
self.client, resource, condition=wait_condition, state=state
|
||||||
|
)
|
||||||
|
return waiter.wait(
|
||||||
|
timeout=wait_timeout,
|
||||||
|
sleep=wait_sleep,
|
||||||
|
name=instance["metadata"].get("name"),
|
||||||
|
namespace=instance["metadata"].get("namespace"),
|
||||||
|
label_selectors=label_selectors,
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_project_request(self, definition: Dict) -> Dict:
|
||||||
|
definition["kind"] = "ProjectRequest"
|
||||||
|
results = {"changed": False, "result": {}}
|
||||||
|
resource = self.find_resource(
|
||||||
|
"ProjectRequest", definition["apiVersion"], fail=True
|
||||||
|
)
|
||||||
|
if not self.module.check_mode:
|
||||||
|
try:
|
||||||
|
k8s_obj = self.client.create(resource, definition)
|
||||||
|
results["result"] = k8s_obj.to_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
|
||||||
|
|
||||||
|
results["changed"] = True
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
def patch_resource(
|
||||||
|
self,
|
||||||
|
resource: Resource,
|
||||||
|
definition: Dict,
|
||||||
|
name: str,
|
||||||
|
namespace: str,
|
||||||
|
merge_type: str = None,
|
||||||
|
) -> Tuple[Dict, List[str]]:
|
||||||
|
try:
|
||||||
|
params = dict(name=name, namespace=namespace, serialize=False)
|
||||||
|
if merge_type:
|
||||||
|
params["content_type"] = "application/{0}-patch+json".format(merge_type)
|
||||||
|
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)
|
||||||
|
raise CoreException(msg) from e
|
||||||
|
|
||||||
|
def retrieve(self, resource: Resource, definition: Dict) -> ResourceInstance:
|
||||||
|
state = self.module.params.get("state", None)
|
||||||
|
append_hash = self.module.params.get("append_hash", False)
|
||||||
|
name = definition["metadata"].get("name")
|
||||||
|
generate_name = definition["metadata"].get("generateName")
|
||||||
|
namespace = definition["metadata"].get("namespace")
|
||||||
|
label_selectors = self.module.params.get("label_selectors")
|
||||||
|
existing: ResourceInstance = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
# ignore append_hash for resources other than ConfigMap and Secret
|
||||||
|
if append_hash and definition["kind"] in ["ConfigMap", "Secret"]:
|
||||||
|
if name:
|
||||||
|
name = "%s-%s" % (name, generate_hash(definition))
|
||||||
|
definition["metadata"]["name"] = name
|
||||||
|
elif generate_name:
|
||||||
|
definition["metadata"]["generateName"] = "%s-%s" % (
|
||||||
|
generate_name,
|
||||||
|
generate_hash(definition),
|
||||||
|
)
|
||||||
|
params = {}
|
||||||
|
if name:
|
||||||
|
params["name"] = name
|
||||||
|
if namespace:
|
||||||
|
params["namespace"] = namespace
|
||||||
|
if label_selectors:
|
||||||
|
params["label_selector"] = ",".join(label_selectors)
|
||||||
|
if "name" in params or "label_selector" in params:
|
||||||
|
existing = self.client.get(resource, **params)
|
||||||
|
except (NotFoundError, MethodNotAllowedError):
|
||||||
|
pass
|
||||||
|
except ForbiddenError as e:
|
||||||
|
if (
|
||||||
|
definition["kind"] in ["Project", "ProjectRequest"]
|
||||||
|
and state != "absent"
|
||||||
|
):
|
||||||
|
return self.create_project_request(definition)
|
||||||
|
reason = e.body if hasattr(e, "body") else e
|
||||||
|
msg = "Failed to retrieve requested object: {0}".format(reason)
|
||||||
|
raise CoreException(msg) from e
|
||||||
|
except Exception as e:
|
||||||
|
reason = e.body if hasattr(e, "body") else e
|
||||||
|
msg = "Failed to retrieve requested object: {0}".format(reason)
|
||||||
|
raise CoreException(msg) from e
|
||||||
|
|
||||||
|
return existing
|
||||||
|
|
||||||
|
def retrieve_all(
|
||||||
|
self, resource: Resource, namespace: str, label_selectors: List[str] = None
|
||||||
|
) -> List[Dict]:
|
||||||
|
definitions: List[ResourceInstance] = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
params = dict(namespace=namespace)
|
||||||
|
if label_selectors:
|
||||||
|
params["label_selector"] = ",".join(label_selectors)
|
||||||
|
resource_list = self.client.get(resource, **params)
|
||||||
|
for item in resource_list.items:
|
||||||
|
existing = self.client.get(
|
||||||
|
resource, name=item.metadata.name, namespace=namespace
|
||||||
|
)
|
||||||
|
definitions.append(existing.to_dict())
|
||||||
|
except (NotFoundError, MethodNotAllowedError):
|
||||||
|
pass
|
||||||
|
except Exception as e:
|
||||||
|
reason = e.body if hasattr(e, "body") else e
|
||||||
|
msg = "Failed to retrieve requested object: {0}".format(reason)
|
||||||
|
raise CoreException(msg) from e
|
||||||
|
|
||||||
|
return definitions
|
||||||
|
|
||||||
|
def find(
|
||||||
|
self,
|
||||||
|
kind: str,
|
||||||
|
api_version: str,
|
||||||
|
name: str = None,
|
||||||
|
namespace: Optional[str] = None,
|
||||||
|
label_selectors: Optional[List[str]] = None,
|
||||||
|
field_selectors: Optional[List[str]] = None,
|
||||||
|
wait: Optional[bool] = False,
|
||||||
|
wait_sleep: Optional[int] = 5,
|
||||||
|
wait_timeout: Optional[int] = 120,
|
||||||
|
state: Optional[str] = "present",
|
||||||
|
condition: Optional[Dict] = None,
|
||||||
|
hidden_fields: Optional[List] = None,
|
||||||
|
) -> Dict:
|
||||||
|
resource = self.find_resource(kind, api_version)
|
||||||
|
api_found = bool(resource)
|
||||||
|
if not api_found:
|
||||||
|
return dict(
|
||||||
|
resources=[],
|
||||||
|
msg='Failed to find API for resource with apiVersion "{0}" and kind "{1}"'.format(
|
||||||
|
api_version, kind
|
||||||
|
),
|
||||||
|
api_found=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not label_selectors:
|
||||||
|
label_selectors = []
|
||||||
|
if not field_selectors:
|
||||||
|
field_selectors = []
|
||||||
|
|
||||||
|
result = {"resources": [], "api_found": True}
|
||||||
|
|
||||||
|
# With a timeout of 0 the waiter will do a single check and return, effectively not waiting.
|
||||||
|
if not wait:
|
||||||
|
wait_timeout = 0
|
||||||
|
|
||||||
|
if state == "present":
|
||||||
|
predicate = exists
|
||||||
|
else:
|
||||||
|
predicate = resource_absent
|
||||||
|
|
||||||
|
waiter = Waiter(self.client, resource, predicate)
|
||||||
|
|
||||||
|
# This is an initial check to get the resource or resources that we then need to wait on individually.
|
||||||
|
try:
|
||||||
|
success, resources, duration = waiter.wait(
|
||||||
|
timeout=wait_timeout,
|
||||||
|
sleep=wait_sleep,
|
||||||
|
name=name,
|
||||||
|
namespace=namespace,
|
||||||
|
label_selectors=label_selectors,
|
||||||
|
field_selectors=field_selectors,
|
||||||
|
)
|
||||||
|
except BadRequestError:
|
||||||
|
return result
|
||||||
|
except CoreException as e:
|
||||||
|
raise e
|
||||||
|
except Exception as e:
|
||||||
|
raise CoreException(
|
||||||
|
"Exception '{0}' raised while trying to get resource using (name={1}, namespace={2}, label_selectors={3}, field_selectors={4})".format(
|
||||||
|
e, name, namespace, label_selectors, field_selectors
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# There is either no result or there is a List resource with no items
|
||||||
|
if (
|
||||||
|
not resources
|
||||||
|
or resources["kind"].endswith("List")
|
||||||
|
and not resources.get("items")
|
||||||
|
):
|
||||||
|
return result
|
||||||
|
|
||||||
|
instances = resources.get("items") or [resources]
|
||||||
|
|
||||||
|
if not wait:
|
||||||
|
result["resources"] = [
|
||||||
|
hide_fields(instance, hidden_fields) for instance in instances
|
||||||
|
]
|
||||||
|
return result
|
||||||
|
|
||||||
|
# Now wait for the specified state of any resource instances we have found.
|
||||||
|
waiter = get_waiter(self.client, resource, state=state, condition=condition)
|
||||||
|
for instance in instances:
|
||||||
|
name = instance["metadata"].get("name")
|
||||||
|
namespace = instance["metadata"].get("namespace")
|
||||||
|
success, res, duration = waiter.wait(
|
||||||
|
timeout=wait_timeout,
|
||||||
|
sleep=wait_sleep,
|
||||||
|
name=name,
|
||||||
|
namespace=namespace,
|
||||||
|
)
|
||||||
|
if not success:
|
||||||
|
raise CoreException(
|
||||||
|
"Failed to gather information about %s(s) even"
|
||||||
|
" after waiting for %s seconds" % (res.get("kind"), duration)
|
||||||
|
)
|
||||||
|
result["resources"].append(hide_fields(res, hidden_fields))
|
||||||
|
return result
|
||||||
|
|
||||||
|
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:
|
||||||
|
return _encode_stringdata(definition), []
|
||||||
|
|
||||||
|
try:
|
||||||
|
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
|
||||||
|
# In this case we'll mark it as unchanged and warn the user
|
||||||
|
self.module.warn(
|
||||||
|
"{0} was not found, but creating it returned a 409 Conflict error. This can happen \
|
||||||
|
if the resource you are creating does not directly create a resource of the same kind.".format(
|
||||||
|
name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return dict(), []
|
||||||
|
except Exception as e:
|
||||||
|
reason = e.body if hasattr(e, "body") else e
|
||||||
|
msg = "Failed to create object: {0}".format(reason)
|
||||||
|
raise CoreException(msg) from e
|
||||||
|
|
||||||
|
def apply(
|
||||||
|
self,
|
||||||
|
resource: Resource,
|
||||||
|
definition: Dict,
|
||||||
|
existing: Optional[ResourceInstance] = None,
|
||||||
|
) -> 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:
|
||||||
|
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)
|
||||||
|
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
|
||||||
|
|
||||||
|
def replace(
|
||||||
|
self,
|
||||||
|
resource: Resource,
|
||||||
|
definition: Dict,
|
||||||
|
existing: ResourceInstance,
|
||||||
|
) -> 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:
|
||||||
|
return _encode_stringdata(definition), []
|
||||||
|
|
||||||
|
try:
|
||||||
|
return decode_response(
|
||||||
|
self.client.replace(
|
||||||
|
resource,
|
||||||
|
definition,
|
||||||
|
name=name,
|
||||||
|
namespace=namespace,
|
||||||
|
append_hash=append_hash,
|
||||||
|
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
|
||||||
|
|
||||||
|
def update(
|
||||||
|
self, resource: Resource, definition: Dict, existing: ResourceInstance
|
||||||
|
) -> Tuple[Dict, List[str]]:
|
||||||
|
name = definition["metadata"].get("name")
|
||||||
|
namespace = definition["metadata"].get("namespace")
|
||||||
|
|
||||||
|
if self._client_side_dry_run:
|
||||||
|
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:
|
||||||
|
return self.patch_resource(
|
||||||
|
resource,
|
||||||
|
definition,
|
||||||
|
name,
|
||||||
|
namespace,
|
||||||
|
merge_type=merge_type,
|
||||||
|
)
|
||||||
|
except CoreException as e:
|
||||||
|
exception = e
|
||||||
|
continue
|
||||||
|
raise exception
|
||||||
|
|
||||||
|
def delete(
|
||||||
|
self,
|
||||||
|
resource: Resource,
|
||||||
|
definition: Dict,
|
||||||
|
existing: Optional[ResourceInstance] = None,
|
||||||
|
) -> Dict:
|
||||||
|
delete_options = self.module.params.get("delete_options")
|
||||||
|
label_selectors = self.module.params.get("label_selectors")
|
||||||
|
name = definition["metadata"].get("name")
|
||||||
|
namespace = definition["metadata"].get("namespace")
|
||||||
|
params = {}
|
||||||
|
|
||||||
|
if not exists(existing):
|
||||||
|
return {}
|
||||||
|
|
||||||
|
# Delete the object
|
||||||
|
if self._client_side_dry_run:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
if name:
|
||||||
|
params["name"] = name
|
||||||
|
|
||||||
|
if namespace:
|
||||||
|
params["namespace"] = namespace
|
||||||
|
|
||||||
|
if label_selectors:
|
||||||
|
params["label_selector"] = ",".join(label_selectors)
|
||||||
|
|
||||||
|
if delete_options and not self.module.check_mode:
|
||||||
|
body = {
|
||||||
|
"apiVersion": "v1",
|
||||||
|
"kind": "DeleteOptions",
|
||||||
|
}
|
||||||
|
body.update(delete_options)
|
||||||
|
params["body"] = body
|
||||||
|
|
||||||
|
try:
|
||||||
|
k8s_obj = self.client.delete(resource, **params).to_dict()
|
||||||
|
except Exception as e:
|
||||||
|
reason = e.body if hasattr(e, "body") else e
|
||||||
|
msg = "Failed to delete object: {0}".format(reason)
|
||||||
|
raise CoreException(msg) from e
|
||||||
|
return k8s_obj
|
||||||
|
|
||||||
|
|
||||||
|
def diff_objects(
|
||||||
|
existing: Dict, new: Dict, hidden_fields: Optional[list] = None
|
||||||
|
) -> Tuple[bool, Dict]:
|
||||||
|
result = {}
|
||||||
|
diff = recursive_diff(existing, new)
|
||||||
|
if not diff:
|
||||||
|
return True, result
|
||||||
|
|
||||||
|
result["before"] = hide_fields(diff[0], hidden_fields)
|
||||||
|
result["after"] = hide_fields(diff[1], hidden_fields)
|
||||||
|
|
||||||
|
if list(result["after"].keys()) == ["metadata"] and list(
|
||||||
|
result["before"].keys()
|
||||||
|
) == ["metadata"]:
|
||||||
|
# If only metadata.generation and metadata.resourceVersion changed, ignore it
|
||||||
|
ignored_keys = set(["generation", "resourceVersion"])
|
||||||
|
|
||||||
|
if set(result["after"]["metadata"].keys()).issubset(ignored_keys) and set(
|
||||||
|
result["before"]["metadata"].keys()
|
||||||
|
).issubset(ignored_keys):
|
||||||
|
return True, result
|
||||||
|
|
||||||
|
return False, result
|
||||||
|
|
||||||
|
|
||||||
|
def hide_field_tree(hidden_field: str) -> List[str]:
|
||||||
|
result = []
|
||||||
|
key, rest = hide_field_split2(hidden_field)
|
||||||
|
result.append(key)
|
||||||
|
while rest:
|
||||||
|
key, rest = hide_field_split2(rest)
|
||||||
|
result.append(key)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def build_hidden_field_tree(hidden_fields: List[str]) -> Dict[str, Any]:
|
||||||
|
"""Group hidden field targeting the same json key
|
||||||
|
Example:
|
||||||
|
Input: ['env[3]', 'env[0]']
|
||||||
|
Output: {'env': [0, 3]}
|
||||||
|
"""
|
||||||
|
output = {}
|
||||||
|
for hidden_field in hidden_fields:
|
||||||
|
current = output
|
||||||
|
tree = hide_field_tree(hidden_field)
|
||||||
|
for idx, key in enumerate(tree):
|
||||||
|
if current.get(key, "") is None:
|
||||||
|
break
|
||||||
|
if idx == (len(tree) - 1):
|
||||||
|
current[key] = None
|
||||||
|
elif key not in current:
|
||||||
|
current[key] = {}
|
||||||
|
current = current[key]
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
# hide_field should be able to cope with simple or more complicated
|
||||||
|
# field definitions
|
||||||
|
# e.g. status or metadata.managedFields or
|
||||||
|
# spec.template.spec.containers[0].env[3].value or
|
||||||
|
# metadata.annotations[kubectl.kubernetes.io/last-applied-configuration]
|
||||||
|
def hide_field(
|
||||||
|
definition: Union[Dict[str, Any], List[Any]], hidden_field: Dict[str, Any]
|
||||||
|
) -> Dict[str, Any]:
|
||||||
|
def dict_contains_key(obj: Dict[str, Any], key: str) -> bool:
|
||||||
|
return key in obj
|
||||||
|
|
||||||
|
def list_contains_key(obj: List[Any], key: str) -> bool:
|
||||||
|
return int(key) < len(obj)
|
||||||
|
|
||||||
|
hidden_keys = list(hidden_field.keys())
|
||||||
|
field_contains_key = dict_contains_key
|
||||||
|
field_get_key = str
|
||||||
|
if isinstance(definition, list):
|
||||||
|
# Sort with reverse=true so that when we delete an item from the list, the order is not changed
|
||||||
|
hidden_keys = sorted(
|
||||||
|
[k for k in hidden_field.keys() if k.isdecimal()], reverse=True
|
||||||
|
)
|
||||||
|
field_contains_key = list_contains_key
|
||||||
|
field_get_key = int
|
||||||
|
|
||||||
|
for key in hidden_keys:
|
||||||
|
if field_contains_key(definition, key):
|
||||||
|
value = hidden_field.get(key)
|
||||||
|
convert_key = field_get_key(key)
|
||||||
|
if value is None:
|
||||||
|
del definition[convert_key]
|
||||||
|
else:
|
||||||
|
definition[convert_key] = hide_field(definition[convert_key], value)
|
||||||
|
if (
|
||||||
|
definition[convert_key] == dict()
|
||||||
|
or definition[convert_key] == list()
|
||||||
|
):
|
||||||
|
del definition[convert_key]
|
||||||
|
|
||||||
|
return definition
|
||||||
|
|
||||||
|
|
||||||
|
def hide_fields(
|
||||||
|
definition: Dict[str, Any], hidden_fields: Optional[List[str]]
|
||||||
|
) -> Dict[str, Any]:
|
||||||
|
if not hidden_fields:
|
||||||
|
return definition
|
||||||
|
result = copy.deepcopy(definition)
|
||||||
|
hidden_field_tree = build_hidden_field_tree(hidden_fields)
|
||||||
|
return hide_field(result, hidden_field_tree)
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
# hide_field_split2 returns the first key in hidden_field and the rest of the hidden_field
|
||||||
|
# We expect the first key to either be in brackets, to be terminated by the start of a left
|
||||||
|
# bracket, or to be terminated by a dot.
|
||||||
|
|
||||||
|
# examples would be:
|
||||||
|
# field.another.next -> (field, another.next)
|
||||||
|
# field[key].value -> (field, [key].value)
|
||||||
|
# [key].value -> (key, value)
|
||||||
|
# [one][two] -> (one, [two])
|
||||||
|
|
||||||
|
|
||||||
|
def hide_field_split2(hidden_field: str) -> Tuple[str, str]:
|
||||||
|
lbracket = hidden_field.find("[")
|
||||||
|
rbracket = hidden_field.find("]")
|
||||||
|
dot = hidden_field.find(".")
|
||||||
|
|
||||||
|
if lbracket == 0:
|
||||||
|
# skip past right bracket and any following dot
|
||||||
|
rest = hidden_field[rbracket + 1 :] # noqa: E203
|
||||||
|
if rest and rest[0] == ".":
|
||||||
|
rest = rest[1:]
|
||||||
|
return (hidden_field[lbracket + 1 : rbracket], rest) # noqa: E203
|
||||||
|
|
||||||
|
if lbracket != -1 and (dot == -1 or lbracket < dot):
|
||||||
|
return (hidden_field[:lbracket], hidden_field[lbracket:])
|
||||||
|
|
||||||
|
split = hidden_field.split(".", 1)
|
||||||
|
if len(split) == 1:
|
||||||
|
return split[0], ""
|
||||||
|
return split
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user