mirror of
https://github.com/ansible-collections/kubernetes.core.git
synced 2026-05-11 20:12:18 +00:00
Compare commits
277 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fb6546b03 | ||
|
|
ef9fb67688 | ||
|
|
90bc4c4b3b | ||
|
|
1590c6a4cc | ||
|
|
76eccacab6 | ||
|
|
620abbac26 | ||
|
|
66a820e03a | ||
|
|
a3f2438e9d | ||
|
|
0709ea31c9 | ||
|
|
44ab1fc478 | ||
|
|
80c33c5573 | ||
|
|
73dc94be68 | ||
|
|
1bc65230bb | ||
|
|
91427a5b6a | ||
|
|
1d1a23b1ab | ||
|
|
6edc84678d | ||
|
|
66bd8620e4 | ||
|
|
94b43dc582 | ||
|
|
3c4f9cee60 | ||
|
|
a54b4a13b6 | ||
|
|
e16b3c46b0 | ||
|
|
bc60523372 | ||
|
|
64f3f07c5a | ||
|
|
d6492b66d9 | ||
|
|
4d5388ddf8 | ||
|
|
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 |
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
|
||||
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
|
||||
164
.github/workflows/integration-tests.yaml
vendored
Normal file
164
.github/workflows/integration-tests.yaml
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
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:
|
||||
# Ref must match a branch/tag on github.com/ansible/ansible (e.g. stable-2.18, not 2.18).
|
||||
ansible-version: ["stable-2.18", "milestone"]
|
||||
enable-turbo-mode: [true, false]
|
||||
exclude:
|
||||
- ansible-version: "milestone"
|
||||
enable-turbo-mode: true
|
||||
python-version:
|
||||
- "3.12"
|
||||
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
|
||||
if: ${{ matrix.enable-turbo-mode == true }}
|
||||
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
|
||||
if: ${{ matrix.enable-turbo-mode == true }}
|
||||
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 }}
|
||||
28
.github/workflows/label-new-prs.yaml
vendored
Normal file
28
.github/workflows/label-new-prs.yaml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
name: label new prs
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
- converted_to_draft
|
||||
- ready_for_review
|
||||
|
||||
jobs:
|
||||
add_label:
|
||||
if: github.actor != 'patchback[bot]'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Add 'needs_triage' label if the pr is not a draft
|
||||
uses: actions-ecosystem/action-add-labels@v1
|
||||
if: github.event.pull_request.draft == false
|
||||
with:
|
||||
labels: needs_triage
|
||||
|
||||
- name: Remove 'needs_triage' label if the pr is a draft
|
||||
uses: actions-ecosystem/action-remove-labels@v1
|
||||
if: github.event.pull_request.draft == true
|
||||
with:
|
||||
labels: needs_triage
|
||||
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,6 +13,15 @@ changelogs/.plugin-cache.yaml
|
||||
tests/output
|
||||
tests/integration/cloud-config-*
|
||||
.cache
|
||||
.ansible
|
||||
|
||||
# Helm charts
|
||||
molecule/default/*-chart-*.tgz
|
||||
tests/integration/*-chart-*.tgz
|
||||
tests/integration/targets/*/*.tgz
|
||||
|
||||
# ansible-test generated file
|
||||
tests/integration/inventory
|
||||
tests/integration/*-*.yml
|
||||
|
||||
# VS Code settings
|
||||
.vscode/
|
||||
|
||||
@@ -5,16 +5,25 @@ rules:
|
||||
braces:
|
||||
max-spaces-inside: 1
|
||||
level: error
|
||||
|
||||
brackets:
|
||||
max-spaces-inside: 1
|
||||
level: error
|
||||
comments:
|
||||
min-spaces-from-content: 1
|
||||
comments-indentation: false
|
||||
document-start: disable
|
||||
line-length: disable
|
||||
truthy: disable
|
||||
indentation:
|
||||
spaces: 2
|
||||
indent-sequences: consistent
|
||||
octal-values:
|
||||
forbid-implicit-octal: true
|
||||
forbid-explicit-octal: true
|
||||
ignore: |
|
||||
.cache
|
||||
.tox
|
||||
.ansible
|
||||
tests/output
|
||||
plugins/connection/kubectl.py
|
||||
|
||||
526
CHANGELOG.rst
526
CHANGELOG.rst
@@ -4,6 +4,532 @@ Kubernetes Collection Release Notes
|
||||
|
||||
.. contents:: Topics
|
||||
|
||||
v6.4.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
This release adds Helm v4 compatibility across the Helm modules and improves ``k8s_drain`` with check mode. When you explicitly allow evicting unmanaged pods, pods with local storage, or pods managed by a ``DaemonSet``, those cases are reported as informational output instead of module warnings.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- helm_info - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
|
||||
- helm_plugin - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
|
||||
- helm_plugin_info - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
|
||||
- helm_pull - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
|
||||
- helm_registry_auth - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
|
||||
- helm_registry_auth - add new option plain_http to allow insecure http connection when running ``helm registry login`` (https://github.com/ansible-collections/kubernetes.core/pull/1090).
|
||||
- helm_repository - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
|
||||
- k8s_drain - Add support for ``check_mode`` (https://github.com/ansible-collections/kubernetes.core/pull/1086).
|
||||
- k8s_drain - Convert module warnings into informational displays when users explicitly request the deletion of unmanaged pods, pods with local storage, or those managed by a `DaemonSet` (https://github.com/ansible-collections/kubernetes.core/issues/1037).
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Helm - Allow taking ownership of existing Kubernetes resources on the first installation of a Helm release. Previously, the ``take_ownership`` parameter was always disabled during the initial install, preventing resource adoption (https://github.com/ansible-collections/kubernetes.core/pull/1034).
|
||||
|
||||
v6.3.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
This release includes bugfixes such as implementing idempotency for the ``helm_pull`` module as well as a security update for selectively redacting sensitive information from kubeconfig.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Remove deprecated import from ``ansible.module_utils._text`` (https://github.com/ansible-collections/kubernetes.core/pull/1053).
|
||||
- helm - add ``release_values`` key to ``status`` return value that can be accessed using Jinja2 dot notation (https://github.com/ansible-collections/kubernetes.core/pull/1056).
|
||||
- helm_info - add ``release_values`` key to ``status`` return value that can be accessed using Jinja2 dot notation (https://github.com/ansible-collections/kubernetes.core/pull/1056).
|
||||
|
||||
Deprecated Features
|
||||
-------------------
|
||||
|
||||
- helm - the ``status.values`` return value has been deprecated and will be removed in a release after 2027-01-08. Use ``status.release_values`` instead (https://github.com/ansible-collections/kubernetes.core/pull/1056).
|
||||
- helm_info - the ``status.values`` return value has been deprecated and will be removed in a release after 2027-01-08. Use ``status.release_values`` instead (https://github.com/ansible-collections/kubernetes.core/pull/1056).
|
||||
|
||||
Security Fixes
|
||||
--------------
|
||||
|
||||
- Selectively redact sensitive info from kubeconfig instead of applying blanket ``no_log=True`` (https://github.com/ansible-collections/kubernetes.core/pull/1014).
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Add idempotency for ``helm_pull`` module (https://github.com/ansible-collections/kubernetes.core/pull/1055).
|
||||
- Fixed a bug where setting ``K8S_AUTH_VERIFY_SSL=true`` (or any string value) caused the value to be treated as a separate ``kubectl`` command argument. (https://github.com/ansible-collections/kubernetes.core/pull/1049).
|
||||
- Limit supported versions of Helm to <4.0.0 (https://github.com/ansible-collections/kubernetes.core/pull/1039).
|
||||
- Replace passing ``warnings`` to ``exit_json`` with ``AnsibleModule.warn`` in the ``k8s_drain``, ``k8s_rollback.py`` and ``k8s_scale.py`` modules as it deprecated in ``ansible-core>=2.19.0`` and will be removed in ``ansible-core>=2.23.0`` (https://github.com/ansible-collections/kubernetes.core/pull/1033).
|
||||
- k8s - Fix return block from the module documentation (https://github.com/ansible-collections/kubernetes.core/pull/1056).
|
||||
- meta - Add ``k8s_cluster_info``, ``k8s_json_patch`` and ``k8s_rollback`` to k8s action group (https://github.com/ansible-collections/kubernetes.core/pull/992).
|
||||
|
||||
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
|
||||
======
|
||||
|
||||
@@ -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
|
||||
[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
|
||||
|
||||
@@ -70,11 +70,3 @@ Review the changes and create a pull request using updated files.
|
||||
The `kubernetes.core` collection follows the Ansible project's
|
||||
[Code of Conduct](https://docs.ansible.com/ansible/devel/community/code_of_conduct.html).
|
||||
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.
|
||||
|
||||
7
Makefile
7
Makefile
@@ -1,5 +1,5 @@
|
||||
# Also needs to be updated in galaxy.yml
|
||||
VERSION = 2.2.0
|
||||
VERSION = 6.4.0
|
||||
|
||||
TEST_ARGS ?= ""
|
||||
PYTHON_VERSION ?= `python -c 'import platform; print(".".join(platform.python_version_tuple()[0:2]))'`
|
||||
@@ -22,10 +22,7 @@ test-sanity:
|
||||
ansible-test sanity --docker -v --color --python $(PYTHON_VERSION) $(?TEST_ARGS)
|
||||
|
||||
test-integration:
|
||||
ansible-test integration --docker -v --color --retry-on-error --python $(PYTHON_VERSION) --continue-on-error --diff --coverage $(?TEST_ARGS)
|
||||
|
||||
test-molecule:
|
||||
molecule test
|
||||
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-unit:
|
||||
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.
|
||||
95
README.md
95
README.md
@@ -1,28 +1,50 @@
|
||||
# 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.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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-->
|
||||
## 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.
|
||||
A collection may contain metadata that identifies these versions.
|
||||
PEP440 is the schema used to describe the versions of Ansible.
|
||||
<!--end requires_ansible-->
|
||||
|
||||
## Python Support
|
||||
### Helm Version Compatibility
|
||||
|
||||
* Collection supports 3.6+
|
||||
This collection supports Helm v3.x and newer. Please note that specific modules or certain parameters may have additional version requirements.
|
||||
|
||||
### Python Support
|
||||
|
||||
* Collection supports 3.9+
|
||||
|
||||
Note: Python2 is deprecated from [1st January 2020](https://www.python.org/doc/sunset-python-2/). Please switch to Python3.
|
||||
|
||||
## 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:
|
||||
|
||||
@@ -37,11 +59,6 @@ Name | Description
|
||||
--- | ---
|
||||
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
|
||||
Name | Description
|
||||
--- | ---
|
||||
@@ -55,6 +72,8 @@ 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_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_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_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
|
||||
@@ -68,12 +87,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_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_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-->
|
||||
|
||||
## Installation and Usage
|
||||
|
||||
### Installing the Collection from Ansible Galaxy
|
||||
## Installation
|
||||
|
||||
Before using the Kubernetes collection, you need to install it with the Ansible Galaxy CLI:
|
||||
|
||||
@@ -85,7 +103,7 @@ You can also include it in a `requirements.yml` file and install it via `ansible
|
||||
---
|
||||
collections:
|
||||
- name: kubernetes.core
|
||||
version: 2.2.0
|
||||
version: 6.4.0
|
||||
```
|
||||
|
||||
### Installing the Kubernetes Python Library
|
||||
@@ -94,7 +112,7 @@ Content in this collection requires the [Kubernetes Python client](https://pypi.
|
||||
|
||||
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`:
|
||||
|
||||
@@ -162,10 +180,9 @@ 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.
|
||||
|
||||
## Ansible Turbo mode Tech Preview
|
||||
## Ansible Turbo Mode Tech Preview
|
||||
|
||||
|
||||
The ``kubernetes.core`` collection supports Ansible Turbo mode as a tech preview via the ``cloud.common`` collection. By default, this feature is disabled. To enable Turbo mode, set the environment variable `ENABLE_TURBO_MODE=1` on the managed node. For example:
|
||||
The ``kubernetes.core`` collection supports Ansible Turbo mode as a tech preview via the ``cloud.common`` collection. By default, this feature is disabled. To enable Turbo mode for modules, set the environment variable `ENABLE_TURBO_MODE=1` on the managed node. For example:
|
||||
|
||||
```yaml
|
||||
---
|
||||
@@ -176,14 +193,21 @@ The ``kubernetes.core`` collection supports Ansible Turbo mode as a tech preview
|
||||
...
|
||||
```
|
||||
|
||||
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).
|
||||
|
||||
## Testing and Development
|
||||
## Contributing to this Collection
|
||||
|
||||
If you want to develop new content for this collection or improve what's already here, the easiest way to work on the collection is to clone it into one of the configured [`COLLECTIONS_PATHS`](https://docs.ansible.com/ansible/latest/reference_appendices/config.html#collections-paths), and work on it there.
|
||||
|
||||
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`
|
||||
|
||||
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).
|
||||
@@ -196,7 +220,7 @@ You can run the collection's test suites with the commands:
|
||||
|
||||
### Testing with `molecule`
|
||||
|
||||
There are also integration tests in the `molecule` directory which are meant to be run against a local Kubernetes cluster, e.g. using [KinD](https://kind.sigs.k8s.io) or [Minikube](https://minikube.sigs.k8s.io). To setup a local cluster using KinD and run Molecule:
|
||||
There are also integration tests in the `molecule` directory which are meant to be run against a local Kubernetes cluster, e.g. using [KinD](https://kind.sigs.k8s.io) or [Minikube](https://minikube.sigs.k8s.io). To set up a local cluster using KinD and run Molecule:
|
||||
|
||||
kind create cluster
|
||||
make test-molecule
|
||||
@@ -220,12 +244,35 @@ 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.
|
||||
|
||||
## More Information
|
||||
## Support
|
||||
|
||||
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.
|
||||
<!--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.
|
||||
|
||||
## License
|
||||
|
||||
GNU General Public License v3.0 or later
|
||||
|
||||
See LICENCE to see the full text.
|
||||
See LICENSE to see the full text.
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
kubernetes-client [platform:fedora]
|
||||
openshift-clients [platform:rhel-8]
|
||||
openshift-clients [platform:rhel-9]
|
||||
|
||||
@@ -486,3 +486,720 @@ releases:
|
||||
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`` does 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'
|
||||
6.3.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Add idempotency for ``helm_pull`` module (https://github.com/ansible-collections/kubernetes.core/pull/1055).
|
||||
- Fixed a bug where setting ``K8S_AUTH_VERIFY_SSL=true`` (or any string value)
|
||||
caused the value to be treated as a separate ``kubectl`` command argument.
|
||||
(https://github.com/ansible-collections/kubernetes.core/pull/1049).
|
||||
- Limit supported versions of Helm to <4.0.0 (https://github.com/ansible-collections/kubernetes.core/pull/1039).
|
||||
- Replace passing ``warnings`` to ``exit_json`` with ``AnsibleModule.warn``
|
||||
in the ``k8s_drain``, ``k8s_rollback.py`` and ``k8s_scale.py`` modules as
|
||||
it deprecated in ``ansible-core>=2.19.0`` and will be removed in ``ansible-core>=2.23.0``
|
||||
(https://github.com/ansible-collections/kubernetes.core/pull/1033).
|
||||
- k8s - Fix return block from the module documentation (https://github.com/ansible-collections/kubernetes.core/pull/1056).
|
||||
- meta - Add ``k8s_cluster_info``, ``k8s_json_patch`` and ``k8s_rollback`` to
|
||||
k8s action group (https://github.com/ansible-collections/kubernetes.core/pull/992).
|
||||
deprecated_features:
|
||||
- helm - the ``status.values`` return value has been deprecated and will be
|
||||
removed in a release after 2027-01-08. Use ``status.release_values`` instead
|
||||
(https://github.com/ansible-collections/kubernetes.core/pull/1056).
|
||||
- helm_info - the ``status.values`` return value has been deprecated and will
|
||||
be removed in a release after 2027-01-08. Use ``status.release_values`` instead
|
||||
(https://github.com/ansible-collections/kubernetes.core/pull/1056).
|
||||
minor_changes:
|
||||
- Remove deprecated import from ``ansible.module_utils._text`` (https://github.com/ansible-collections/kubernetes.core/pull/1053).
|
||||
- helm - add ``release_values`` key to ``status`` return value that can be accessed
|
||||
using Jinja2 dot notation (https://github.com/ansible-collections/kubernetes.core/pull/1056).
|
||||
- helm_info - add ``release_values`` key to ``status`` return value that can
|
||||
be accessed using Jinja2 dot notation (https://github.com/ansible-collections/kubernetes.core/pull/1056).
|
||||
release_summary: This release includes bugfixes such as implementing idempotency
|
||||
for the ``helm_pull`` module as well as a security update for selectively
|
||||
redacting sensitive information from kubeconfig.
|
||||
security_fixes:
|
||||
- Selectively redact sensitive info from kubeconfig instead of applying blanket
|
||||
``no_log=True`` (https://github.com/ansible-collections/kubernetes.core/pull/1014).
|
||||
fragments:
|
||||
- 1033-warnings-deprecations.yaml
|
||||
- 20251002-fix-k8s-actiongroup.yaml
|
||||
- 20251007-selective-kubeconfig-redaction.yaml
|
||||
- 20251115-limit-versions-of-helm.yaml
|
||||
- 20251220-fix-K8S_AUTH_VERIFY_SSL-in-kubectl-connecton-plugion.yaml
|
||||
- 20251228-1053-remove-deprecated-import.yaml
|
||||
- 20260107-add-idempodency-for-helm-pull.yaml
|
||||
- 20260108-fix-sanity-failures.yml
|
||||
- 6-3-0.yaml
|
||||
release_date: '2026-02-03'
|
||||
6.4.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Helm - Allow taking ownership of existing Kubernetes resources on the first
|
||||
installation of a Helm release. Previously, the ``take_ownership`` parameter
|
||||
was always disabled during the initial install, preventing resource adoption
|
||||
(https://github.com/ansible-collections/kubernetes.core/pull/1034).
|
||||
minor_changes:
|
||||
- helm_info - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
|
||||
- helm_plugin - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
|
||||
- helm_plugin_info - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
|
||||
- helm_pull - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
|
||||
- helm_registry_auth - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
|
||||
- helm_registry_auth - add new option plain_http to allow insecure http connection
|
||||
when running ``helm registry login`` (https://github.com/ansible-collections/kubernetes.core/pull/1090).
|
||||
- helm_repository - Ensure compatibility with Helm v4 (https://github.com/ansible-collections/kubernetes.core/issues/1038).
|
||||
- k8s_drain - Add support for ``check_mode`` (https://github.com/ansible-collections/kubernetes.core/pull/1086).
|
||||
- k8s_drain - Convert module warnings into informational displays when users
|
||||
explicitly request the deletion of unmanaged pods, pods with local storage,
|
||||
or those managed by a ``DaemonSet`` (https://github.com/ansible-collections/kubernetes.core/issues/1037).
|
||||
release_summary: This release adds Helm v4 compatibility across the Helm modules
|
||||
and improves ``k8s_drain`` with check mode. When you explicitly allow evicting
|
||||
unmanaged pods, pods with local storage, or pods managed by a ``DaemonSet``,
|
||||
those cases are reported as informational output instead of module warnings.
|
||||
fragments:
|
||||
- 20251224-take-ownership-helm-initialization.yaml
|
||||
- 20260203-k8s_drain-warning-fixes.yaml
|
||||
- 20260213-support-helm-v4-for-helm-plugin-modules.yaml
|
||||
- release-6-4-0.yml
|
||||
release_date: '2026-04-22'
|
||||
|
||||
@@ -1,147 +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 installing the cloud.common collection and setting the ``ENABLE_TURBO_MODE`` environment variable.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
The following requirement is needed on the host that executes this module.
|
||||
|
||||
- The ``cloud.common`` collection (https://github.com/ansible-collections/cloud.common)
|
||||
|
||||
You will also need to set the environment variable ``ENABLE_TURBO_MODE=1`` on the managed host. This can be done in the same ways you would usually do so, for example::
|
||||
|
||||
---
|
||||
- hosts: remote
|
||||
environment:
|
||||
ENABLE_TURBO_MODE: 1
|
||||
tasks:
|
||||
...
|
||||
|
||||
|
||||
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 ``async`` 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.
|
||||
@@ -17,7 +17,7 @@ Requirements
|
||||
|
||||
To use the modules, you'll need the following:
|
||||
|
||||
- Ansible 2.9.17 or latest installed
|
||||
- Ansible 2.16.0 or latest installed
|
||||
- `Kubernetes Python client <https://pypi.org/project/kubernetes/>`_ installed on the host that will execute the modules.
|
||||
|
||||
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
.. _ansible_collections.kubernetes.core.docsite.k8s_ansible_inventory:
|
||||
|
||||
*****************************************
|
||||
Using Kubernetes dynamic inventory plugin
|
||||
*****************************************
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Kubernetes dynamic inventory plugin
|
||||
===================================
|
||||
|
||||
|
||||
The best way to interact with your Pods is to use the Kubernetes dynamic inventory plugin, which queries Kubernetes APIs using ``kubectl`` command line available on controller node and tells Ansible what Pods can be managed.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
To use the Kubernetes dynamic inventory plugins, you must install `Kubernetes Python client <https://github.com/kubernetes-client/python>`_, `kubectl <https://github.com/kubernetes/kubectl>`_ on your control node (the host running Ansible).
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install kubernetes
|
||||
|
||||
Please refer to Kubernetes official documentation for `installing kubectl <https://kubernetes.io/docs/tasks/tools/install-kubectl/>`_ on the given operating systems.
|
||||
|
||||
To use this Kubernetes dynamic inventory plugin, you need to enable it first by specifying the following in the ``ansible.cfg`` file:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[inventory]
|
||||
enable_plugins = kubernetes.core.k8s
|
||||
|
||||
Then, create a file that ends in ``.k8s.yml`` or ``.k8s.yaml`` in your working directory.
|
||||
|
||||
The ``kubernetes.core.k8s`` inventory plugin takes in the same authentication information as any other Kubernetes modules.
|
||||
|
||||
Here's an example of a valid inventory file:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
plugin: kubernetes.core.k8s
|
||||
|
||||
Executing ``ansible-inventory --list -i <filename>.k8s.yml`` will create a list of Pods that are ready to be configured using Ansible.
|
||||
|
||||
You can also provide the namespace to gather information about specific pods from the given namespace. For example, to gather information about Pods under the ``test`` namespace you will specify the ``namespaces`` parameter:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
plugin: kubernetes.core.k8s
|
||||
connections:
|
||||
- namespaces:
|
||||
- test
|
||||
|
||||
Using vaulted configuration files
|
||||
=================================
|
||||
|
||||
Since the inventory configuration file contains Kubernetes related sensitive information in plain text, a security risk, you may want to
|
||||
encrypt your entire inventory configuration file.
|
||||
|
||||
You can encrypt a valid inventory configuration file as follows:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ ansible-vault encrypt <filename>.k8s.yml
|
||||
New Vault password:
|
||||
Confirm New Vault password:
|
||||
Encryption successful
|
||||
|
||||
$ echo "MySuperSecretPassw0rd!" > /path/to/vault_password_file
|
||||
|
||||
And you can use this vaulted inventory configuration file using:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ ansible-inventory -i <filename>.k8s.yml --list --vault-password-file=/path/to/vault_password_file
|
||||
|
||||
|
||||
.. seealso::
|
||||
|
||||
`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
|
||||
@@ -54,20 +54,20 @@ In this use case / example, we will create a Pod in the given Kubernetes Cluster
|
||||
- kubernetes.core
|
||||
tasks:
|
||||
- name: Create a pod
|
||||
k8s:
|
||||
kubernetes.core.k8s:
|
||||
state: present
|
||||
definition:
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: "utilitypod-1"
|
||||
namespace: default
|
||||
labels:
|
||||
app: galaxy
|
||||
spec:
|
||||
app: galaxy
|
||||
spec:
|
||||
containers:
|
||||
- name: utilitypod
|
||||
image: busybox
|
||||
- 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.
|
||||
|
||||
|
||||
@@ -13,6 +13,5 @@ To get started, please select one of the following topics.
|
||||
:maxdepth: 1
|
||||
|
||||
kubernetes_scenarios/k8s_intro
|
||||
kubernetes_scenarios/k8s_inventory
|
||||
kubernetes_scenarios/k8s_scenarios
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ Requirements
|
||||
------------
|
||||
The below requirements are needed on the host that executes this module.
|
||||
|
||||
- helm (https://github.com/helm/helm/releases)
|
||||
- helm >= 3.0.0 (https://github.com/helm/helm/releases)
|
||||
- yaml (https://pypi.org/project/PyYAML/)
|
||||
|
||||
|
||||
@@ -105,6 +105,27 @@ Parameters
|
||||
<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>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>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
@@ -127,7 +148,7 @@ Parameters
|
||||
<b>kubeconfig</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: purple">raw</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
@@ -135,6 +156,7 @@ Parameters
|
||||
<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. Added in version 2.4.0.</div>
|
||||
<div style="font-size: small; color: darkgreen"><br/>aliases: kubeconfig_path</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -172,6 +194,32 @@ Parameters
|
||||
<div style="font-size: small; color: darkgreen"><br/>aliases: namespace</div>
|
||||
</td>
|
||||
</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>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
@@ -204,16 +252,23 @@ Examples
|
||||
|
||||
.. 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:
|
||||
name: test
|
||||
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
|
||||
-------------
|
||||
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:
|
||||
Common return values are documented `here <https://docs.ansible.com/projects/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
@@ -270,6 +325,42 @@ Common return values are documented `here <https://docs.ansible.com/ansible/late
|
||||
<br/>
|
||||
</td>
|
||||
</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>
|
||||
<td class="elbow-placeholder"> </td>
|
||||
<td colspan="1">
|
||||
@@ -302,6 +393,40 @@ Common return values are documented `here <https://docs.ansible.com/ansible/late
|
||||
<br/>
|
||||
</td>
|
||||
</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>
|
||||
<td class="elbow-placeholder"> </td>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||
<b>release_values</b>
|
||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">dictionary</span>
|
||||
</div>
|
||||
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.3.0</div>
|
||||
</td>
|
||||
<td>always</td>
|
||||
<td>
|
||||
<div>Dict of Values used to deploy.</div>
|
||||
<br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="elbow-placeholder"> </td>
|
||||
<td colspan="1">
|
||||
@@ -357,12 +482,13 @@ Common return values are documented `here <https://docs.ansible.com/ansible/late
|
||||
<b>values</b>
|
||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">string</span>
|
||||
<span style="color: purple">dictionary</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>always</td>
|
||||
<td>
|
||||
<div>Dict of Values used to deploy</div>
|
||||
<div>This return value has been deprecated and will be removed in a release after 2027-01-08. Use RV(status.release_values) instead.</div>
|
||||
<br/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -25,7 +25,7 @@ Requirements
|
||||
------------
|
||||
The below requirements are needed on the host that executes this module.
|
||||
|
||||
- helm (https://github.com/helm/helm/releases)
|
||||
- helm >= 3.0.0 (https://github.com/helm/helm/releases)
|
||||
- yaml (https://pypi.org/project/PyYAML/)
|
||||
|
||||
|
||||
@@ -36,12 +36,12 @@ Parameters
|
||||
|
||||
<table border=0 cellpadding=0 class="documentation-table">
|
||||
<tr>
|
||||
<th colspan="1">Parameter</th>
|
||||
<th colspan="2">Parameter</th>
|
||||
<th>Choices/<font color="blue">Defaults</font></th>
|
||||
<th width="100%">Comments</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>api_key</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -57,7 +57,7 @@ Parameters
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>atomic</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -76,7 +76,7 @@ Parameters
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>binary_path</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -91,7 +91,7 @@ Parameters
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>ca_cert</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -108,7 +108,7 @@ Parameters
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>chart_ref</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -127,7 +127,7 @@ Parameters
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>chart_repo_url</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -142,7 +142,7 @@ Parameters
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>chart_version</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -157,7 +157,7 @@ Parameters
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>context</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -174,7 +174,7 @@ Parameters
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>create_namespace</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -194,7 +194,32 @@ Parameters
|
||||
</td>
|
||||
</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>
|
||||
<b>disable_hook</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -213,7 +238,7 @@ Parameters
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>force</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -232,7 +257,7 @@ Parameters
|
||||
</td>
|
||||
</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>
|
||||
@@ -249,7 +274,7 @@ Parameters
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>host</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -265,12 +290,35 @@ Parameters
|
||||
</td>
|
||||
</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>
|
||||
<b>kubeconfig</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: purple">raw</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
@@ -278,11 +326,49 @@ Parameters
|
||||
<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. Added in version 2.4.0.</div>
|
||||
<div style="font-size: small; color: darkgreen"><br/>aliases: kubeconfig_path</div>
|
||||
</td>
|
||||
</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>
|
||||
<b>purge</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -301,7 +387,7 @@ Parameters
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>release_name</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -318,7 +404,7 @@ Parameters
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>release_namespace</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -335,7 +421,7 @@ Parameters
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>release_state</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -355,7 +441,7 @@ Parameters
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>release_values</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -372,7 +458,7 @@ Parameters
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>replace</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -394,7 +480,130 @@ Parameters
|
||||
</td>
|
||||
</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">
|
||||
<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>skip_crds</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -414,7 +623,67 @@ Parameters
|
||||
</td>
|
||||
</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>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>
|
||||
<b>update_repo_cache</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -429,11 +698,11 @@ Parameters
|
||||
</ul>
|
||||
</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>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>validate_certs</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -454,7 +723,7 @@ Parameters
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>values_files</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -475,7 +744,7 @@ Parameters
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>wait</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -490,11 +759,12 @@ Parameters
|
||||
</ul>
|
||||
</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>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>wait_timeout</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -506,12 +776,19 @@ Parameters
|
||||
</td>
|
||||
<td>
|
||||
<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>
|
||||
</tr>
|
||||
</table>
|
||||
<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
|
||||
@@ -561,6 +838,22 @@ Examples
|
||||
state: absent
|
||||
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
|
||||
- name: Git clone stable repo on HEAD
|
||||
ansible.builtin.git:
|
||||
@@ -580,6 +873,12 @@ Examples
|
||||
chart_ref: "https://github.com/grafana/helm-charts/releases/download/grafana-5.6.0/grafana-5.6.0.tgz"
|
||||
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
|
||||
- name: Deploy new-relic client chart
|
||||
kubernetes.core.helm:
|
||||
@@ -606,11 +905,22 @@ Examples
|
||||
logging:
|
||||
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
|
||||
-------------
|
||||
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:
|
||||
Common return values are documented `here <https://docs.ansible.com/projects/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
@@ -716,6 +1026,23 @@ Common return values are documented `here <https://docs.ansible.com/ansible/late
|
||||
<br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="elbow-placeholder"> </td>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||
<b>release_values</b>
|
||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">dictionary</span>
|
||||
</div>
|
||||
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.3.0</div>
|
||||
</td>
|
||||
<td>always</td>
|
||||
<td>
|
||||
<div>Dict of Values used to deploy.</div>
|
||||
<br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="elbow-placeholder"> </td>
|
||||
<td colspan="1">
|
||||
@@ -771,12 +1098,13 @@ Common return values are documented `here <https://docs.ansible.com/ansible/late
|
||||
<b>values</b>
|
||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">string</span>
|
||||
<span style="color: purple">dictionary</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>always</td>
|
||||
<td>
|
||||
<div>Dict of Values used to deploy</div>
|
||||
<div>Dict of Values used to deploy.</div>
|
||||
<div>This return value has been deprecated and will be removed in a release after 2027-01-08. Use RV(status.release_values) instead.</div>
|
||||
<br/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -25,7 +25,7 @@ Requirements
|
||||
------------
|
||||
The below requirements are needed on the host that executes this module.
|
||||
|
||||
- helm (https://github.com/helm/helm/releases)
|
||||
- helm >= 3.0.0 (https://github.com/helm/helm/releases)
|
||||
|
||||
|
||||
Parameters
|
||||
@@ -126,7 +126,7 @@ Parameters
|
||||
<b>kubeconfig</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: purple">raw</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
@@ -134,6 +134,7 @@ Parameters
|
||||
<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. Added in version 2.4.0.</div>
|
||||
<div style="font-size: small; color: darkgreen"><br/>aliases: kubeconfig_path</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -195,7 +196,7 @@ Examples
|
||||
|
||||
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:
|
||||
Common return values are documented `here <https://docs.ansible.com/projects/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ Requirements
|
||||
------------
|
||||
The below requirements are needed on the host that executes this module.
|
||||
|
||||
- helm (https://github.com/helm/helm/releases)
|
||||
- helm >= 3.0.0 (https://github.com/helm/helm/releases)
|
||||
|
||||
|
||||
Parameters
|
||||
@@ -126,7 +126,7 @@ Parameters
|
||||
<b>kubeconfig</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: purple">raw</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
@@ -134,6 +134,7 @@ Parameters
|
||||
<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. Added in version 2.4.0.</div>
|
||||
<div style="font-size: small; color: darkgreen"><br/>aliases: kubeconfig_path</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -150,7 +151,7 @@ Parameters
|
||||
</td>
|
||||
<td>
|
||||
<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>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -170,6 +171,23 @@ Parameters
|
||||
<div>Required only if <code>state=present</code>.</div>
|
||||
</td>
|
||||
</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>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
@@ -183,10 +201,12 @@ Parameters
|
||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||
<li>absent</li>
|
||||
<li><div style="color: blue"><b>present</b> ←</div></li>
|
||||
<li>latest</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
<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>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -211,6 +231,28 @@ Parameters
|
||||
<div style="font-size: small; color: darkgreen"><br/>aliases: verify_ssl</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>verify</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">boolean</span>
|
||||
</div>
|
||||
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.4.0</div>
|
||||
</td>
|
||||
<td>
|
||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||
<li>no</li>
|
||||
<li><div style="color: blue"><b>yes</b> ←</div></li>
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
<div>Verify the plugin signature before installing.</div>
|
||||
<div>This option requires helm version >= 4.0.0</div>
|
||||
<div>Used with <em>state=present</em>.</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br/>
|
||||
|
||||
@@ -237,11 +279,22 @@ Examples
|
||||
plugin_name: env
|
||||
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
|
||||
-------------
|
||||
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:
|
||||
Common return values are documented `here <https://docs.ansible.com/projects/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
|
||||
545
docs/kubernetes.core.helm_pull_module.rst
Normal file
545
docs/kubernetes.core.helm_pull_module.rst
Normal file
@@ -0,0 +1,545 @@
|
||||
.. _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.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>force</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">boolean</span>
|
||||
</div>
|
||||
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.3.0</div>
|
||||
</td>
|
||||
<td>
|
||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||
<li>yes</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
<div>Force download of the chart even if it already exists in the destination directory.</div>
|
||||
<div>By default, the module will skip downloading if the chart with the same version already exists for idempotency.</div>
|
||||
<div>When used with O(untar_chart=true), will remove any existing chart directory before extracting.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<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
|
||||
|
||||
- name: Download Chart (force re-download even if exists)
|
||||
kubernetes.core.helm_pull:
|
||||
chart_ref: redis
|
||||
repo_url: https://charts.bitnami.com/bitnami
|
||||
chart_version: '17.0.0'
|
||||
destination: /path/to/chart
|
||||
force: yes
|
||||
|
||||
- name: Download and untar chart (force re-extraction even if directory exists)
|
||||
kubernetes.core.helm_pull:
|
||||
chart_ref: redis
|
||||
repo_url: https://charts.bitnami.com/bitnami
|
||||
chart_version: '17.0.0'
|
||||
destination: /path/to/chart
|
||||
untar_chart: yes
|
||||
force: yes
|
||||
|
||||
|
||||
|
||||
Return Values
|
||||
-------------
|
||||
Common return values are documented `here <https://docs.ansible.com/projects/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<table border=0 cellpadding=0 class="documentation-table">
|
||||
<tr>
|
||||
<th colspan="1">Key</th>
|
||||
<th>Returned</th>
|
||||
<th width="100%">Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||
<b>command</b>
|
||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">string</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>always</td>
|
||||
<td>
|
||||
<div>Full `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>msg</b>
|
||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">string</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>when chart already exists</td>
|
||||
<td>
|
||||
<div>A message indicating the result of the operation.</div>
|
||||
<br/>
|
||||
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">Chart redis version 17.0.0 already exists in destination directory</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<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)
|
||||
354
docs/kubernetes.core.helm_registry_auth_module.rst
Normal file
354
docs/kubernetes.core.helm_registry_auth_module.rst
Normal file
@@ -0,0 +1,354 @@
|
||||
.. _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>plain_http</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">boolean</span>
|
||||
</div>
|
||||
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.4.0</div>
|
||||
</td>
|
||||
<td>
|
||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||
<li>yes</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
<div>Use insecure HTTP connections for <code>helm registry login</code>.</div>
|
||||
<div>Requires Helm >= 3.18.0</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>state</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">string</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||
<li><div style="color: blue"><b>present</b> ←</div></li>
|
||||
<li>absent</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
<div>Desired state of the registry.</div>
|
||||
<div>If set to V(present) attempt to log in to the remote registry server using the URL specified in O(host).</div>
|
||||
<div>If set to V(absent) attempt to log out from the remote registry server using the URL specified in O(host).</div>
|
||||
<div>As helm >= 3.18.0 reports successful logout even if the user is not logged in, this module will report a change regardless of the current state.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>username</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">string</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<div>Username for the registry.</div>
|
||||
<div style="font-size: small; color: darkgreen"><br/>aliases: repo_username</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br/>
|
||||
|
||||
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
- name: Login to remote registry
|
||||
kubernetes.core.helm_registry_auth:
|
||||
username: admin
|
||||
password: "sample_password"
|
||||
host: localhost:5000
|
||||
|
||||
- name: Logout from remote registry
|
||||
kubernetes.core.helm_registry_auth:
|
||||
state: absent
|
||||
host: localhost:5000
|
||||
|
||||
|
||||
|
||||
Return Values
|
||||
-------------
|
||||
Common return values are documented `here <https://docs.ansible.com/projects/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<table border=0 cellpadding=0 class="documentation-table">
|
||||
<tr>
|
||||
<th colspan="1">Key</th>
|
||||
<th>Returned</th>
|
||||
<th width="100%">Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||
<b>command</b>
|
||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">string</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>always</td>
|
||||
<td>
|
||||
<div>Full <code>helm</code> command executed</div>
|
||||
<br/>
|
||||
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">/usr/local/bin/helm registry login oci-registry.domain.example --username=admin --password-stdin --insecure</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||
<b>failed</b>
|
||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">boolean</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>always</td>
|
||||
<td>
|
||||
<div>Indicate if the <code>helm</code> command failed</div>
|
||||
<br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||
<b>stderr</b>
|
||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">string</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>always</td>
|
||||
<td>
|
||||
<div>Full <code>helm</code> command stderr, in case you want to display it or examine the event log. Please be note that helm binnary may print messages to stderr even if the command is successful.</div>
|
||||
<br/>
|
||||
<div style="font-size: smaller"><b>Sample:</b></div>
|
||||
<div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">Login Succeeded\n</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||
<b>stderr_lines</b>
|
||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">list</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>always</td>
|
||||
<td>
|
||||
<div>Full <code>helm</code> command stderr, in case you want to display it or examine the event log</div>
|
||||
<br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||
<b>stdout</b>
|
||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">string</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>always</td>
|
||||
<td>
|
||||
<div>Full <code>helm</code> command stdout, in case you want to display it or examine the event log</div>
|
||||
<br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="return-"></div>
|
||||
<b>stout_lines</b>
|
||||
<a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
|
||||
<div style="font-size: small">
|
||||
<span style="color: purple">list</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>always</td>
|
||||
<td>
|
||||
<div>Full <code>helm</code> command stdout, in case you want to display it or examine the event log</div>
|
||||
<br/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br/><br/>
|
||||
|
||||
|
||||
Status
|
||||
------
|
||||
|
||||
|
||||
Authors
|
||||
~~~~~~~
|
||||
|
||||
- Yuriy Novostavskiy (@yurnov)
|
||||
@@ -25,7 +25,7 @@ Requirements
|
||||
------------
|
||||
The below requirements are needed on the host that executes this module.
|
||||
|
||||
- helm (https://github.com/helm/helm/releases)
|
||||
- helm >= 3.0.0 (https://github.com/helm/helm/releases)
|
||||
- yaml (https://pypi.org/project/PyYAML/)
|
||||
|
||||
|
||||
@@ -40,6 +40,22 @@ Parameters
|
||||
<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>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>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
@@ -55,6 +71,138 @@ Parameters
|
||||
<div>The path of a helm binary to use.</div>
|
||||
</td>
|
||||
</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>
|
||||
<td colspan="1">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
@@ -142,6 +290,27 @@ Parameters
|
||||
<div style="font-size: small; color: darkgreen"><br/>aliases: username</div>
|
||||
</td>
|
||||
</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>
|
||||
<br/>
|
||||
|
||||
@@ -167,7 +336,7 @@ Examples
|
||||
|
||||
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:
|
||||
Common return values are documented `here <https://docs.ansible.com/projects/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
|
||||
@@ -20,6 +20,13 @@ Synopsis
|
||||
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
The below requirements are needed on the host that executes this module.
|
||||
|
||||
- helm >= 3.0.0 (https://github.com/helm/helm/releases)
|
||||
- yaml (https://pypi.org/project/PyYAML/)
|
||||
|
||||
|
||||
Parameters
|
||||
----------
|
||||
@@ -28,12 +35,12 @@ Parameters
|
||||
|
||||
<table border=0 cellpadding=0 class="documentation-table">
|
||||
<tr>
|
||||
<th colspan="1">Parameter</th>
|
||||
<th colspan="2">Parameter</th>
|
||||
<th>Choices/<font color="blue">Defaults</font></th>
|
||||
<th width="100%">Comments</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>binary_path</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -48,7 +55,7 @@ Parameters
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>chart_ref</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -67,7 +74,7 @@ Parameters
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>chart_repo_url</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -82,7 +89,7 @@ Parameters
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>chart_version</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -97,7 +104,50 @@ Parameters
|
||||
</td>
|
||||
</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>
|
||||
<b>include_crds</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -116,7 +166,27 @@ Parameters
|
||||
</td>
|
||||
</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>
|
||||
<b>output_dir</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -132,7 +202,61 @@ Parameters
|
||||
</td>
|
||||
</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>
|
||||
<b>release_values</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -149,7 +273,85 @@ Parameters
|
||||
</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">
|
||||
<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>
|
||||
<b>update_repo_cache</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -168,7 +370,7 @@ Parameters
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1">
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
<b>values_files</b>
|
||||
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||
@@ -213,11 +415,29 @@ Examples
|
||||
dest: myfile.yaml
|
||||
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
|
||||
-------------
|
||||
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:
|
||||
Common return values are documented `here <https://docs.ansible.com/projects/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
|
||||
|
||||
.. raw:: html
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@ Requirements
|
||||
------------
|
||||
The below requirements are needed on the host that executes this module.
|
||||
|
||||
- python >= 3.6
|
||||
- kubernetes >= 12.0.0
|
||||
- python >= 3.9
|
||||
- kubernetes >= 24.2.0
|
||||
- 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>
|
||||
</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>
|
||||
@@ -168,9 +203,29 @@ Parameters
|
||||
</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>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>
|
||||
|
||||
@@ -25,8 +25,8 @@ Requirements
|
||||
------------
|
||||
The below requirements are needed on the host that executes this module.
|
||||
|
||||
- python >= 3.6
|
||||
- kubernetes >= 12.0.0
|
||||
- python >= 3.9
|
||||
- kubernetes >= 24.2.0
|
||||
|
||||
|
||||
Parameters
|
||||
@@ -167,6 +167,41 @@ Parameters
|
||||
<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>
|
||||
@@ -180,6 +215,7 @@ Parameters
|
||||
</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>
|
||||
@@ -236,6 +272,25 @@ Parameters
|
||||
<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>
|
||||
@@ -457,6 +512,7 @@ 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.
|
||||
|
||||
|
||||
@@ -503,7 +559,7 @@ Examples
|
||||
state: from_pod
|
||||
|
||||
# copy content into a file in the remote pod
|
||||
- name: Copy /tmp/foo from a remote pod to /tmp/bar locally
|
||||
- name: Copy content into a file in the remote pod
|
||||
kubernetes.core.k8s_cp:
|
||||
state: to_pod
|
||||
namespace: some-namespace
|
||||
|
||||
@@ -29,8 +29,8 @@ Requirements
|
||||
------------
|
||||
The below requirements are needed on the host that executes this module.
|
||||
|
||||
- python >= 3.6
|
||||
- kubernetes >= 12.0.0
|
||||
- python >= 3.9
|
||||
- kubernetes >= 24.2.0
|
||||
|
||||
|
||||
Parameters
|
||||
@@ -132,6 +132,7 @@ Parameters
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<b>Default:</b><br/><div style="color: blue">{}</div>
|
||||
</td>
|
||||
<td>
|
||||
<div>Specify options to delete pods.</div>
|
||||
@@ -140,6 +141,27 @@ Parameters
|
||||
</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>
|
||||
@@ -266,6 +288,41 @@ Parameters
|
||||
<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>
|
||||
@@ -279,6 +336,7 @@ Parameters
|
||||
</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>
|
||||
@@ -298,6 +356,25 @@ Parameters
|
||||
<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>
|
||||
@@ -337,6 +414,25 @@ Parameters
|
||||
<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>
|
||||
@@ -499,14 +595,15 @@ Examples
|
||||
kubernetes.core.k8s_drain:
|
||||
state: drain
|
||||
name: foo
|
||||
force: yes
|
||||
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
|
||||
terminate_grace_period: 900
|
||||
|
||||
- name: Mark node "foo" as schedulable.
|
||||
kubernetes.core.k8s_drain:
|
||||
@@ -518,6 +615,14 @@ Examples
|
||||
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
|
||||
|
||||
@@ -25,8 +25,8 @@ Requirements
|
||||
------------
|
||||
The below requirements are needed on the host that executes this module.
|
||||
|
||||
- python >= 3.6
|
||||
- kubernetes >= 12.0.0
|
||||
- python >= 3.9
|
||||
- kubernetes >= 24.2.0
|
||||
- PyYAML >= 3.11
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ Parameters
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<div>The command to execute</div>
|
||||
<div>The command to execute.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -134,6 +134,7 @@ Parameters
|
||||
<td>
|
||||
<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>If not specified, will choose the first container from the given pod as kubectl cmdline does.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -166,6 +167,41 @@ Parameters
|
||||
<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>
|
||||
@@ -179,6 +215,7 @@ Parameters
|
||||
</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>
|
||||
@@ -195,7 +232,26 @@ Parameters
|
||||
<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>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -250,7 +306,7 @@ Parameters
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<div>The pod name</div>
|
||||
<div>The pod name.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -267,7 +323,7 @@ Parameters
|
||||
<td>
|
||||
<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>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>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -414,6 +470,13 @@ Examples
|
||||
msg: "cmd failed"
|
||||
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"
|
||||
|
||||
|
||||
|
||||
Return Values
|
||||
|
||||
@@ -28,8 +28,8 @@ Requirements
|
||||
------------
|
||||
The below requirements are needed on the host that executes this module.
|
||||
|
||||
- python >= 3.6
|
||||
- kubernetes >= 12.0.0
|
||||
- python >= 3.9
|
||||
- kubernetes >= 24.2.0
|
||||
- PyYAML >= 3.11
|
||||
|
||||
|
||||
@@ -153,11 +153,30 @@ Parameters
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<b>Default:</b><br/><div style="color: blue">[]</div>
|
||||
</td>
|
||||
<td>
|
||||
<div>List of field selectors to use to filter results</div>
|
||||
</td>
|
||||
</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>
|
||||
<td colspan="2">
|
||||
<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>
|
||||
</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>
|
||||
@@ -205,6 +259,7 @@ Parameters
|
||||
</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>
|
||||
@@ -219,6 +274,7 @@ Parameters
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<b>Default:</b><br/><div style="color: blue">[]</div>
|
||||
</td>
|
||||
<td>
|
||||
<div>List of label selectors to use to filter results</div>
|
||||
@@ -260,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>
|
||||
</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>
|
||||
@@ -626,6 +701,21 @@ Examples
|
||||
wait_sleep: 10
|
||||
wait_timeout: 360
|
||||
|
||||
- name: Wait for OpenShift bootstrap to complete
|
||||
kubernetes.core.k8s_info:
|
||||
api_version: v1
|
||||
kind: ConfigMap
|
||||
name: bootstrap
|
||||
namespace: kube-system
|
||||
register: ocp_bootstrap_status
|
||||
until: >
|
||||
ocp_bootstrap_status.resources is defined and
|
||||
(ocp_bootstrap_status.resources | length > 0) and
|
||||
(ocp_bootstrap_status.resources[0].data.status is defined) and
|
||||
(ocp_bootstrap_status.resources[0].data.status == 'complete')
|
||||
retries: 60
|
||||
delay: 15
|
||||
|
||||
|
||||
|
||||
Return Values
|
||||
|
||||
@@ -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.
|
||||
@@ -27,8 +27,8 @@ Requirements
|
||||
------------
|
||||
The below requirements are needed on the host that executes this module.
|
||||
|
||||
- python >= 3.6
|
||||
- kubernetes >= 12.0.0
|
||||
- python >= 3.9
|
||||
- kubernetes >= 24.2.0
|
||||
- PyYAML >= 3.11
|
||||
- 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>
|
||||
</td>
|
||||
</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>
|
||||
<td colspan="2">
|
||||
<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>
|
||||
</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>
|
||||
@@ -185,6 +239,7 @@ Parameters
|
||||
</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>
|
||||
@@ -221,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>
|
||||
</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>
|
||||
@@ -559,7 +633,7 @@ Examples
|
||||
path: /metadata/labels/app
|
||||
value: myapp
|
||||
- op: replace
|
||||
patch: /spec/containers/0/image
|
||||
path: /spec/containers/0/image
|
||||
value: nginx
|
||||
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@ Requirements
|
||||
------------
|
||||
The below requirements are needed on the host that executes this module.
|
||||
|
||||
- python >= 3.6
|
||||
- kubernetes >= 12.0.0
|
||||
- python >= 3.9
|
||||
- kubernetes >= 24.2.0
|
||||
- PyYAML >= 3.11
|
||||
|
||||
|
||||
@@ -44,6 +44,27 @@ Parameters
|
||||
<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>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>
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
@@ -141,7 +162,8 @@ Parameters
|
||||
<td>
|
||||
<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 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>
|
||||
</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>
|
||||
</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>
|
||||
@@ -205,6 +262,7 @@ Parameters
|
||||
</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>
|
||||
@@ -219,6 +277,7 @@ Parameters
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<b>Default:</b><br/><div style="color: blue">[]</div>
|
||||
</td>
|
||||
<td>
|
||||
<div>List of label selectors to use to filter results</div>
|
||||
@@ -260,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>
|
||||
</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>
|
||||
@@ -299,6 +377,26 @@ Parameters
|
||||
<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>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>
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
@@ -400,6 +498,22 @@ Parameters
|
||||
<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>
|
||||
<td colspan="2">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
@@ -484,8 +598,16 @@ Examples
|
||||
kind: DeploymentConfig
|
||||
namespace: testing
|
||||
name: example
|
||||
tail_lines: 100
|
||||
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
|
||||
|
||||
@@ -26,8 +26,8 @@ Requirements
|
||||
------------
|
||||
The below requirements are needed on the local Ansible controller node that executes this lookup.
|
||||
|
||||
- python >= 3.6
|
||||
- kubernetes >= 12.0.0
|
||||
- python >= 3.9
|
||||
- kubernetes >= 24.2.0
|
||||
- PyYAML >= 3.11
|
||||
|
||||
|
||||
@@ -438,106 +438,28 @@ Common return values are documented `here <https://docs.ansible.com/ansible/late
|
||||
|
||||
<table border=0 cellpadding=0 class="documentation-table">
|
||||
<tr>
|
||||
<th colspan="2">Key</th>
|
||||
<th colspan="1">Key</th>
|
||||
<th>Returned</th>
|
||||
<th width="100%">Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<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">complex</span>
|
||||
<span style="color: purple">list</span>
|
||||
/ <span style="color: purple">elements=dictionary</span>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
<td>
|
||||
<div>One ore more object definitions returned from the API.</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': {'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>
|
||||
</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/>
|
||||
|
||||
@@ -549,8 +471,8 @@ Status
|
||||
Authors
|
||||
~~~~~~~
|
||||
|
||||
- Chris Houseknecht <@chouseknecht>
|
||||
- Fabian von Feilitzsch <@fabianvf>
|
||||
- Chris Houseknecht (@chouseknecht)
|
||||
- Fabian von Feilitzsch (@fabianvf)
|
||||
|
||||
|
||||
.. hint::
|
||||
|
||||
@@ -29,8 +29,8 @@ Requirements
|
||||
------------
|
||||
The below requirements are needed on the host that executes this module.
|
||||
|
||||
- python >= 3.6
|
||||
- kubernetes >= 12.0.0
|
||||
- python >= 3.9
|
||||
- kubernetes >= 24.2.0
|
||||
- PyYAML >= 3.11
|
||||
- jsonpatch
|
||||
|
||||
@@ -121,7 +121,7 @@ Parameters
|
||||
<td>
|
||||
<div><code>apply</code> compares the desired resource definition with the previously supplied resource definition, ignoring properties that are automatically generated</div>
|
||||
<div><code>apply</code> works better with Services than 'force=yes'</div>
|
||||
<div>mutually exclusive with <code>merge_type</code></div>
|
||||
<div>Mutually exclusive with <code>merge_type</code>.</div>
|
||||
</td>
|
||||
</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>
|
||||
</td>
|
||||
</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>
|
||||
<td colspan="3">
|
||||
<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>
|
||||
</td>
|
||||
</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>
|
||||
<td colspan="3">
|
||||
<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>
|
||||
</td>
|
||||
</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>
|
||||
<td colspan="3">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
@@ -382,6 +479,7 @@ Parameters
|
||||
</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>
|
||||
@@ -414,18 +512,17 @@ Parameters
|
||||
</td>
|
||||
<td>
|
||||
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||
<li>json</li>
|
||||
<li>merge</li>
|
||||
<li>strategic-merge</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
<div>Whether to override the default patch merge approach with a specific type. By default, the strategic merge will typically be used.</div>
|
||||
<div>For example, Custom Resource Definitions typically aren'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>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><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>Mutually exclusive with <code>apply</code>.</div>
|
||||
<div><em>merge_type=json</em> has been removed in version 4.0.0. Please use <span class='module'>kubernetes.core.k8s_json_patch</span> instead.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -464,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>
|
||||
</td>
|
||||
</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>
|
||||
<td colspan="3">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
@@ -605,6 +721,63 @@ Parameters
|
||||
<div style="font-size: small; color: darkgreen"><br/>aliases: definition, inline</div>
|
||||
</td>
|
||||
</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>
|
||||
<td colspan="3">
|
||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||
@@ -619,7 +792,8 @@ Parameters
|
||||
<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>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>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -981,6 +1155,14 @@ Examples
|
||||
state: present
|
||||
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
|
||||
kubernetes.core.k8s:
|
||||
state: present
|
||||
@@ -998,10 +1180,10 @@ Examples
|
||||
kubernetes.core.k8s:
|
||||
state: present
|
||||
template:
|
||||
- path: '/testing/deployment_one.j2'
|
||||
- path: '/testing/deployment_two.j2'
|
||||
variable_start_string: '[['
|
||||
variable_end_string: ']]'
|
||||
- path: '/testing/deployment_one.j2'
|
||||
- path: '/testing/deployment_two.j2'
|
||||
variable_start_string: '[['
|
||||
variable_end_string: ']]'
|
||||
|
||||
- name: fail on validation errors
|
||||
kubernetes.core.k8s:
|
||||
@@ -1058,6 +1240,41 @@ Examples
|
||||
labels:
|
||||
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
|
||||
|
||||
@@ -27,8 +27,8 @@ Requirements
|
||||
------------
|
||||
The below requirements are needed on the host that executes this module.
|
||||
|
||||
- python >= 3.6
|
||||
- kubernetes >= 12.0.0
|
||||
- python >= 3.9
|
||||
- kubernetes >= 24.2.0
|
||||
- PyYAML >= 3.11
|
||||
|
||||
|
||||
@@ -152,6 +152,7 @@ Parameters
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<b>Default:</b><br/><div style="color: blue">[]</div>
|
||||
</td>
|
||||
<td>
|
||||
<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>
|
||||
</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>
|
||||
@@ -203,6 +239,7 @@ Parameters
|
||||
</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>
|
||||
@@ -217,6 +254,7 @@ Parameters
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<b>Default:</b><br/><div style="color: blue">[]</div>
|
||||
</td>
|
||||
<td>
|
||||
<div>List of label selectors to use to filter results.</div>
|
||||
@@ -258,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>
|
||||
</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>
|
||||
|
||||
@@ -25,8 +25,8 @@ Requirements
|
||||
------------
|
||||
The below requirements are needed on the host that executes this module.
|
||||
|
||||
- python >= 3.6
|
||||
- kubernetes >= 12.0.0
|
||||
- python >= 3.9
|
||||
- kubernetes >= 24.2.0
|
||||
- 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>
|
||||
</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>
|
||||
@@ -220,6 +255,7 @@ Parameters
|
||||
</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>
|
||||
@@ -235,6 +271,7 @@ Parameters
|
||||
<div style="font-style: italic; font-size: small; color: darkgreen">added in 2.0.0</div>
|
||||
</td>
|
||||
<td>
|
||||
<b>Default:</b><br/><div style="color: blue">[]</div>
|
||||
</td>
|
||||
<td>
|
||||
<div>List of label selectors to use to filter results.</div>
|
||||
@@ -276,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>
|
||||
</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>
|
||||
@@ -462,7 +518,8 @@ Parameters
|
||||
<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>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>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
@@ -24,8 +24,8 @@ Requirements
|
||||
------------
|
||||
The below requirements are needed on the host that executes this module.
|
||||
|
||||
- python >= 3.6
|
||||
- kubernetes >= 12.0.0
|
||||
- python >= 3.9
|
||||
- kubernetes >= 24.2.0
|
||||
|
||||
|
||||
Parameters
|
||||
@@ -172,6 +172,41 @@ Parameters
|
||||
<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>
|
||||
@@ -185,6 +220,7 @@ Parameters
|
||||
</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>
|
||||
@@ -245,6 +281,25 @@ Parameters
|
||||
<div>Use to specify a Service object namespace.</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>
|
||||
@@ -433,7 +488,8 @@ Parameters
|
||||
<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>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>
|
||||
</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>
|
||||
<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>
|
||||
</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
|
||||
~~~~~~~
|
||||
|
||||
- xuxinkun
|
||||
- xuxinkun (@xuxinkun)
|
||||
|
||||
|
||||
.. hint::
|
||||
|
||||
@@ -77,6 +77,44 @@ Parameters
|
||||
<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>
|
||||
@@ -112,17 +150,29 @@ Examples
|
||||
.. code-block:: yaml
|
||||
|
||||
- name: Run lookup using kustomize
|
||||
set_fact:
|
||||
ansible.builtin.set_fact:
|
||||
resources: "{{ lookup('kubernetes.core.kustomize', binary_path='/path/to/kustomize') }}"
|
||||
|
||||
- name: Run lookup using kubectl kustomize
|
||||
set_fact:
|
||||
ansible.builtin.set_fact:
|
||||
resources: "{{ lookup('kubernetes.core.kustomize', binary_path='/path/to/kubectl') }}"
|
||||
|
||||
- name: Create kubernetes resources for lookup output
|
||||
k8s:
|
||||
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
|
||||
@@ -133,106 +183,27 @@ Common return values are documented `here <https://docs.ansible.com/ansible/late
|
||||
|
||||
<table border=0 cellpadding=0 class="documentation-table">
|
||||
<tr>
|
||||
<th colspan="2">Key</th>
|
||||
<th colspan="1">Key</th>
|
||||
<th>Returned</th>
|
||||
<th width="100%">Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<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">complex</span>
|
||||
<span style="color: purple">string</span>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
<td>
|
||||
<div>One ore more object definitions returned from the tool execution.</div>
|
||||
<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>
|
||||
<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/>
|
||||
|
||||
@@ -244,7 +215,7 @@ Status
|
||||
Authors
|
||||
~~~~~~~
|
||||
|
||||
- Aubin Bikouo <@abikouo>
|
||||
- Aubin Bikouo (@abikouo)
|
||||
|
||||
|
||||
.. hint::
|
||||
|
||||
@@ -9,8 +9,8 @@ authors:
|
||||
- mmazur (https://github.com/mmazur)
|
||||
- jamescassell (https://github.com/jamescassell)
|
||||
description: Kubernetes Collection for Ansible.
|
||||
documentation: ''
|
||||
homepage: ''
|
||||
documentation: ""
|
||||
homepage: ""
|
||||
issues: https://github.com/ansible-collections/kubernetes.core/issues
|
||||
license_file: LICENSE
|
||||
namespace: kubernetes
|
||||
@@ -25,7 +25,7 @@ tags:
|
||||
- openshift
|
||||
- okd
|
||||
- cluster
|
||||
version: 2.2.0
|
||||
version: 6.4.0
|
||||
build_ignore:
|
||||
- .DS_Store
|
||||
- '*.tar.gz'
|
||||
- "*.tar.gz"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
requires_ansible: '>=2.9.17'
|
||||
requires_ansible: '>=2.16.0'
|
||||
|
||||
action_groups:
|
||||
helm:
|
||||
@@ -8,50 +8,26 @@ action_groups:
|
||||
- helm_repository
|
||||
k8s:
|
||||
- k8s
|
||||
- k8s_exec
|
||||
- k8s_facts
|
||||
- k8s_info
|
||||
- k8s_log
|
||||
- k8s_scale
|
||||
- k8s_service
|
||||
- k8s_cluster_info
|
||||
- k8s_cp
|
||||
- k8s_drain
|
||||
- k8s_exec
|
||||
- k8s_info
|
||||
- k8s_json_patch
|
||||
- k8s_log
|
||||
- k8s_rollback
|
||||
- k8s_scale
|
||||
- k8s_service
|
||||
|
||||
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_cp:
|
||||
redirect: kubernetes.core.k8s_info
|
||||
k8s_drain:
|
||||
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:
|
||||
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:
|
||||
k8s_auth:
|
||||
redirect: community.okd.k8s_auth
|
||||
|
||||
@@ -1,292 +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 validate.yml
|
||||
include_tasks:
|
||||
file: tasks/validate.yml
|
||||
apply:
|
||||
tags: [ validate, 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, k8s ]
|
||||
tags:
|
||||
- always
|
||||
|
||||
- name: Include label_selectors.yml
|
||||
include_tasks:
|
||||
file: tasks/label_selectors.yml
|
||||
apply:
|
||||
tags: [ label_selectors, k8s ]
|
||||
tags:
|
||||
- always
|
||||
|
||||
- name: Include diff.yml
|
||||
include_tasks:
|
||||
file: tasks/diff.yml
|
||||
apply:
|
||||
tags: [ diff, k8s ]
|
||||
tags:
|
||||
- always
|
||||
|
||||
- name: Include lookup_kustomize.yml
|
||||
include_tasks:
|
||||
file: tasks/lookup_kustomize.yml
|
||||
apply:
|
||||
tags: [ lookup_kustomize, k8s ]
|
||||
tags:
|
||||
- always
|
||||
|
||||
roles:
|
||||
- role: helm
|
||||
tags:
|
||||
- helm
|
||||
|
||||
- role: k8scopy
|
||||
tags:
|
||||
- copy
|
||||
- k8s
|
||||
|
||||
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,39 +0,0 @@
|
||||
---
|
||||
driver:
|
||||
name: delegated
|
||||
options:
|
||||
managed: false
|
||||
login_cmd_template: 'docker exec -ti {instance} bash'
|
||||
ansible_connection_options:
|
||||
ansible_connection: docker
|
||||
platforms:
|
||||
- name: instance-kind
|
||||
provisioner:
|
||||
name: ansible
|
||||
log: true
|
||||
config_options:
|
||||
inventory:
|
||||
enable_plugins: kubernetes.core.k8s,yaml
|
||||
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
|
||||
- syntax
|
||||
- prepare
|
||||
- converge
|
||||
- verify
|
||||
dependency:
|
||||
name: galaxy
|
||||
options:
|
||||
requirements-file: requirements.yml
|
||||
@@ -1,12 +0,0 @@
|
||||
---
|
||||
- name: Prepare
|
||||
hosts: localhost
|
||||
connection: local
|
||||
|
||||
collections:
|
||||
- kubernetes.core
|
||||
|
||||
tasks:
|
||||
- name: Include drain.yml
|
||||
include_tasks:
|
||||
file: tasks/drain.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,45 +0,0 @@
|
||||
---
|
||||
- name: Ensure helm is not installed
|
||||
file:
|
||||
path: "{{ item }}"
|
||||
state: absent
|
||||
with_items:
|
||||
- "/tmp/helm"
|
||||
|
||||
- name: Check failed if helm is not installed
|
||||
include_tasks: test_helm_not_installed.yml
|
||||
|
||||
- name: "Install {{ helm_version }}"
|
||||
include_tasks: install.yml
|
||||
|
||||
- name: "Ensure we honor the environment variables"
|
||||
include_tasks: test_read_envvars.yml
|
||||
|
||||
- name: tests_repository
|
||||
include_tasks: tests_repository.yml
|
||||
|
||||
- name: Deploy charts
|
||||
include_tasks: "tests_chart/{{ test_chart_type }}.yml"
|
||||
loop_control:
|
||||
loop_var: test_chart_type
|
||||
with_items:
|
||||
- from_local_path
|
||||
- from_repository
|
||||
- from_url
|
||||
|
||||
- name: Test helm plugin
|
||||
include_tasks: tests_helm_plugin.yml
|
||||
|
||||
- name: Test helm diff
|
||||
include_tasks: tests_helm_diff.yml
|
||||
|
||||
# https://github.com/ansible-collections/community.kubernetes/issues/296
|
||||
- name: Test Skip CRDS feature in helm chart install
|
||||
include_tasks: test_crds.yml
|
||||
|
||||
- name: Clean helm install
|
||||
file:
|
||||
path: "{{ item }}"
|
||||
state: absent
|
||||
with_items:
|
||||
- "/tmp/helm/"
|
||||
@@ -1,100 +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:
|
||||
binary_path: "{{ helm_binary }}"
|
||||
chart_ref: "/tmp/helm_test_crds/{{ test_chart }}"
|
||||
namespace: "{{ helm_namespace }}"
|
||||
name: test-crds
|
||||
skip_crds: true
|
||||
register: install
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- install is changed
|
||||
- install.status.name == "test-crds"
|
||||
|
||||
- name: Fail to create custom resource
|
||||
k8s:
|
||||
definition:
|
||||
apiVersion: 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:
|
||||
binary_path: "{{ helm_binary }}"
|
||||
namespace: "{{ helm_namespace }}"
|
||||
name: test-crds
|
||||
state: absent
|
||||
|
||||
- name: Install chart with CRDs
|
||||
helm:
|
||||
binary_path: "{{ helm_binary }}"
|
||||
chart_ref: "/tmp/helm_test_crds/{{ test_chart }}"
|
||||
namespace: "{{ helm_namespace }}"
|
||||
name: test-crds
|
||||
|
||||
- name: Create custom resource
|
||||
k8s:
|
||||
definition:
|
||||
apiVersion: 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,21 +0,0 @@
|
||||
---
|
||||
- name: Add chart repo
|
||||
helm_repository:
|
||||
binary_path: "{{ helm_binary }}"
|
||||
name: test_helm
|
||||
repo_url: "{{ chart_test_repo }}"
|
||||
|
||||
- name: Install Chart from repository
|
||||
include_tasks: "../tests_chart.yml"
|
||||
vars:
|
||||
source: repository
|
||||
chart_source: "test_helm/{{ chart_test }}"
|
||||
chart_source_version: "{{ chart_test_version }}"
|
||||
chart_source_version_upgrade: "{{ chart_test_version_upgrade }}"
|
||||
|
||||
- name: Add chart repo
|
||||
helm_repository:
|
||||
binary_path: "{{ helm_binary }}"
|
||||
name: test_helm
|
||||
repo_url: "{{ chart_test_repo }}"
|
||||
state: absent
|
||||
@@ -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,153 +0,0 @@
|
||||
---
|
||||
- name: Test helm diff functionality
|
||||
vars:
|
||||
test_chart_ref: "/tmp/test-chart"
|
||||
|
||||
block:
|
||||
- name: Install helm diff
|
||||
helm_plugin:
|
||||
binary_path: "{{ helm_binary }}"
|
||||
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:
|
||||
binary_path: "{{ helm_binary }}"
|
||||
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,119 +0,0 @@
|
||||
---
|
||||
- name: Install env plugin in check mode
|
||||
helm_plugin:
|
||||
binary_path: "{{ helm_binary }}"
|
||||
state: present
|
||||
plugin_path: https://github.com/adamreese/helm-env
|
||||
register: check_install_env
|
||||
check_mode: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- check_install_env.changed
|
||||
|
||||
- name: Install env plugin
|
||||
helm_plugin:
|
||||
binary_path: "{{ helm_binary }}"
|
||||
state: present
|
||||
plugin_path: https://github.com/adamreese/helm-env
|
||||
register: install_env
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- install_env.changed
|
||||
|
||||
- name: Gather info about all plugin
|
||||
helm_plugin_info:
|
||||
binary_path: "{{ helm_binary }}"
|
||||
register: plugin_info
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- plugin_info.plugin_list is defined
|
||||
|
||||
- name: Install env plugin again
|
||||
helm_plugin:
|
||||
binary_path: "{{ helm_binary }}"
|
||||
state: present
|
||||
plugin_path: https://github.com/adamreese/helm-env
|
||||
register: install_env
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- not install_env.changed
|
||||
|
||||
- name: Uninstall env plugin in check mode
|
||||
helm_plugin:
|
||||
binary_path: "{{ helm_binary }}"
|
||||
state: absent
|
||||
plugin_name: env
|
||||
register: check_uninstall_env
|
||||
check_mode: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- check_uninstall_env.changed
|
||||
|
||||
- name: Uninstall env plugin
|
||||
helm_plugin:
|
||||
binary_path: "{{ helm_binary }}"
|
||||
state: absent
|
||||
plugin_name: env
|
||||
register: uninstall_env
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- uninstall_env.changed
|
||||
|
||||
- name: Uninstall env plugin again
|
||||
helm_plugin:
|
||||
binary_path: "{{ helm_binary }}"
|
||||
state: absent
|
||||
plugin_name: env
|
||||
register: uninstall_env
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- not uninstall_env.changed
|
||||
|
||||
# https://github.com/ansible-collections/community.kubernetes/issues/399
|
||||
- block:
|
||||
- name: Copy required plugin files
|
||||
copy:
|
||||
src: "files/sample_plugin"
|
||||
dest: "/tmp/helm_plugin_test/"
|
||||
|
||||
- name: Install sample_plugin from the directory
|
||||
helm_plugin:
|
||||
binary_path: "{{ helm_binary }}"
|
||||
state: present
|
||||
plugin_path: "/tmp/helm_plugin_test/sample_plugin"
|
||||
register: sample_plugin_output
|
||||
|
||||
- name: Assert that sample_plugin is installed or not
|
||||
assert:
|
||||
that:
|
||||
- sample_plugin_output.changed
|
||||
|
||||
- name: Gather Helm plugin info
|
||||
helm_plugin_info:
|
||||
binary_path: "{{ helm_binary }}"
|
||||
register: r
|
||||
|
||||
- name: Set sample_plugin version
|
||||
set_fact:
|
||||
plugin_version: "{{ ( r.plugin_list | selectattr('name', 'equalto', plugin_name) | list )[0].version }}"
|
||||
vars:
|
||||
plugin_name: "sample_plugin"
|
||||
|
||||
- name: Assert if sample_plugin with multiline comment is installed
|
||||
assert:
|
||||
that:
|
||||
- plugin_version == "0.0.1"
|
||||
always:
|
||||
- name: Uninstall sample_plugin
|
||||
helm_plugin:
|
||||
binary_path: "{{ helm_binary }}"
|
||||
state: absent
|
||||
plugin_name: sample_plugin
|
||||
ignore_errors: yes
|
||||
Binary file not shown.
@@ -1,91 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright: (c) 2021, Aubin Bikouo <@abikouo>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
|
||||
module: k8s_diff
|
||||
|
||||
short_description: Create large file with a defined size.
|
||||
|
||||
author:
|
||||
- Aubin Bikouo (@abikouo)
|
||||
|
||||
description:
|
||||
- This module is used to validate k8s_cp module.
|
||||
|
||||
options:
|
||||
path:
|
||||
description:
|
||||
- The destination path for the file to create.
|
||||
type: path
|
||||
required: yes
|
||||
size:
|
||||
description:
|
||||
- The size of the output file in MB.
|
||||
type: int
|
||||
default: 400
|
||||
binary:
|
||||
description:
|
||||
- If this flag is set to yes, the generated file content binary data.
|
||||
type: bool
|
||||
default: False
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: create 150MB file
|
||||
k8s_diff:
|
||||
path: large_file.txt
|
||||
size: 150
|
||||
'''
|
||||
|
||||
|
||||
RETURN = r'''
|
||||
'''
|
||||
|
||||
import os
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils._text import to_native
|
||||
|
||||
|
||||
def execute_module(module):
|
||||
try:
|
||||
size = module.params.get('size') * 1024 * 1024
|
||||
path = module.params.get('path')
|
||||
write_mode = "w"
|
||||
if module.params.get('binary'):
|
||||
content = os.urandom(size)
|
||||
write_mode = "wb"
|
||||
else:
|
||||
content = ""
|
||||
count = 0
|
||||
while len(content) < size:
|
||||
content += "This file has been generated using ansible: {0}\n".format(count)
|
||||
count += 1
|
||||
|
||||
with open(path, write_mode) as f:
|
||||
f.write(content)
|
||||
module.exit_json(changed=True, size=len(content))
|
||||
except Exception as e:
|
||||
module.fail_json(msg="failed to create file due to: {0}".format(to_native(e)))
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = {}
|
||||
argument_spec['size'] = {'type': 'int', 'default': 400}
|
||||
argument_spec['path'] = {'type': 'path', 'required': True}
|
||||
argument_spec['binary'] = {'type': 'bool', 'default': False}
|
||||
module = AnsibleModule(argument_spec=argument_spec)
|
||||
|
||||
execute_module(module)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,217 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright: (c) 2021, Aubin Bikouo <@abikouo>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
|
||||
module: kubectl_file_compare
|
||||
|
||||
short_description: Compare file and directory using kubectl
|
||||
|
||||
author:
|
||||
- Aubin Bikouo (@abikouo)
|
||||
|
||||
description:
|
||||
- This module is used to validate k8s_cp module.
|
||||
- Compare the local file/directory with the remote pod version
|
||||
|
||||
notes:
|
||||
- This module authenticates on kubernetes cluster using default kubeconfig only.
|
||||
|
||||
options:
|
||||
namespace:
|
||||
description:
|
||||
- The pod namespace name
|
||||
type: str
|
||||
required: yes
|
||||
pod:
|
||||
description:
|
||||
- The pod name
|
||||
type: str
|
||||
required: yes
|
||||
container:
|
||||
description:
|
||||
- The container to retrieve files from.
|
||||
type: str
|
||||
remote_path:
|
||||
description:
|
||||
- Path of the file or directory on Pod.
|
||||
type: path
|
||||
required: yes
|
||||
local_path:
|
||||
description:
|
||||
- Path of the local file or directory.
|
||||
type: path
|
||||
content:
|
||||
description:
|
||||
- local content to compare with remote file from pod.
|
||||
- mutually exclusive with option I(local_path).
|
||||
type: path
|
||||
required: yes
|
||||
args:
|
||||
description:
|
||||
- The file is considered to be an executable.
|
||||
- The tool will be run locally and on pod and compare result from output and stderr.
|
||||
type: list
|
||||
kubectl_path:
|
||||
description:
|
||||
- Path to the kubectl executable, if not specified it will be download.
|
||||
type: path
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: compare local /tmp/foo with /tmp/bar in a remote pod
|
||||
kubectl_file_compare:
|
||||
namespace: some-namespace
|
||||
pod: some-pod
|
||||
remote_path: /tmp/bar
|
||||
local_path: /tmp/foo
|
||||
kubectl_path: /tmp/test/kubectl
|
||||
|
||||
- name: Compare executable running help command
|
||||
kubectl_file_compare:
|
||||
namespace: some-namespace
|
||||
pod: some-pod
|
||||
remote_path: /tmp/test/kubectl
|
||||
local_path: kubectl
|
||||
kubectl_path: /tmp/test/kubectl
|
||||
args:
|
||||
- "--help"
|
||||
'''
|
||||
|
||||
|
||||
RETURN = r'''
|
||||
'''
|
||||
|
||||
import os
|
||||
import filecmp
|
||||
|
||||
from tempfile import NamedTemporaryFile, TemporaryDirectory
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
|
||||
def kubectl_get_content(module, dest_dir):
|
||||
kubectl_path = module.params.get('kubectl_path')
|
||||
if kubectl_path is None:
|
||||
kubectl_path = module.get_bin_path('kubectl', required=True)
|
||||
|
||||
namespace = module.params.get('namespace')
|
||||
pod = module.params.get('pod')
|
||||
file = module.params.get('remote_path')
|
||||
|
||||
cmd = [
|
||||
kubectl_path,
|
||||
'cp',
|
||||
"{0}/{1}:{2}".format(namespace, pod, file)
|
||||
]
|
||||
container = module.params.get('container')
|
||||
if container:
|
||||
cmd += ['-c', container]
|
||||
local_file = os.path.join(dest_dir, os.path.basename(module.params.get('remote_path')))
|
||||
cmd.append(local_file)
|
||||
rc, out, err = module.run_command(cmd)
|
||||
return local_file, err, rc, out
|
||||
|
||||
|
||||
def kubectl_run_from_pod(module):
|
||||
kubectl_path = module.params.get('kubectl_path')
|
||||
if kubectl_path is None:
|
||||
kubectl_path = module.get_bin_path('kubectl', required=True)
|
||||
|
||||
cmd = [
|
||||
kubectl_path,
|
||||
'exec',
|
||||
module.params.get('pod'),
|
||||
'-n',
|
||||
module.params.get('namespace')
|
||||
]
|
||||
container = module.params.get('container')
|
||||
if container:
|
||||
cmd += ['-c', container]
|
||||
cmd += ['--', module.params.get('remote_path')]
|
||||
cmd += module.params.get('args')
|
||||
return module.run_command(cmd)
|
||||
|
||||
|
||||
def compare_directories(dir1, dir2):
|
||||
test = filecmp.dircmp(dir1, dir2)
|
||||
if any([len(test.left_only) > 0, len(test.right_only) > 0, len(test.funny_files) > 0]):
|
||||
return False
|
||||
(t, mismatch, errors) = filecmp.cmpfiles(dir1, dir2, test.common_files, shallow=False)
|
||||
if len(mismatch) > 0 or len(errors) > 0:
|
||||
return False
|
||||
for common_dir in test.common_dirs:
|
||||
new_dir1 = os.path.join(dir1, common_dir)
|
||||
new_dir2 = os.path.join(dir2, common_dir)
|
||||
if not compare_directories(new_dir1, new_dir2):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def execute_module(module):
|
||||
|
||||
args = module.params.get('args')
|
||||
local_path = module.params.get('local_path')
|
||||
namespace = module.params.get('namespace')
|
||||
pod = module.params.get('pod')
|
||||
file = module.params.get('remote_path')
|
||||
content = module.params.get('content')
|
||||
if args:
|
||||
pod_rc, pod_out, pod_err = kubectl_run_from_pod(module)
|
||||
rc, out, err = module.run_command([module.params.get('local_path')] + args)
|
||||
if rc == pod_rc and out == pod_out:
|
||||
module.exit_json(msg="{0} and {1}/{2}:{3} are same.".format(
|
||||
local_path, namespace, pod, file
|
||||
), rc=rc, stderr=err, stdout=out)
|
||||
result = dict(local=dict(rc=rc, out=out, err=err), remote=dict(rc=pod_rc, out=pod_out, err=pod_err))
|
||||
module.fail_json(msg=f"{local_path} and {namespace}/{pod}:{file} are same.", **result)
|
||||
else:
|
||||
with TemporaryDirectory() as tmpdirname:
|
||||
file_from_pod, err, rc, out = kubectl_get_content(module=module, dest_dir=tmpdirname)
|
||||
if not os.path.exists(file_from_pod):
|
||||
module.fail_json(msg="failed to copy content from pod", error=err, output=out)
|
||||
|
||||
if content is not None:
|
||||
with NamedTemporaryFile(mode="w") as tmp_file:
|
||||
tmp_file.write(content)
|
||||
tmp_file.flush()
|
||||
if filecmp.cmp(file_from_pod, tmp_file.name):
|
||||
module.exit_json(msg=f"defined content and {namespace}/{pod}:{file} are same.")
|
||||
module.fail_json(msg=f"defined content and {namespace}/{pod}:{file} are same.")
|
||||
|
||||
if os.path.isfile(local_path):
|
||||
if filecmp.cmp(file_from_pod, local_path):
|
||||
module.exit_json(msg=f"{local_path} and {namespace}/{pod}:{file} are same.")
|
||||
module.fail_json(msg=f"{local_path} and {namespace}/{pod}:{file} are same.")
|
||||
|
||||
if os.path.isdir(local_path):
|
||||
if compare_directories(file_from_pod, local_path):
|
||||
module.exit_json(msg=f"{local_path} and {namespace}/{pod}:{file} are same.")
|
||||
module.fail_json(msg=f"{local_path} and {namespace}/{pod}:{file} are same.")
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = {}
|
||||
argument_spec['namespace'] = {'type': 'str', 'required': True}
|
||||
argument_spec['pod'] = {'type': 'str', 'required': True}
|
||||
argument_spec['container'] = {}
|
||||
argument_spec['remote_path'] = {'type': 'path', 'required': True}
|
||||
argument_spec['local_path'] = {'type': 'path'}
|
||||
argument_spec['content'] = {'type': 'str'}
|
||||
argument_spec['kubectl_path'] = {'type': 'path'}
|
||||
argument_spec['args'] = {'type': 'list'}
|
||||
module = AnsibleModule(argument_spec=argument_spec,
|
||||
mutually_exclusive=[('local_path', 'content')],
|
||||
required_one_of=[['local_path', 'content']])
|
||||
|
||||
execute_module(module)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,46 +0,0 @@
|
||||
---
|
||||
- block:
|
||||
- name: Download kubeclt executable used to compare results
|
||||
get_url:
|
||||
url: https://dl.k8s.io/release/v1.21.3/bin/linux/amd64/kubectl
|
||||
dest: "{{ kubectl_path }}"
|
||||
|
||||
- name: make kubectl executable
|
||||
ansible.builtin.file:
|
||||
path: "{{ kubectl_path }}"
|
||||
mode: "+x"
|
||||
|
||||
# Ensure namespace and create pod to perform tests on
|
||||
- name: Ensure namespace exists
|
||||
k8s:
|
||||
definition:
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: "{{ copy_namespace }}"
|
||||
|
||||
- name: Create Pods
|
||||
k8s:
|
||||
namespace: '{{ copy_namespace }}'
|
||||
wait: yes
|
||||
template: pods_definition.j2
|
||||
|
||||
- include_tasks: test_copy_errors.yml
|
||||
- include_tasks: test_copy_file.yml
|
||||
- include_tasks: test_multi_container_pod.yml
|
||||
- include_tasks: test_copy_directory.yml
|
||||
- include_tasks: test_copy_large_file.yml
|
||||
|
||||
always:
|
||||
- name: Remove kubectl executable
|
||||
ansible.builtin.file:
|
||||
path: "{{ kubectl_path }}"
|
||||
state: absent
|
||||
ignore_errors: true
|
||||
|
||||
- name: Remove namespace
|
||||
k8s:
|
||||
kind: Namespace
|
||||
name: "{{ copy_namespace }}"
|
||||
state: absent
|
||||
ignore_errors: true
|
||||
@@ -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,227 +0,0 @@
|
||||
---
|
||||
- block:
|
||||
- name: Set common facts
|
||||
set_fact:
|
||||
drain_namespace: "drain"
|
||||
drain_daemonset_name: "promotheus-dset"
|
||||
drain_pod_name: "pod-drain"
|
||||
|
||||
- name: Create {{ drain_namespace }} namespace
|
||||
k8s:
|
||||
kind: Namespace
|
||||
name: '{{ drain_namespace }}'
|
||||
|
||||
- name: list cluster nodes
|
||||
k8s_info:
|
||||
kind: node
|
||||
register: nodes
|
||||
|
||||
- name: Select uncordoned nodes
|
||||
set_fact:
|
||||
uncordoned_nodes: "{{ nodes.resources | selectattr('spec.unschedulable', 'undefined') | map(attribute='metadata.name') | list}}"
|
||||
|
||||
- name: Assert that at least one node is schedulable
|
||||
assert:
|
||||
that:
|
||||
- uncordoned_nodes | length > 0
|
||||
|
||||
- name: select node to drain
|
||||
set_fact:
|
||||
node_to_drain: '{{ uncordoned_nodes[0] }}'
|
||||
|
||||
- name: Deploy daemonset on cluster
|
||||
k8s:
|
||||
namespace: '{{ drain_namespace }}'
|
||||
definition:
|
||||
apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: '{{ drain_daemonset_name }}'
|
||||
spec:
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchFields:
|
||||
- key: metadata.name
|
||||
operator: In
|
||||
values:
|
||||
- '{{ node_to_drain }}'
|
||||
selector:
|
||||
matchLabels:
|
||||
name: prometheus-exporter
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
name: prometheus-exporter
|
||||
spec:
|
||||
containers:
|
||||
- name: prometheus
|
||||
image: prom/node-exporter
|
||||
ports:
|
||||
- containerPort: 80
|
||||
|
||||
- name: Create Pods not managed by ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet.
|
||||
k8s:
|
||||
namespace: '{{ drain_namespace }}'
|
||||
wait: yes
|
||||
definition:
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: '{{ drain_pod_name }}'
|
||||
spec:
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchFields:
|
||||
- key: metadata.name
|
||||
operator: In
|
||||
values:
|
||||
- '{{ node_to_drain }}'
|
||||
containers:
|
||||
- name: c0
|
||||
image: busybox
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- while true;do date;sleep 5; done
|
||||
|
||||
- name: Cordon node
|
||||
k8s_drain:
|
||||
state: cordon
|
||||
name: '{{ node_to_drain }}'
|
||||
register: cordon
|
||||
|
||||
- name: assert that cordon is changed
|
||||
assert:
|
||||
that:
|
||||
- cordon is changed
|
||||
|
||||
- name: Test cordon idempotency
|
||||
k8s_drain:
|
||||
state: cordon
|
||||
name: '{{ node_to_drain }}'
|
||||
register: cordon
|
||||
|
||||
- name: assert that cordon is not changed
|
||||
assert:
|
||||
that:
|
||||
- cordon is not changed
|
||||
|
||||
- name: Get pods
|
||||
k8s_info:
|
||||
kind: Pod
|
||||
namespace: '{{ drain_namespace }}'
|
||||
register: Pod
|
||||
|
||||
- name: assert that pods are running on cordoned node
|
||||
assert:
|
||||
that:
|
||||
- "{{ Pod.resources | selectattr('status.phase', 'equalto', 'Running') | selectattr('spec.nodeName', 'equalto', node_to_drain) | list | length > 0 }}"
|
||||
|
||||
- name: Uncordon node
|
||||
k8s_drain:
|
||||
state: uncordon
|
||||
name: '{{ node_to_drain }}'
|
||||
register: uncordon
|
||||
|
||||
- name: assert that uncordon is changed
|
||||
assert:
|
||||
that:
|
||||
- uncordon is changed
|
||||
|
||||
- name: Test uncordon idempotency
|
||||
k8s_drain:
|
||||
state: uncordon
|
||||
name: '{{ node_to_drain }}'
|
||||
register: uncordon
|
||||
|
||||
- name: assert that uncordon is not changed
|
||||
assert:
|
||||
that:
|
||||
- uncordon is not changed
|
||||
|
||||
- name: Drain node
|
||||
k8s_drain:
|
||||
state: drain
|
||||
name: '{{ node_to_drain }}'
|
||||
ignore_errors: true
|
||||
register: drain_result
|
||||
|
||||
- name: assert that drain failed due to DaemonSet managed Pods
|
||||
assert:
|
||||
that:
|
||||
- drain_result is failed
|
||||
- '"cannot delete DaemonSet-managed Pods" in drain_result.msg'
|
||||
- '"cannot delete Pods not managed by ReplicationController, ReplicaSet, Job, DaemonSet or StatefulSet" in drain_result.msg'
|
||||
|
||||
- name: Drain node using ignore_daemonsets and force options
|
||||
k8s_drain:
|
||||
state: drain
|
||||
name: '{{ node_to_drain }}'
|
||||
delete_options:
|
||||
force: true
|
||||
ignore_daemonsets: true
|
||||
wait_timeout: 0
|
||||
register: drain_result
|
||||
|
||||
- name: assert that node has been drained
|
||||
assert:
|
||||
that:
|
||||
- drain_result is changed
|
||||
- '"node {{ node_to_drain }} marked unschedulable." in drain_result.result'
|
||||
|
||||
- name: assert that unmanaged pod were deleted
|
||||
k8s_info:
|
||||
namespace: '{{ drain_namespace }}'
|
||||
kind: Pod
|
||||
name: '{{ drain_pod_name }}'
|
||||
register: _result
|
||||
failed_when: _result.resources
|
||||
|
||||
- name: Test drain idempotency
|
||||
k8s_drain:
|
||||
state: drain
|
||||
name: '{{ node_to_drain }}'
|
||||
delete_options:
|
||||
force: true
|
||||
ignore_daemonsets: true
|
||||
register: drain_result
|
||||
|
||||
- name: Check idempotency
|
||||
assert:
|
||||
that:
|
||||
- drain_result is not changed
|
||||
|
||||
- name: Get DaemonSet
|
||||
k8s_info:
|
||||
kind: DaemonSet
|
||||
namespace: '{{ drain_namespace }}'
|
||||
name: '{{ drain_daemonset_name }}'
|
||||
register: dset_result
|
||||
|
||||
- name: assert that daemonset managed pods were not removed
|
||||
assert:
|
||||
that:
|
||||
- dset_result.resources | list | length > 0
|
||||
|
||||
- name: Uncordon node
|
||||
k8s_drain:
|
||||
state: uncordon
|
||||
name: '{{ node_to_drain }}'
|
||||
|
||||
always:
|
||||
- name: Uncordon node
|
||||
k8s_drain:
|
||||
state: uncordon
|
||||
name: '{{ node_to_drain }}'
|
||||
when: node_to_drain is defined
|
||||
ignore_errors: true
|
||||
|
||||
- name: delete namespace
|
||||
k8s:
|
||||
state: absent
|
||||
kind: namespace
|
||||
name: '{{ drain_namespace }}'
|
||||
@@ -1,65 +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.rc != 0
|
||||
- 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,112 +0,0 @@
|
||||
---
|
||||
- block:
|
||||
- set_fact:
|
||||
pre_test1: "{{ lookup('kubernetes.core.k8s', kind='Namespace', label_selector='namespace_label=app_development') }}"
|
||||
pre_test2: "{{ lookup('kubernetes.core.k8s', kind='Namespace', resource_name='app-development-one') }}"
|
||||
pre_test3: "{{ query('kubernetes.core.k8s', kind='Namespace', label_selector='namespace_label=app_development') }}"
|
||||
pre_test4: "{{ query('kubernetes.core.k8s', kind='Namespace', resource_name='app-development-one') }}"
|
||||
|
||||
# https://github.com/ansible-collections/kubernetes.core/issues/147
|
||||
- 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:
|
||||
test1: "{{ lookup('kubernetes.core.k8s', kind='Namespace', label_selector='namespace_label=app_development', wantlist=True) }}"
|
||||
test2: "{{ query('kubernetes.core.k8s', kind='Namespace', label_selector='namespace_label=app_development') }}"
|
||||
test3: "{{ lookup('kubernetes.core.k8s', kind='Namespace', resource_name='app-development-one', wantlist=True) }}"
|
||||
test4: "{{ query('kubernetes.core.k8s', kind='Namespace', resource_name='app-development-one') }}"
|
||||
test5: "{{ lookup('kubernetes.core.k8s', kind='Namespace', label_selector='namespace_label=app_development') }}"
|
||||
test6: "{{ lookup('kubernetes.core.k8s', kind='Namespace', resource_name='app-development-one') }}"
|
||||
test7: "{{ lookup('kubernetes.core.k8s', kind='Ingress', api_version='networking.k8s.io/vINVALID', errors='ignore') }}"
|
||||
|
||||
- set_fact:
|
||||
test8: "{{ lookup('kubernetes.core.k8s', kind='Ingress', api_version='networking.k8s.io/vINVALID') }}"
|
||||
ignore_errors: true
|
||||
|
||||
- name: Assert that every test is passed
|
||||
assert:
|
||||
that:
|
||||
# Before creating object
|
||||
- pre_test1 is sequence and pre_test1 is not string
|
||||
- pre_test1 | length == 0
|
||||
- pre_test2 is sequence and pre_test2 is not string
|
||||
- pre_test2 | length == 0
|
||||
- pre_test3 is sequence and pre_test3 is not string
|
||||
- pre_test3 | length == 0
|
||||
- pre_test4 is sequence and pre_test4 is not string
|
||||
- pre_test4 | length == 0
|
||||
# After creating object
|
||||
- test1 is sequence and test1 is not string
|
||||
- test1 | length == 1
|
||||
- test2 is sequence and test2 is not string
|
||||
- test2 | length == 1
|
||||
- test3 is sequence and test3 is not string
|
||||
- test3 | length == 1
|
||||
- test4 is sequence and test4 is not string
|
||||
- test4 | length == 1
|
||||
# Without wantlist=True lookup should return mapping
|
||||
- test5 is mapping
|
||||
- test6 is mapping
|
||||
# errors='ignore'
|
||||
- test7 is string
|
||||
- test8 is not defined
|
||||
|
||||
- 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:
|
||||
test1: "{{ lookup('kubernetes.core.k8s', kind='Namespace', label_selector='namespace_label=app_development', wantlist=True) }}"
|
||||
test2: "{{ query('kubernetes.core.k8s', kind='Namespace', label_selector='namespace_label=app_development') }}"
|
||||
test3: "{{ lookup('kubernetes.core.k8s', kind='Namespace', resource_name='app-development-one', wantlist=True) }}"
|
||||
test4: "{{ query('kubernetes.core.k8s', kind='Namespace', resource_name='app-development-one') }}"
|
||||
test5: "{{ lookup('kubernetes.core.k8s', kind='Namespace', resource_name='app-development-two', wantlist=True) }}"
|
||||
test6: "{{ query('kubernetes.core.k8s', kind='Namespace', resource_name='app-development-two') }}"
|
||||
test7: "{{ lookup('kubernetes.core.k8s', kind='Namespace', label_selector='namespace_label=app_development') }}"
|
||||
test8: "{{ lookup('kubernetes.core.k8s', kind='Namespace', resource_name='app-development-one') }}"
|
||||
test9: "{{ lookup('kubernetes.core.k8s', kind='Namespace', resource_name='app-development-two') }}"
|
||||
|
||||
- name: Assert that every test is passed after creating second object
|
||||
assert:
|
||||
that:
|
||||
# After creating second object
|
||||
- test1 is sequence and test1 is not string
|
||||
- test1 | length == 2
|
||||
- test2 is sequence and test2 is not string
|
||||
- test2 | length == 2
|
||||
- test3 is sequence and test3 is not string
|
||||
- test3 | length == 1
|
||||
- test4 is sequence and test4 is not string
|
||||
- test4 | length == 1
|
||||
- test5 is sequence and test5 is not string
|
||||
- test5 | length == 1
|
||||
- test6 is sequence and test6 is not string
|
||||
- test6 | length == 1
|
||||
# When label_selector is used it returns list irrespective of wantlist=True
|
||||
- test7 is sequence and test7 is not string
|
||||
# Without wantlist=True lookup should return mapping
|
||||
- test8 is mapping
|
||||
- test9 is mapping
|
||||
|
||||
always:
|
||||
- name: Ensure that namespace is removed
|
||||
k8s:
|
||||
kind: Namespace
|
||||
name: "app-development-{{ item }}"
|
||||
state: absent
|
||||
with_items:
|
||||
- one
|
||||
- two
|
||||
@@ -1,103 +0,0 @@
|
||||
---
|
||||
- block:
|
||||
- set_fact:
|
||||
kustomize_ns: "kustomize"
|
||||
|
||||
- name: create environment for test
|
||||
block:
|
||||
- name: Ensure namespace
|
||||
k8s:
|
||||
kind: Namespace
|
||||
name: "{{ kustomize_ns }}"
|
||||
|
||||
- name: Create temp directory
|
||||
tempfile:
|
||||
state: directory
|
||||
suffix: .test
|
||||
register: _tmp_dir
|
||||
|
||||
- set_fact:
|
||||
tmp_dir_path: "{{ _tmp_dir.path }}"
|
||||
|
||||
- set_fact:
|
||||
kustomize_dir: "{{ tmp_dir_path }}/kustomization"
|
||||
|
||||
- name: create kustomize directory
|
||||
file:
|
||||
path: "{{ kustomize_dir }}"
|
||||
state: directory
|
||||
|
||||
- name: create kustomization file
|
||||
copy:
|
||||
content: '{{ item.content }}'
|
||||
dest: '{{ item.dest }}'
|
||||
with_items:
|
||||
- content: |
|
||||
configMapGenerator:
|
||||
- name: test-confmap-
|
||||
files:
|
||||
- data.properties
|
||||
dest: "{{ kustomize_dir }}/kustomization.yaml"
|
||||
- content: "project=ansible"
|
||||
dest: "{{ kustomize_dir }}/data.properties"
|
||||
|
||||
- name: copy script to install kustomize
|
||||
get_url:
|
||||
url: https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh
|
||||
dest: "{{ tmp_dir_path }}"
|
||||
|
||||
- name: make script as executable
|
||||
file:
|
||||
path: "{{ tmp_dir_path }}/install_kustomize.sh"
|
||||
mode: 0755
|
||||
|
||||
- name: Install kustomize
|
||||
command: "{{ tmp_dir_path }}/install_kustomize.sh"
|
||||
args:
|
||||
chdir: "{{ tmp_dir_path }}"
|
||||
register: _install
|
||||
|
||||
- set_fact:
|
||||
kustomize_binary: "{{ _install.stdout | regex_search('kustomize installed to (.*)', '\\1') | list | join('') }}"
|
||||
kubectl_binary: "{{ tmp_dir_path }}/kubectl"
|
||||
|
||||
- name: Download kubeclt executable used to compare results
|
||||
get_url:
|
||||
url: https://dl.k8s.io/release/v1.21.3/bin/linux/amd64/kubectl
|
||||
dest: "{{ kubectl_binary }}"
|
||||
|
||||
- name: make kubectl executable
|
||||
ansible.builtin.file:
|
||||
path: "{{ kubectl_binary }}"
|
||||
mode: "+x"
|
||||
|
||||
- name: Run lookup using kustomize binary
|
||||
set_fact:
|
||||
resource_kustomize: "{{ lookup('kubernetes.core.kustomize', binary_path=kustomize_binary, dir=kustomize_dir) }}"
|
||||
|
||||
- name: Run lookup using kubectl binary
|
||||
set_fact:
|
||||
resource_kubectl: "{{ lookup('kubernetes.core.kustomize', binary_path=kubectl_binary, dir=kustomize_dir) }}"
|
||||
|
||||
- name: assert output are the same
|
||||
assert:
|
||||
that:
|
||||
- resource_kubectl == resource_kustomize
|
||||
|
||||
- name: create kubernetes resource using lookup plugin
|
||||
k8s:
|
||||
namespace: "{{ kustomize_ns }}"
|
||||
definition: "{{ lookup('kubernetes.core.kustomize', dir=kustomize_dir, opt_dirs=tmp_dir_path) }}"
|
||||
|
||||
always:
|
||||
- name: Delete namespace
|
||||
k8s:
|
||||
kind: Namespace
|
||||
name: "{{ kustomize_ns }}"
|
||||
state: absent
|
||||
ignore_errors: true
|
||||
|
||||
- name: Delete temporary directory
|
||||
file:
|
||||
state: absent
|
||||
path: "{{ tmp_dir_path }}"
|
||||
@@ -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,274 +0,0 @@
|
||||
---
|
||||
- block:
|
||||
- set_fact:
|
||||
scale_namespace: scale
|
||||
|
||||
- name: Ensure namespace exists
|
||||
k8s:
|
||||
definition:
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: "{{ scale_namespace }}"
|
||||
|
||||
- name: Add a deployment
|
||||
k8s:
|
||||
definition:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: scale-deploy
|
||||
namespace: "{{ scale_namespace }}"
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: "{{ k8s_pod_name }}"
|
||||
template: "{{ k8s_pod_template }}"
|
||||
wait: yes
|
||||
wait_timeout: 60
|
||||
apply: yes
|
||||
vars:
|
||||
k8s_pod_name: scale-deploy
|
||||
k8s_pod_image: gcr.io/kuar-demo/kuard-amd64:v0.10.0-green
|
||||
k8s_pod_ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
protocol: TCP
|
||||
|
||||
- name: Get pods in scale-deploy
|
||||
k8s_info:
|
||||
kind: Pod
|
||||
label_selectors:
|
||||
- app=scale-deploy
|
||||
namespace: "{{ scale_namespace }}"
|
||||
field_selectors:
|
||||
- status.phase=Running
|
||||
|
||||
- name: Scale the deployment
|
||||
k8s_scale:
|
||||
api_version: apps/v1
|
||||
kind: Deployment
|
||||
name: scale-deploy
|
||||
namespace: "{{ scale_namespace }}"
|
||||
replicas: 0
|
||||
wait: yes
|
||||
register: scale_down
|
||||
diff: true
|
||||
|
||||
- name: Get pods in scale-deploy
|
||||
k8s_info:
|
||||
kind: Pod
|
||||
label_selectors:
|
||||
- app=scale-deploy
|
||||
namespace: "{{ scale_namespace }}"
|
||||
field_selectors:
|
||||
- status.phase=Running
|
||||
register: scale_down_deploy_pods
|
||||
until: scale_down_deploy_pods.resources | length == 0
|
||||
retries: 6
|
||||
delay: 5
|
||||
|
||||
- name: Ensure that scale down took effect
|
||||
assert:
|
||||
that:
|
||||
- scale_down is changed
|
||||
- '"duration" in scale_down'
|
||||
- scale_down.diff
|
||||
|
||||
- name: Reapply the earlier deployment
|
||||
k8s:
|
||||
definition:
|
||||
api_version: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: scale-deploy
|
||||
namespace: "{{ scale_namespace }}"
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: "{{ k8s_pod_name }}"
|
||||
template: "{{ k8s_pod_template }}"
|
||||
wait: yes
|
||||
wait_timeout: 60
|
||||
apply: yes
|
||||
vars:
|
||||
k8s_pod_name: scale-deploy
|
||||
k8s_pod_image: gcr.io/kuar-demo/kuard-amd64:v0.10.0-green
|
||||
k8s_pod_ports:
|
||||
- containerPort: 8080
|
||||
name: http
|
||||
protocol: TCP
|
||||
register: reapply_after_scale
|
||||
|
||||
- name: Get pods in scale-deploy
|
||||
k8s_info:
|
||||
kind: Pod
|
||||
label_selectors:
|
||||
- app=scale-deploy
|
||||
namespace: "{{ scale_namespace }}"
|
||||
field_selectors:
|
||||
- status.phase=Running
|
||||
register: scale_up_deploy_pods
|
||||
|
||||
- name: Ensure that reapply after scale worked
|
||||
assert:
|
||||
that:
|
||||
- reapply_after_scale is changed
|
||||
- scale_up_deploy_pods.resources | length == 1
|
||||
|
||||
- name: Scale the deployment up
|
||||
k8s_scale:
|
||||
api_version: apps/v1
|
||||
kind: Deployment
|
||||
name: scale-deploy
|
||||
namespace: "{{ scale_namespace }}"
|
||||
replicas: 2
|
||||
wait: yes
|
||||
wait_timeout: 60
|
||||
register: scale_up
|
||||
|
||||
- name: Get pods in scale-deploy
|
||||
k8s_info:
|
||||
kind: Pod
|
||||
label_selectors:
|
||||
- app=scale-deploy
|
||||
field_selectors:
|
||||
- status.phase=Running
|
||||
namespace: "{{ scale_namespace }}"
|
||||
register: scale_up_further_deploy_pods
|
||||
|
||||
- name: Ensure that scale up worked
|
||||
assert:
|
||||
that:
|
||||
- scale_up is changed
|
||||
- '"duration" in scale_up'
|
||||
- scale_up.diff is not defined
|
||||
- scale_up_further_deploy_pods.resources | length == 2
|
||||
|
||||
- name: Don't scale the deployment up
|
||||
k8s_scale:
|
||||
api_version: apps/v1
|
||||
kind: Deployment
|
||||
name: scale-deploy
|
||||
namespace: "{{ scale_namespace }}"
|
||||
replicas: 2
|
||||
wait: yes
|
||||
register: scale_up_noop
|
||||
|
||||
- name: Get pods in scale-deploy
|
||||
k8s_info:
|
||||
kind: Pod
|
||||
label_selectors:
|
||||
- app=scale-deploy
|
||||
field_selectors:
|
||||
- status.phase=Running
|
||||
namespace: "{{ scale_namespace }}"
|
||||
register: scale_up_noop_pods
|
||||
|
||||
- name: Ensure that no-op scale up worked
|
||||
assert:
|
||||
that:
|
||||
- scale_up_noop is not changed
|
||||
- scale_up_noop.diff is not defined
|
||||
- scale_up_noop_pods.resources | length == 2
|
||||
- '"duration" in scale_up_noop'
|
||||
|
||||
- name: Scale deployment down without wait
|
||||
k8s_scale:
|
||||
api_version: apps/v1
|
||||
kind: Deployment
|
||||
name: scale-deploy
|
||||
namespace: "{{ scale_namespace }}"
|
||||
replicas: 1
|
||||
wait: no
|
||||
register: scale_down_no_wait
|
||||
diff: true
|
||||
|
||||
- name: Ensure that scale down succeeds
|
||||
k8s_info:
|
||||
kind: Pod
|
||||
label_selectors:
|
||||
- app=scale-deploy
|
||||
namespace: "{{ scale_namespace }}"
|
||||
register: scale_down_no_wait_pods
|
||||
retries: 6
|
||||
delay: 5
|
||||
until: scale_down_no_wait_pods.resources | length == 1
|
||||
|
||||
- name: Ensure that scale down without wait worked
|
||||
assert:
|
||||
that:
|
||||
- scale_down_no_wait is changed
|
||||
- scale_down_no_wait.diff
|
||||
- scale_down_no_wait_pods.resources | length == 1
|
||||
|
||||
# scale multiple resource using label selectors
|
||||
- name: create deployment
|
||||
kubernetes.core.k8s:
|
||||
namespace: "{{ scale_namespace }}"
|
||||
src: files/deployment.yaml
|
||||
|
||||
- name: list deployment
|
||||
kubernetes.core.k8s_info:
|
||||
kind: Deployment
|
||||
namespace: "{{ scale_namespace }}"
|
||||
label_selectors:
|
||||
- app=nginx
|
||||
register: resource
|
||||
- assert:
|
||||
that:
|
||||
- resource.resources | list | length == 2
|
||||
|
||||
- name: scale deployment using resource version
|
||||
kubernetes.core.k8s_scale:
|
||||
replicas: 2
|
||||
kind: Deployment
|
||||
namespace: "{{ scale_namespace }}"
|
||||
resource_version: 0
|
||||
label_selectors:
|
||||
- app=nginx
|
||||
register: scale_out
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- not scale_out.changed
|
||||
- scale_out.results | selectattr('warning', 'defined') | list | length == 2
|
||||
|
||||
- name: scale deployment using current replicas (wrong value)
|
||||
kubernetes.core.k8s_scale:
|
||||
replicas: 2
|
||||
current_replicas: 4
|
||||
kind: Deployment
|
||||
namespace: "{{ scale_namespace }}"
|
||||
label_selectors:
|
||||
- app=nginx
|
||||
register: scale_out
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- not scale_out.changed
|
||||
- scale_out.results | selectattr('warning', 'defined') | list | length == 2
|
||||
|
||||
- name: scale deployment using current replicas (right value)
|
||||
kubernetes.core.k8s_scale:
|
||||
replicas: 2
|
||||
current_replicas: 3
|
||||
kind: Deployment
|
||||
namespace: "{{ scale_namespace }}"
|
||||
label_selectors:
|
||||
- app=nginx
|
||||
register: scale_out
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- scale_out.changed
|
||||
- scale_out.results | map(attribute='result.status.replicas') | list | unique == [2]
|
||||
|
||||
always:
|
||||
- name: Remove namespace
|
||||
k8s:
|
||||
kind: Namespace
|
||||
name: "{{ scale_namespace }}"
|
||||
state: absent
|
||||
@@ -3,44 +3,64 @@
|
||||
# Copyright (c) 2020, 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)
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
import copy
|
||||
import traceback
|
||||
import os
|
||||
import platform
|
||||
import traceback
|
||||
from contextlib import contextmanager
|
||||
|
||||
|
||||
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.common.text.converters import to_bytes, to_native, to_text
|
||||
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
|
||||
|
||||
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):
|
||||
|
||||
TRANSFERS_FILES = True
|
||||
DEFAULT_NEWLINE_SEQUENCE = "\n"
|
||||
|
||||
def _ensure_invocation(self, result):
|
||||
# NOTE: adding invocation arguments here needs to be kept in sync with
|
||||
# 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:
|
||||
result['invocation'] = "CENSORED: no_log is set"
|
||||
result["invocation"] = "CENSORED: no_log is set"
|
||||
else:
|
||||
result['invocation'] = self._task.args.copy()
|
||||
result['invocation']['module_args'] = self._task.args.copy()
|
||||
result["invocation"] = self._task.args.copy()
|
||||
result["invocation"]["module_args"] = self._task.args.copy()
|
||||
|
||||
return result
|
||||
|
||||
@contextmanager
|
||||
def get_template_data(self, template_path):
|
||||
try:
|
||||
source = self._find_needle('templates', template_path)
|
||||
source = self._find_needle("templates", template_path)
|
||||
except AnsibleError as e:
|
||||
raise AnsibleActionFail(to_text(e))
|
||||
|
||||
@@ -48,15 +68,19 @@ class ActionModule(ActionBase):
|
||||
try:
|
||||
tmp_source = self._loader.get_real_file(source)
|
||||
except AnsibleFileNotFound as e:
|
||||
raise AnsibleActionFail("could not find template=%s, %s" % (source, to_text(e)))
|
||||
b_tmp_source = to_bytes(tmp_source, errors='surrogate_or_strict')
|
||||
raise AnsibleActionFail(
|
||||
"could not find template=%s, %s" % (source, to_text(e))
|
||||
)
|
||||
b_tmp_source = to_bytes(tmp_source, errors="surrogate_or_strict")
|
||||
|
||||
try:
|
||||
with open(b_tmp_source, 'rb') as f:
|
||||
with open(b_tmp_source, "rb") as f:
|
||||
try:
|
||||
template_data = to_text(f.read(), errors='surrogate_or_strict')
|
||||
template_data = to_text(f.read(), errors="surrogate_or_strict")
|
||||
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
|
||||
except AnsibleAction:
|
||||
raise
|
||||
@@ -73,72 +97,115 @@ class ActionModule(ActionBase):
|
||||
"block_start_string": None,
|
||||
"block_end_string": None,
|
||||
"trim_blocks": True,
|
||||
"lstrip_blocks": False
|
||||
"lstrip_blocks": False,
|
||||
}
|
||||
if isinstance(template, string_types):
|
||||
if isinstance(template, str):
|
||||
# treat this as raw_params
|
||||
template_param['path'] = template
|
||||
template_param["path"] = template
|
||||
elif isinstance(template, dict):
|
||||
template_args = template
|
||||
template_path = template_args.get('path', None)
|
||||
template_path = template_args.get("path", None)
|
||||
if not template_path:
|
||||
raise AnsibleActionFail("Please specify path for template.")
|
||||
template_param['path'] = template_path
|
||||
template_param["path"] = template_path
|
||||
|
||||
# Options type validation strings
|
||||
for s_type in ('newline_sequence', 'variable_start_string', 'variable_end_string', 'block_start_string',
|
||||
'block_end_string'):
|
||||
for s_type in (
|
||||
"newline_sequence",
|
||||
"variable_start_string",
|
||||
"variable_end_string",
|
||||
"block_start_string",
|
||||
"block_end_string",
|
||||
):
|
||||
if s_type in template_args:
|
||||
value = ensure_type(template_args[s_type], 'string')
|
||||
if value is not None and not isinstance(value, string_types):
|
||||
raise AnsibleActionFail("%s is expected to be a string, but got %s instead" % (s_type, type(value)))
|
||||
value = ensure_type(template_args[s_type], "string")
|
||||
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))
|
||||
)
|
||||
try:
|
||||
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)
|
||||
})
|
||||
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
|
||||
),
|
||||
}
|
||||
)
|
||||
except TypeError as e:
|
||||
raise AnsibleActionFail(to_native(e))
|
||||
|
||||
template_param.update({
|
||||
"newline_sequence": template_args.get('newline_sequence', self.DEFAULT_NEWLINE_SEQUENCE),
|
||||
"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)
|
||||
})
|
||||
template_param.update(
|
||||
{
|
||||
"newline_sequence": template_args.get(
|
||||
"newline_sequence", self.DEFAULT_NEWLINE_SEQUENCE
|
||||
),
|
||||
"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:
|
||||
raise AnsibleActionFail("Error while reading template file - "
|
||||
"a string or dict for template expected, but got %s instead" % type(template))
|
||||
raise AnsibleActionFail(
|
||||
"Error while reading template file - "
|
||||
"a string or dict for template expected, but got %s instead"
|
||||
% type(template)
|
||||
)
|
||||
return template_param
|
||||
|
||||
def import_jinja2_lstrip(self, templates):
|
||||
# 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:
|
||||
import jinja2.defaults
|
||||
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:
|
||||
jinja2.defaults.LSTRIP_BLOCKS
|
||||
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):
|
||||
# template is only supported by k8s module.
|
||||
if self._task.action not in ('k8s', 'kubernetes.core.k8s', 'community.okd.k8s', 'redhat.openshift.k8s', 'community.kubernetes.k8s'):
|
||||
raise AnsibleActionFail("'template' is only a supported parameter for the 'k8s' module.")
|
||||
if self._task.action not in (
|
||||
"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 = []
|
||||
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))
|
||||
elif isinstance(template, list):
|
||||
for element in template:
|
||||
template_params.append(self.get_template_args(element))
|
||||
else:
|
||||
raise AnsibleActionFail("Error while reading template file - "
|
||||
"a string or dict for template expected, but got %s instead" % type(template))
|
||||
raise AnsibleActionFail(
|
||||
"Error while reading template file - "
|
||||
"a string or dict for template expected, but got %s instead"
|
||||
% type(template)
|
||||
)
|
||||
|
||||
self.import_jinja2_lstrip(template_params)
|
||||
|
||||
@@ -149,71 +216,117 @@ class ActionModule(ActionBase):
|
||||
old_vars = self._templar.available_variables
|
||||
|
||||
default_environment = {}
|
||||
for key in ("newline_sequence", "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)
|
||||
if trust_as_template is None:
|
||||
for key in (
|
||||
"newline_sequence",
|
||||
"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:
|
||||
# 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:
|
||||
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:
|
||||
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
|
||||
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
|
||||
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 value is not None:
|
||||
setattr(self._templar.environment, key, value)
|
||||
else:
|
||||
setattr(self._templar.environment, key, default_environment.get(key))
|
||||
overrides[key] = value
|
||||
if trust_as_template is None:
|
||||
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
|
||||
result = self._templar.do_template(template_data, preserve_trailing_newlines=True, escape_backslashes=False)
|
||||
result_template.append(result)
|
||||
if trust_as_template:
|
||||
template_data = trust_as_template(template_data)
|
||||
result = self._templar.template(
|
||||
template_data,
|
||||
preserve_trailing_newlines=True,
|
||||
escape_backslashes=False,
|
||||
overrides=overrides,
|
||||
)
|
||||
else:
|
||||
result = self._templar.do_template(
|
||||
template_data,
|
||||
preserve_trailing_newlines=True,
|
||||
escape_backslashes=False,
|
||||
)
|
||||
result_template.extend(_from_yaml_to_definition(result))
|
||||
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:
|
||||
new_module_args.pop('template')
|
||||
new_module_args['definition'] = result_template
|
||||
new_module_args.pop("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 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)
|
||||
return self._find_needle("files", local_path)
|
||||
except AnsibleError:
|
||||
raise AnsibleActionFail("%s does not exist in local filesystem" % local_path)
|
||||
raise AnsibleActionFail(
|
||||
"%s does not exist in local filesystem" % local_path
|
||||
)
|
||||
|
||||
def get_kubeconfig(self, kubeconfig, remote_transport, new_module_args):
|
||||
if isinstance(kubeconfig, string_types):
|
||||
if isinstance(kubeconfig, str):
|
||||
# find the kubeconfig in the expected search path
|
||||
if not remote_transport:
|
||||
# kubeconfig is local
|
||||
# find in expected paths
|
||||
kubeconfig = self._find_needle('files', kubeconfig)
|
||||
configs = []
|
||||
for config in kubeconfig.split(ENV_KUBECONFIG_PATH_SEPARATOR):
|
||||
config = self._find_needle("files", config)
|
||||
|
||||
# decrypt kubeconfig found
|
||||
actual_file = self._loader.get_real_file(kubeconfig, decrypt=True)
|
||||
new_module_args['kubeconfig'] = actual_file
|
||||
# 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
|
||||
new_module_args["kubeconfig"] = kubeconfig
|
||||
else:
|
||||
raise AnsibleActionFail("Error while reading kubeconfig parameter - "
|
||||
"a string or dict expected, but got %s instead" % type(kubeconfig))
|
||||
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):
|
||||
''' handler for k8s options '''
|
||||
"""handler for k8s options"""
|
||||
if task_vars is None:
|
||||
task_vars = dict()
|
||||
|
||||
@@ -224,53 +337,61 @@ class ActionModule(ActionBase):
|
||||
# look for kubeconfig and src
|
||||
# 'local' => look files on Ansible Controller
|
||||
# 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)
|
||||
|
||||
kubeconfig = self._task.args.get('kubeconfig', None)
|
||||
kubeconfig = self._task.args.get("kubeconfig", None)
|
||||
if kubeconfig:
|
||||
try:
|
||||
self.get_kubeconfig(kubeconfig, remote_transport, new_module_args)
|
||||
except AnsibleError as e:
|
||||
result['failed'] = True
|
||||
result['msg'] = to_text(e)
|
||||
result['exception'] = traceback.format_exc()
|
||||
result["failed"] = True
|
||||
result["msg"] = to_text(e)
|
||||
result["exception"] = traceback.format_exc()
|
||||
return result
|
||||
|
||||
# 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:
|
||||
# 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)
|
||||
|
||||
# src is local
|
||||
try:
|
||||
# find in expected paths
|
||||
src = self._find_needle('files', src)
|
||||
src = self._find_needle("files", src)
|
||||
except AnsibleError as e:
|
||||
result['failed'] = True
|
||||
result['msg'] = to_text(e)
|
||||
result['exception'] = traceback.format_exc()
|
||||
result["failed"] = True
|
||||
result["msg"] = to_text(e)
|
||||
result["exception"] = traceback.format_exc()
|
||||
return result
|
||||
|
||||
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:
|
||||
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':
|
||||
new_module_args['local_path'] = self.get_file_realpath(local_path)
|
||||
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.
|
||||
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
|
||||
self._remove_tmp_path(self._connection._shell.tmpdir)
|
||||
|
||||
@@ -17,14 +17,15 @@
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# 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
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
author:
|
||||
- xuxinkun
|
||||
- xuxinkun (@xuxinkun)
|
||||
|
||||
connection: kubectl
|
||||
name: kubectl
|
||||
|
||||
short_description: Execute tasks in pods running on Kubernetes.
|
||||
|
||||
@@ -71,9 +72,19 @@ DOCUMENTATION = r"""
|
||||
- name: ansible_kubectl_extra_args
|
||||
env:
|
||||
- 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:
|
||||
description:
|
||||
- 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: ''
|
||||
vars:
|
||||
- name: ansible_kubectl_kubeconfig
|
||||
@@ -170,41 +181,119 @@ DOCUMENTATION = r"""
|
||||
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.path
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
from ansible.parsing.yaml.loader import AnsibleLoader
|
||||
from ansible.errors import AnsibleError, AnsibleFileNotFound
|
||||
from ansible.module_utils.common.text.converters import to_bytes
|
||||
from ansible.module_utils.parsing.convert_bool import boolean
|
||||
from ansible.module_utils.six.moves import shlex_quote
|
||||
from ansible.module_utils._text import to_bytes
|
||||
from ansible.plugins.connection import ConnectionBase, BUFSIZE
|
||||
from ansible.parsing.yaml.loader import AnsibleLoader
|
||||
from ansible.plugins.connection import BUFSIZE, ConnectionBase
|
||||
from ansible.utils.display import Display
|
||||
|
||||
display = Display()
|
||||
|
||||
|
||||
CONNECTION_TRANSPORT = 'kubectl'
|
||||
CONNECTION_TRANSPORT = "kubectl"
|
||||
|
||||
CONNECTION_OPTIONS = {
|
||||
'kubectl_container': '-c',
|
||||
'kubectl_namespace': '-n',
|
||||
'kubectl_kubeconfig': '--kubeconfig',
|
||||
'kubectl_context': '--context',
|
||||
'kubectl_host': '--server',
|
||||
'kubectl_username': '--username',
|
||||
'kubectl_password': '--password',
|
||||
'client_cert': '--client-certificate',
|
||||
'client_key': '--client-key',
|
||||
'ca_cert': '--certificate-authority',
|
||||
'validate_certs': '--insecure-skip-tls-verify',
|
||||
'kubectl_token': '--token'
|
||||
"kubectl_container": "-c",
|
||||
"kubectl_namespace": "-n",
|
||||
"kubectl_kubeconfig": "--kubeconfig",
|
||||
"kubectl_context": "--context",
|
||||
"kubectl_host": "--server",
|
||||
"kubectl_username": "--username",
|
||||
"kubectl_password": "--password",
|
||||
"client_cert": "--client-certificate",
|
||||
"client_key": "--client-key",
|
||||
"ca_cert": "--certificate-authority",
|
||||
"validate_certs": "--insecure-skip-tls-verify",
|
||||
"kubectl_token": "--token",
|
||||
}
|
||||
|
||||
|
||||
class Connection(ConnectionBase):
|
||||
''' Local kubectl based connections '''
|
||||
"""Local kubectl based connections"""
|
||||
|
||||
transport = CONNECTION_TRANSPORT
|
||||
connection_options = CONNECTION_OPTIONS
|
||||
@@ -217,155 +306,249 @@ class Connection(ConnectionBase):
|
||||
|
||||
# Note: kubectl runs commands as the user that started the container.
|
||||
# It is impossible to set the remote user for a kubectl connection.
|
||||
cmd_arg = '{0}_command'.format(self.transport)
|
||||
if cmd_arg in kwargs:
|
||||
self.transport_cmd = kwargs[cmd_arg]
|
||||
else:
|
||||
self.transport_cmd = distutils.spawn.find_executable(self.transport)
|
||||
if not self.transport_cmd:
|
||||
raise AnsibleError("{0} command not found in PATH".format(self.transport))
|
||||
cmd_arg = "{0}_command".format(self.transport)
|
||||
self.transport_cmd = kwargs.get(cmd_arg, shutil.which(self.transport))
|
||||
if not self.transport_cmd:
|
||||
raise AnsibleError("{0} command not found in PATH".format(self.transport))
|
||||
self._file_to_delete = None
|
||||
|
||||
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):
|
||||
""" 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]
|
||||
censored_local_cmd = [self.transport_cmd]
|
||||
|
||||
# Build command options based on doc string
|
||||
doc_yaml = AnsibleLoader(self.documentation).get_single_data()
|
||||
for key in doc_yaml.get('options'):
|
||||
if key.endswith('verify_ssl') and self.get_option(key) != '':
|
||||
# Translate verify_ssl to skip_verify_ssl, and output as string
|
||||
skip_verify_ssl = not self.get_option(key)
|
||||
local_cmd.append(u'{0}={1}'.format(self.connection_options[key], str(skip_verify_ssl).lower()))
|
||||
censored_local_cmd.append(u'{0}={1}'.format(self.connection_options[key], str(skip_verify_ssl).lower()))
|
||||
elif not key.endswith('container') and self.get_option(key) and self.connection_options.get(key):
|
||||
for key in doc_yaml.get("options"):
|
||||
if key == "validate_certs" and self.get_option(key) != "":
|
||||
# Translate validate_certs to --insecure-skip-tls-verify flag
|
||||
# validate_certs=True means verify certs (don't skip verification)
|
||||
# validate_certs=False means don't verify certs (skip verification)
|
||||
validate_certs_value = boolean(self.get_option(key), strict=False)
|
||||
skip_verify_ssl = not validate_certs_value
|
||||
local_cmd.append(
|
||||
"{0}={1}".format(
|
||||
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]
|
||||
local_cmd += [cmd_arg, self.get_option(key)]
|
||||
# Redact password and token from console log
|
||||
if key.endswith(('_token', '_password')):
|
||||
censored_local_cmd += [cmd_arg, '********']
|
||||
if key.endswith(("_token", "_password")):
|
||||
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):
|
||||
local_cmd += self.get_option(extra_args_name).split(' ')
|
||||
censored_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(" ")
|
||||
|
||||
pod = self.get_option(u'{0}_pod'.format(self.transport))
|
||||
pod = self.get_option("{0}_pod".format(self.transport))
|
||||
if not pod:
|
||||
pod = self._play_context.remote_addr
|
||||
# -i is needed to keep stdin open which allows pipelining to work
|
||||
local_cmd += ['exec', '-i', pod]
|
||||
censored_local_cmd += ['exec', '-i', pod]
|
||||
local_cmd += ["exec", "-i", pod]
|
||||
censored_local_cmd += ["exec", "-i", pod]
|
||||
|
||||
# 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):
|
||||
local_cmd += ['-c', self.get_option(container_arg_name)]
|
||||
censored_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)]
|
||||
|
||||
local_cmd += ['--'] + cmd
|
||||
censored_local_cmd += ['--'] + cmd
|
||||
local_cmd += ["--"] + cmd
|
||||
censored_local_cmd += ["--"] + 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):
|
||||
""" Connect to the container. Nothing to do """
|
||||
"""Connect to the container. Nothing to do"""
|
||||
super(Connection, self)._connect()
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
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)
|
||||
display.vvv(
|
||||
"EXEC %s" % (censored_local_cmd,), host=self._play_context.remote_addr
|
||||
)
|
||||
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)
|
||||
self.delete_temporary_file()
|
||||
return (p.returncode, stdout, stderr)
|
||||
|
||||
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.
|
||||
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.
|
||||
This also happens to be the former default.
|
||||
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
|
||||
exist in any given chroot. So for now we're choosing "/" instead.
|
||||
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):
|
||||
remote_path = os.path.join(os.path.sep, remote_path)
|
||||
return os.path.normpath(remote_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)
|
||||
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)
|
||||
if not os.path.exists(to_bytes(in_path, errors='surrogate_or_strict')):
|
||||
raise AnsibleFileNotFound(
|
||||
"file or module does not exist: %s" % in_path)
|
||||
if not os.path.exists(to_bytes(in_path, errors="surrogate_or_strict")):
|
||||
raise AnsibleFileNotFound("file or module does not exist: %s" % in_path)
|
||||
|
||||
out_path = shlex_quote(out_path)
|
||||
# kubectl doesn't have native support for copying files into
|
||||
# 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:
|
||||
count = ' count=0'
|
||||
count = " count=0"
|
||||
else:
|
||||
count = ''
|
||||
args, dummy = self._build_exec_cmd([self._play_context.executable, "-c", "dd of=%s bs=%s%s" % (out_path, BUFSIZE, count)])
|
||||
args = [to_bytes(i, errors='surrogate_or_strict') for i in args]
|
||||
count = ""
|
||||
args, dummy = self._build_exec_cmd(
|
||||
[
|
||||
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:
|
||||
p = subprocess.Popen(args, stdin=in_file,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
p = subprocess.Popen(
|
||||
args,
|
||||
stdin=in_file,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
env=self._local_env(),
|
||||
)
|
||||
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()
|
||||
self.delete_temporary_file()
|
||||
|
||||
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):
|
||||
""" Fetch a file from container to local. """
|
||||
"""Fetch a file from container to local."""
|
||||
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)
|
||||
out_dir = os.path.dirname(out_path)
|
||||
|
||||
# kubectl doesn't have native support for fetching files from
|
||||
# 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 = [to_bytes(i, errors='surrogate_or_strict') for i in args]
|
||||
args, dummy = self._build_exec_cmd(
|
||||
[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))
|
||||
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:
|
||||
p = subprocess.Popen(args, stdin=subprocess.PIPE,
|
||||
stdout=out_file, stderr=subprocess.PIPE)
|
||||
p = subprocess.Popen(
|
||||
args,
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=out_file,
|
||||
stderr=subprocess.PIPE,
|
||||
env=self._local_env(),
|
||||
)
|
||||
except OSError:
|
||||
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()
|
||||
self.delete_temporary_file()
|
||||
|
||||
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:
|
||||
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):
|
||||
""" Terminate the connection. Nothing to do for kubectl"""
|
||||
"""Terminate the connection. Nothing to do for kubectl"""
|
||||
super(Connection, self).close()
|
||||
self._connected = False
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
|
||||
# Options for common Helm modules
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
class ModuleDocFragment(object):
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
DOCUMENTATION = r"""
|
||||
options:
|
||||
binary_path:
|
||||
description:
|
||||
@@ -29,18 +29,19 @@ options:
|
||||
description:
|
||||
- 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.
|
||||
type: path
|
||||
- The configuration can be provided as dictionary. Added in version 2.4.0.
|
||||
type: raw
|
||||
aliases: [ kubeconfig_path ]
|
||||
host:
|
||||
description:
|
||||
- Provide a URL for accessing the API. Can also be specified via C(K8S_AUTH_HOST) environment variable.
|
||||
type: str
|
||||
version_added: "1.2.0"
|
||||
version_added: 1.2.0
|
||||
api_key:
|
||||
description:
|
||||
- Token used to authenticate with the API. Can also be specified via C(K8S_AUTH_API_KEY) environment variable.
|
||||
type: str
|
||||
version_added: "1.2.0"
|
||||
version_added: 1.2.0
|
||||
validate_certs:
|
||||
description:
|
||||
- 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
|
||||
aliases: [ verify_ssl ]
|
||||
default: True
|
||||
version_added: "1.2.0"
|
||||
version_added: 1.2.0
|
||||
ca_cert:
|
||||
description:
|
||||
- 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.
|
||||
type: path
|
||||
aliases: [ ssl_ca_cert ]
|
||||
version_added: "1.2.0"
|
||||
'''
|
||||
version_added: 1.2.0
|
||||
"""
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
|
||||
# Options for authenticating with the API.
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
class ModuleDocFragment(object):
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
DOCUMENTATION = r"""
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
@@ -27,6 +27,7 @@ options:
|
||||
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.
|
||||
- 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:
|
||||
@@ -76,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.
|
||||
- Please note that this module does not pick up typical proxy settings from the environment (e.g. HTTP_PROXY).
|
||||
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:
|
||||
description:
|
||||
- The Header used for the HTTP proxy.
|
||||
@@ -110,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.
|
||||
- "The fix for this k8s python library is here: https://github.com/kubernetes-client/python-base/pull/169"
|
||||
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:
|
||||
- "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
|
||||
kubeconfig file."
|
||||
'''
|
||||
"""
|
||||
|
||||
@@ -5,17 +5,17 @@
|
||||
|
||||
# Options for specifying object wait
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
class ModuleDocFragment(object):
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
DOCUMENTATION = r"""
|
||||
options:
|
||||
delete_options:
|
||||
type: dict
|
||||
version_added: '1.2.0'
|
||||
version_added: 1.2.0
|
||||
description:
|
||||
- Configure behavior when deleting an object.
|
||||
- Only used when I(state=absent).
|
||||
@@ -48,4 +48,4 @@ options:
|
||||
type: str
|
||||
description:
|
||||
- Specify the UID of the target object.
|
||||
'''
|
||||
"""
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
class ModuleDocFragment(object):
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
DOCUMENTATION = r"""
|
||||
options:
|
||||
api_version:
|
||||
description:
|
||||
@@ -49,4 +49,4 @@ options:
|
||||
- If I(resource definition) is provided, the I(metadata.namespace) value from the I(resource_definition)
|
||||
will override this option.
|
||||
type: str
|
||||
'''
|
||||
"""
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
|
||||
# Options for providing an object configuration
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
class ModuleDocFragment(object):
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
DOCUMENTATION = r"""
|
||||
options:
|
||||
resource_definition:
|
||||
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
|
||||
plugin or template lookup plugin, combined with the from_yaml filter, and pass the result to
|
||||
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
|
||||
'''
|
||||
"""
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
|
||||
# Options used by scale modules.
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
class ModuleDocFragment(object):
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
DOCUMENTATION = r"""
|
||||
options:
|
||||
replicas:
|
||||
description:
|
||||
@@ -46,4 +46,4 @@ options:
|
||||
default: 5
|
||||
type: int
|
||||
version_added: 2.0.0
|
||||
'''
|
||||
"""
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
|
||||
# Options for specifying object state
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
class ModuleDocFragment(object):
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
DOCUMENTATION = r"""
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
@@ -27,4 +27,4 @@ options:
|
||||
- If set to C(yes), and I(state) is C(present), an existing object will be replaced.
|
||||
type: bool
|
||||
default: no
|
||||
'''
|
||||
"""
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
|
||||
# Options for specifying object wait
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
class ModuleDocFragment(object):
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
DOCUMENTATION = r"""
|
||||
options:
|
||||
wait:
|
||||
description:
|
||||
@@ -64,4 +64,4 @@ options:
|
||||
- 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.
|
||||
type: dict
|
||||
'''
|
||||
"""
|
||||
|
||||
@@ -2,12 +2,15 @@
|
||||
# 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
|
||||
|
||||
|
||||
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):
|
||||
@@ -15,15 +18,14 @@ def k8s_config_resource_name(resource):
|
||||
Generate resource name for the given resource of type ConfigMap, Secret
|
||||
"""
|
||||
try:
|
||||
return resource['metadata']['name'] + '-' + generate_hash(resource)
|
||||
return resource["metadata"]["name"] + "-" + generate_hash(resource)
|
||||
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 ----
|
||||
class FilterModule(object):
|
||||
|
||||
def filters(self):
|
||||
return {
|
||||
'k8s_config_resource_name': k8s_config_resource_name
|
||||
}
|
||||
return {"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,18 +3,18 @@
|
||||
#
|
||||
# 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
|
||||
|
||||
DOCUMENTATION = '''
|
||||
lookup: k8s
|
||||
DOCUMENTATION = """
|
||||
name: k8s
|
||||
|
||||
short_description: Query the K8s API
|
||||
|
||||
author:
|
||||
- Chris Houseknecht <@chouseknecht>
|
||||
- Fabian von Feilitzsch <@fabianvf>
|
||||
- Chris Houseknecht (@chouseknecht)
|
||||
- Fabian von Feilitzsch (@fabianvf)
|
||||
|
||||
description:
|
||||
- Uses the Kubernetes Python client to fetch a specific object by name, all matching objects within a
|
||||
@@ -86,14 +86,48 @@ DOCUMENTATION = '''
|
||||
description:
|
||||
- Provide a username for authenticating with the API. Can also be specified via K8S_AUTH_USERNAME environment
|
||||
variable.
|
||||
no_proxy:
|
||||
description:
|
||||
- The comma separated list of hosts/domains/IP/CIDR that shouldn't go through proxy.
|
||||
Can also be specified via K8S_AUTH_NO_PROXY environment variable.
|
||||
- Please note that this module does not pick up typical proxy settings from the environment (e.g. NO_PROXY).
|
||||
- This feature requires kubernetes>=19.15.0.
|
||||
When kubernetes library is less than 19.15.0, it fails even if no_proxy is set correctly.
|
||||
type: str
|
||||
password:
|
||||
description:
|
||||
- Provide a password for authenticating with the API. Can also be specified via K8S_AUTH_PASSWORD environment
|
||||
variable.
|
||||
proxy:
|
||||
description:
|
||||
- The URL of an HTTP proxy to use for the connection. Can also be specified via K8S_AUTH_PROXY environment variable.
|
||||
- Please note that this module does not pick up typical proxy settings from the environment (e.g. HTTP_PROXY).
|
||||
type: str
|
||||
proxy_headers:
|
||||
description:
|
||||
- The Header used for the HTTP proxy.
|
||||
- Documentation can be found here
|
||||
U(https://urllib3.readthedocs.io/en/latest/reference/urllib3.util.html?highlight=proxy_headers#urllib3.util.make_headers).
|
||||
type: dict
|
||||
suboptions:
|
||||
proxy_basic_auth:
|
||||
type: str
|
||||
description:
|
||||
- Colon-separated username:password for proxy basic authentication header.
|
||||
- Can also be specified via K8S_AUTH_PROXY_HEADERS_PROXY_BASIC_AUTH environment.
|
||||
basic_auth:
|
||||
type: str
|
||||
description:
|
||||
- Colon-separated username:password for basic authentication header.
|
||||
- Can also be specified via K8S_AUTH_PROXY_HEADERS_BASIC_AUTH environment.
|
||||
user_agent:
|
||||
type: str
|
||||
description:
|
||||
- String representing the user-agent you want, such as foo/1.0.
|
||||
- Can also be specified via K8S_AUTH_PROXY_HEADERS_USER_AGENT environment.
|
||||
client_cert:
|
||||
description:
|
||||
- Path to a certificate used to authenticate with the API. Can also be specified via K8S_AUTH_CERT_FILE
|
||||
environment
|
||||
- Path to a certificate used to authenticate with the API. Can also be specified via K8S_AUTH_CERT_FILE environment
|
||||
variable.
|
||||
aliases: [ cert_file ]
|
||||
client_key:
|
||||
@@ -114,10 +148,10 @@ DOCUMENTATION = '''
|
||||
aliases: [ verify_ssl ]
|
||||
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "kubernetes >= 12.0.0"
|
||||
- "python >= 3.9"
|
||||
- "kubernetes >= 24.2.0"
|
||||
- "PyYAML >= 3.11"
|
||||
'''
|
||||
"""
|
||||
|
||||
EXAMPLES = """
|
||||
- name: Fetch a list of namespaces
|
||||
@@ -159,39 +193,51 @@ RETURN = """
|
||||
_list:
|
||||
description:
|
||||
- One ore more object definitions returned from the API.
|
||||
type: complex
|
||||
contains:
|
||||
api_version:
|
||||
description: The versioned schema of this representation of an object.
|
||||
returned: success
|
||||
type: str
|
||||
kind:
|
||||
description: Represents the REST resource this object represents.
|
||||
returned: success
|
||||
type: str
|
||||
metadata:
|
||||
description: Standard object metadata. Includes name, namespace, annotations, labels, etc.
|
||||
returned: success
|
||||
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
|
||||
type: list
|
||||
elements: dict
|
||||
sample:
|
||||
- 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
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from ansible.errors import AnsibleError
|
||||
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:
|
||||
from kubernetes.dynamic.exceptions import NotFoundError
|
||||
|
||||
HAS_K8S_MODULE_HELPER = True
|
||||
k8s_import_exception = None
|
||||
except ImportError as e:
|
||||
@@ -199,13 +245,13 @@ except ImportError as e:
|
||||
k8s_import_exception = e
|
||||
|
||||
|
||||
class KubernetesLookup(K8sAnsibleMixin):
|
||||
|
||||
class KubernetesLookup(object):
|
||||
def __init__(self):
|
||||
|
||||
if not HAS_K8S_MODULE_HELPER:
|
||||
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
|
||||
@@ -226,31 +272,38 @@ class KubernetesLookup(K8sAnsibleMixin):
|
||||
self.params = kwargs
|
||||
self.client = get_api_client(**kwargs)
|
||||
|
||||
cluster_info = kwargs.get('cluster_info')
|
||||
if cluster_info == 'version':
|
||||
return [self.client.version]
|
||||
if cluster_info == 'api_groups':
|
||||
cluster_info = kwargs.get("cluster_info")
|
||||
if cluster_info == "version":
|
||||
return [self.client.client.version]
|
||||
if cluster_info == "api_groups":
|
||||
if isinstance(self.client.resources.api_groups, KeysView):
|
||||
return [list(self.client.resources.api_groups)]
|
||||
return [self.client.resources.api_groups]
|
||||
|
||||
self.kind = kwargs.get('kind')
|
||||
self.name = kwargs.get('resource_name')
|
||||
self.namespace = kwargs.get('namespace')
|
||||
self.api_version = kwargs.get('api_version', 'v1')
|
||||
self.label_selector = kwargs.get('label_selector')
|
||||
self.field_selector = kwargs.get('field_selector')
|
||||
self.include_uninitialized = kwargs.get('include_uninitialized', False)
|
||||
self.kind = kwargs.get("kind")
|
||||
self.name = kwargs.get("resource_name")
|
||||
self.namespace = kwargs.get("namespace")
|
||||
self.api_version = kwargs.get("api_version", "v1")
|
||||
self.label_selector = kwargs.get("label_selector")
|
||||
self.field_selector = kwargs.get("field_selector")
|
||||
self.include_uninitialized = kwargs.get("include_uninitialized", False)
|
||||
|
||||
resource_definition = kwargs.get('resource_definition')
|
||||
src = kwargs.get('src')
|
||||
resource_definition = kwargs.get("resource_definition")
|
||||
src = kwargs.get("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:
|
||||
self.kind = resource_definition.get('kind', self.kind)
|
||||
self.api_version = resource_definition.get('apiVersion', self.api_version)
|
||||
self.name = resource_definition.get('metadata', {}).get('name', self.name)
|
||||
self.namespace = resource_definition.get('metadata', {}).get('namespace', self.namespace)
|
||||
self.kind = resource_definition.get("kind", self.kind)
|
||||
self.api_version = resource_definition.get("apiVersion", self.api_version)
|
||||
self.name = resource_definition.get("metadata", {}).get("name", self.name)
|
||||
self.namespace = resource_definition.get("metadata", {}).get(
|
||||
"namespace", self.namespace
|
||||
)
|
||||
|
||||
if not self.kind:
|
||||
raise AnsibleError(
|
||||
@@ -258,19 +311,26 @@ class KubernetesLookup(K8sAnsibleMixin):
|
||||
"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:
|
||||
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:
|
||||
return []
|
||||
|
||||
if self.name:
|
||||
return [k8s_obj.to_dict()]
|
||||
|
||||
return k8s_obj.to_dict().get('items')
|
||||
return k8s_obj.to_dict().get("items")
|
||||
|
||||
|
||||
class LookupModule(LookupBase):
|
||||
|
||||
def run(self, terms, variables=None, **kwargs):
|
||||
def _run(self, terms, variables=None, **kwargs):
|
||||
return KubernetesLookup().run(terms, variables=variables, **kwargs)
|
||||
|
||||
run = _run if not hasattr(LookupBase, "run_on_daemon") else LookupBase.run_on_daemon
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
#
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
DOCUMENTATION = '''
|
||||
lookup: kustomize
|
||||
DOCUMENTATION = """
|
||||
name: kustomize
|
||||
|
||||
short_description: Build a set of kubernetes resources using a 'kustomization.yaml' file.
|
||||
|
||||
version_added: "2.2.0"
|
||||
version_added: 2.2.0
|
||||
|
||||
author:
|
||||
- Aubin Bikouo <@abikouo>
|
||||
- Aubin Bikouo (@abikouo)
|
||||
notes:
|
||||
- If both kustomize and kubectl are part of the PATH, kustomize will be used by the plugin.
|
||||
description:
|
||||
@@ -30,60 +30,70 @@ DOCUMENTATION = '''
|
||||
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
|
||||
set_fact:
|
||||
ansible.builtin.set_fact:
|
||||
resources: "{{ lookup('kubernetes.core.kustomize', binary_path='/path/to/kustomize') }}"
|
||||
|
||||
- name: Run lookup using kubectl kustomize
|
||||
set_fact:
|
||||
ansible.builtin.set_fact:
|
||||
resources: "{{ lookup('kubernetes.core.kustomize', binary_path='/path/to/kubectl') }}"
|
||||
|
||||
- name: Create kubernetes resources for lookup output
|
||||
k8s:
|
||||
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:
|
||||
- One ore more object definitions returned from the tool execution.
|
||||
type: complex
|
||||
contains:
|
||||
api_version:
|
||||
description: The versioned schema of this representation of an object.
|
||||
returned: success
|
||||
type: str
|
||||
kind:
|
||||
description: Represents the REST resource this object represents.
|
||||
returned: success
|
||||
type: str
|
||||
- YAML string for the object definitions returned from the tool execution.
|
||||
type: str
|
||||
sample:
|
||||
kind: ConfigMap
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
description: Standard object metadata. Includes name, namespace, annotations, labels, etc.
|
||||
returned: success
|
||||
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
|
||||
name: my-config-map
|
||||
namespace: default
|
||||
data:
|
||||
key1: val1
|
||||
"""
|
||||
|
||||
from ansible.errors import AnsibleLookupError
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
from ansible.module_utils.common.process import get_bin_path
|
||||
|
||||
|
||||
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 = {}
|
||||
@@ -91,43 +101,91 @@ def get_binary_from_path(name, opt_dirs=None):
|
||||
if opt_dirs is not None:
|
||||
if not isinstance(opt_dirs, list):
|
||||
opt_dirs = [opt_dirs]
|
||||
opt_arg['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):
|
||||
cmd = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
return cmd.communicate()
|
||||
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, **kwargs):
|
||||
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)
|
||||
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")
|
||||
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]
|
||||
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))
|
||||
raise AnsibleLookupError(
|
||||
"unexpected tool provided as parameter {0}, expected one of kustomize, kubectl.".format(
|
||||
executable_path
|
||||
)
|
||||
)
|
||||
|
||||
(out, err) = run_command(command)
|
||||
if err:
|
||||
raise AnsibleLookupError("kustomize command failed with: {0}".format(err.decode("utf-8")))
|
||||
return [out.decode('utf-8')]
|
||||
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,4 +1,4 @@
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
@@ -14,9 +14,10 @@ except TypeError:
|
||||
|
||||
if enable_turbo_mode:
|
||||
try:
|
||||
from ansible_collections.cloud.common.plugins.module_utils.turbo.module import (
|
||||
from ansible_collections.cloud.common.plugins.module_utils.turbo.module import ( # noqa: F401
|
||||
AnsibleTurboModule as AnsibleModule,
|
||||
) # noqa: F401
|
||||
)
|
||||
|
||||
AnsibleModule.collection_name = "kubernetes.core"
|
||||
except ImportError:
|
||||
from ansible.module_utils.basic import AnsibleModule # noqa: F401
|
||||
|
||||
@@ -14,13 +14,22 @@
|
||||
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
from collections import OrderedDict
|
||||
import json
|
||||
from collections import OrderedDict
|
||||
|
||||
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:
|
||||
from kubernetes.dynamic.exceptions import NotFoundError
|
||||
@@ -28,50 +37,52 @@ except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
LAST_APPLIED_CONFIG_ANNOTATION = 'kubectl.kubernetes.io/last-applied-configuration'
|
||||
LAST_APPLIED_CONFIG_ANNOTATION = "kubectl.kubernetes.io/last-applied-configuration"
|
||||
|
||||
POD_SPEC_SUFFIXES = {
|
||||
'containers': 'name',
|
||||
'initContainers': 'name',
|
||||
'ephemeralContainers': 'name',
|
||||
'volumes': 'name',
|
||||
'imagePullSecrets': 'name',
|
||||
'containers.volumeMounts': 'mountPath',
|
||||
'containers.volumeDevices': 'devicePath',
|
||||
'containers.env': 'name',
|
||||
'containers.ports': 'containerPort',
|
||||
'initContainers.volumeMounts': 'mountPath',
|
||||
'initContainers.volumeDevices': 'devicePath',
|
||||
'initContainers.env': 'name',
|
||||
'initContainers.ports': 'containerPort',
|
||||
'ephemeralContainers.volumeMounts': 'mountPath',
|
||||
'ephemeralContainers.volumeDevices': 'devicePath',
|
||||
'ephemeralContainers.env': 'name',
|
||||
'ephemeralContainers.ports': 'containerPort',
|
||||
"containers": "name",
|
||||
"initContainers": "name",
|
||||
"ephemeralContainers": "name",
|
||||
"volumes": "name",
|
||||
"imagePullSecrets": "name",
|
||||
"containers.volumeMounts": "mountPath",
|
||||
"containers.volumeDevices": "devicePath",
|
||||
"containers.env": "name",
|
||||
"containers.ports": "containerPort",
|
||||
"initContainers.volumeMounts": "mountPath",
|
||||
"initContainers.volumeDevices": "devicePath",
|
||||
"initContainers.env": "name",
|
||||
"initContainers.ports": "containerPort",
|
||||
"ephemeralContainers.volumeMounts": "mountPath",
|
||||
"ephemeralContainers.volumeDevices": "devicePath",
|
||||
"ephemeralContainers.env": "name",
|
||||
"ephemeralContainers.ports": "containerPort",
|
||||
}
|
||||
|
||||
POD_SPEC_PREFIXES = [
|
||||
'Pod.spec',
|
||||
'Deployment.spec.template.spec',
|
||||
'DaemonSet.spec.template.spec',
|
||||
'StatefulSet.spec.template.spec',
|
||||
'Job.spec.template.spec',
|
||||
'Cronjob.spec.jobTemplate.spec.template.spec',
|
||||
"Pod.spec",
|
||||
"Deployment.spec.template.spec",
|
||||
"DaemonSet.spec.template.spec",
|
||||
"StatefulSet.spec.template.spec",
|
||||
"Job.spec.template.spec",
|
||||
"Cronjob.spec.jobTemplate.spec.template.spec",
|
||||
]
|
||||
|
||||
# patch merge keys taken from generated.proto files under
|
||||
# staging/src/k8s.io/api in kubernetes/kubernetes
|
||||
STRATEGIC_MERGE_PATCH_KEYS = {
|
||||
'Service.spec.ports': 'port',
|
||||
'ServiceAccount.secrets': 'name',
|
||||
'ValidatingWebhookConfiguration.webhooks': 'name',
|
||||
'MutatingWebhookConfiguration.webhooks': 'name',
|
||||
"Service.spec.ports": "port",
|
||||
"ServiceAccount.secrets": "name",
|
||||
"ValidatingWebhookConfiguration.webhooks": "name",
|
||||
"MutatingWebhookConfiguration.webhooks": "name",
|
||||
}
|
||||
|
||||
STRATEGIC_MERGE_PATCH_KEYS.update(
|
||||
{"%s.%s" % (prefix, key): value
|
||||
for prefix in POD_SPEC_PREFIXES
|
||||
for key, value in POD_SPEC_SUFFIXES.items()}
|
||||
{
|
||||
"%s.%s" % (prefix, key): value
|
||||
for prefix in POD_SPEC_PREFIXES
|
||||
for key, value in POD_SPEC_SUFFIXES.items()
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -79,21 +90,28 @@ def annotate(desired):
|
||||
return dict(
|
||||
metadata=dict(
|
||||
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):
|
||||
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:
|
||||
# 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
|
||||
last_applied = json.loads(last_applied)
|
||||
patch = merge(dict_merge(last_applied, annotate(last_applied)),
|
||||
dict_merge(desired, annotate(desired)), actual)
|
||||
patch = merge(
|
||||
dict_merge(last_applied, annotate(last_applied)),
|
||||
dict_merge(desired, annotate(desired)),
|
||||
actual,
|
||||
)
|
||||
if patch:
|
||||
return actual, patch
|
||||
else:
|
||||
@@ -102,24 +120,54 @@ def apply_patch(actual, desired):
|
||||
return actual, dict_merge(desired, annotate(desired))
|
||||
|
||||
|
||||
def apply_object(resource, definition):
|
||||
def apply_object(resource, definition, server_side=False):
|
||||
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:
|
||||
return None, dict_merge(definition, annotate(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)
|
||||
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:
|
||||
return resource.create(body=desired, namespace=definition['metadata'].get('namespace'))
|
||||
return resource.create(
|
||||
body=desired, namespace=definition["metadata"].get("namespace"), **kwargs
|
||||
)
|
||||
if existing == desired:
|
||||
return resource.get(name=definition['metadata']['name'], namespace=definition['metadata'].get('namespace'))
|
||||
return resource.patch(body=desired,
|
||||
name=definition['metadata']['name'],
|
||||
namespace=definition['metadata'].get('namespace'),
|
||||
content_type='application/merge-patch+json')
|
||||
return resource.get(
|
||||
name=definition["metadata"]["name"],
|
||||
namespace=definition["metadata"].get("namespace"),
|
||||
**kwargs
|
||||
)
|
||||
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
|
||||
@@ -128,7 +176,7 @@ def k8s_apply(resource, definition):
|
||||
# deletions, and then apply delta to deletions as a patch, which should be strictly additive.
|
||||
def merge(last_applied, desired, actual, position=None):
|
||||
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)
|
||||
|
||||
|
||||
@@ -138,7 +186,9 @@ def list_to_dict(lst, key, position):
|
||||
try:
|
||||
result[item[key]] = item
|
||||
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
|
||||
|
||||
|
||||
@@ -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:
|
||||
result.append(desired_dict[key])
|
||||
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))
|
||||
for key in actual_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):
|
||||
if not position:
|
||||
if 'kind' in dict1 and dict1.get('kind') == dict2.get('kind'):
|
||||
position = dict1['kind']
|
||||
if "kind" in dict1 and dict1.get("kind") == dict2.get("kind"):
|
||||
position = dict1["kind"]
|
||||
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)
|
||||
for k in (set(dict1.keys()) & set(dict2.keys())):
|
||||
for k in set(dict1.keys()) & set(dict2.keys()):
|
||||
if position:
|
||||
this_position = "%s.%s" % (position, k)
|
||||
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:
|
||||
patch[k] = desired_value
|
||||
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:
|
||||
patch[k] = p
|
||||
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:
|
||||
patch[k] = [item for item in p if item is not None]
|
||||
elif actual_value != desired_value:
|
||||
|
||||
@@ -1,144 +1,146 @@
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
|
||||
from ansible.module_utils.six import string_types
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
import warnings
|
||||
|
||||
|
||||
def list_dict_str(value):
|
||||
if isinstance(value, (list, dict, string_types)):
|
||||
if isinstance(value, (list, dict, str)):
|
||||
return value
|
||||
raise TypeError
|
||||
|
||||
|
||||
def extract_sensitive_values_from_kubeconfig(kubeconfig_data):
|
||||
"""
|
||||
Extract only sensitive string values from kubeconfig data for no_log_values.
|
||||
|
||||
:arg kubeconfig_data: Dictionary containing kubeconfig data
|
||||
:returns: Set of sensitive string values to be added to no_log_values
|
||||
"""
|
||||
values = set()
|
||||
sensitive_fields = {
|
||||
"token",
|
||||
"password",
|
||||
"secret",
|
||||
"client-key-data",
|
||||
"client-certificate-data",
|
||||
"certificate-authority-data",
|
||||
"api_key",
|
||||
"access-token",
|
||||
"refresh-token",
|
||||
}
|
||||
|
||||
# Check API version and warn if not v1
|
||||
if isinstance(kubeconfig_data, dict):
|
||||
api_version = kubeconfig_data.get("apiVersion", "v1")
|
||||
if api_version != "v1":
|
||||
warnings.warn(
|
||||
f"Kubeconfig API version '{api_version}' is not 'v1'. "
|
||||
f"Sensitive field redaction is only guaranteed for API version 'v1'. "
|
||||
f"Some sensitive data may not be properly redacted from the logs.",
|
||||
UserWarning,
|
||||
)
|
||||
|
||||
def _extract_recursive(data, current_path=""):
|
||||
if isinstance(data, dict):
|
||||
for key, value in data.items():
|
||||
path = f"{current_path}.{key}" if current_path else key
|
||||
if key in sensitive_fields:
|
||||
if isinstance(value, str):
|
||||
values.add(value)
|
||||
else:
|
||||
_extract_recursive(value, path)
|
||||
elif isinstance(data, list):
|
||||
for i, item in enumerate(data):
|
||||
_extract_recursive(item, f"{current_path}[{i}]")
|
||||
|
||||
_extract_recursive(kubeconfig_data)
|
||||
return values
|
||||
|
||||
|
||||
AUTH_PROXY_HEADERS_SPEC = dict(
|
||||
proxy_basic_auth=dict(type='str', no_log=True),
|
||||
basic_auth=dict(type='str', no_log=True),
|
||||
user_agent=dict(type='str')
|
||||
proxy_basic_auth=dict(type="str", no_log=True),
|
||||
basic_auth=dict(type="str", no_log=True),
|
||||
user_agent=dict(type="str"),
|
||||
)
|
||||
|
||||
AUTH_ARG_SPEC = {
|
||||
'kubeconfig': {
|
||||
'type': 'raw',
|
||||
},
|
||||
'context': {},
|
||||
'host': {},
|
||||
'api_key': {
|
||||
'no_log': True,
|
||||
},
|
||||
'username': {},
|
||||
'password': {
|
||||
'no_log': True,
|
||||
},
|
||||
'validate_certs': {
|
||||
'type': 'bool',
|
||||
'aliases': ['verify_ssl'],
|
||||
},
|
||||
'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',
|
||||
},
|
||||
"kubeconfig": {"type": "raw"},
|
||||
"context": {},
|
||||
"host": {},
|
||||
"api_key": {"no_log": True},
|
||||
"username": {},
|
||||
"password": {"no_log": True},
|
||||
"validate_certs": {"type": "bool", "aliases": ["verify_ssl"]},
|
||||
"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"},
|
||||
"no_proxy": {"type": "str"},
|
||||
"proxy_headers": {"type": "dict", "options": AUTH_PROXY_HEADERS_SPEC},
|
||||
"persist_config": {"type": "bool"},
|
||||
"impersonate_user": {},
|
||||
"impersonate_groups": {"type": "list", "elements": "str"},
|
||||
}
|
||||
|
||||
WAIT_ARG_SPEC = dict(
|
||||
wait=dict(type='bool', default=False),
|
||||
wait_sleep=dict(type='int', default=5),
|
||||
wait_timeout=dict(type='int', default=120),
|
||||
wait=dict(type="bool", default=False),
|
||||
wait_sleep=dict(type="int", default=5),
|
||||
wait_timeout=dict(type="int", default=120),
|
||||
wait_condition=dict(
|
||||
type='dict',
|
||||
type="dict",
|
||||
default=None,
|
||||
options=dict(
|
||||
type=dict(),
|
||||
status=dict(default=True, choices=[True, False, "Unknown"]),
|
||||
reason=dict()
|
||||
)
|
||||
)
|
||||
reason=dict(),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
# Map kubernetes-client parameters to ansible parameters
|
||||
AUTH_ARG_MAP = {
|
||||
'kubeconfig': 'kubeconfig',
|
||||
'context': 'context',
|
||||
'host': 'host',
|
||||
'api_key': 'api_key',
|
||||
'username': 'username',
|
||||
'password': 'password',
|
||||
'verify_ssl': 'validate_certs',
|
||||
'ssl_ca_cert': 'ca_cert',
|
||||
'cert_file': 'client_cert',
|
||||
'key_file': 'client_key',
|
||||
'proxy': 'proxy',
|
||||
'proxy_headers': 'proxy_headers',
|
||||
'persist_config': 'persist_config',
|
||||
"kubeconfig": "kubeconfig",
|
||||
"context": "context",
|
||||
"host": "host",
|
||||
"api_key": "api_key",
|
||||
"username": "username",
|
||||
"password": "password",
|
||||
"verify_ssl": "validate_certs",
|
||||
"ssl_ca_cert": "ca_cert",
|
||||
"cert_file": "client_cert",
|
||||
"key_file": "client_key",
|
||||
"proxy": "proxy",
|
||||
"no_proxy": "no_proxy",
|
||||
"proxy_headers": "proxy_headers",
|
||||
"persist_config": "persist_config",
|
||||
}
|
||||
|
||||
NAME_ARG_SPEC = {
|
||||
'kind': {},
|
||||
'name': {},
|
||||
'namespace': {},
|
||||
'api_version': {
|
||||
'default': 'v1',
|
||||
'aliases': ['api', 'version'],
|
||||
},
|
||||
"kind": {},
|
||||
"name": {},
|
||||
"namespace": {},
|
||||
"api_version": {"default": "v1", "aliases": ["api", "version"]},
|
||||
}
|
||||
|
||||
COMMON_ARG_SPEC = {
|
||||
'state': {
|
||||
'default': 'present',
|
||||
'choices': ['present', 'absent'],
|
||||
},
|
||||
'force': {
|
||||
'type': 'bool',
|
||||
'default': False,
|
||||
},
|
||||
"state": {"default": "present", "choices": ["present", "absent"]},
|
||||
"force": {"type": "bool", "default": False},
|
||||
}
|
||||
|
||||
RESOURCE_ARG_SPEC = {
|
||||
'resource_definition': {
|
||||
'type': list_dict_str,
|
||||
'aliases': ['definition', 'inline']
|
||||
},
|
||||
'src': {
|
||||
'type': 'path',
|
||||
},
|
||||
"resource_definition": {"type": list_dict_str, "aliases": ["definition", "inline"]},
|
||||
"src": {"type": "path"},
|
||||
}
|
||||
|
||||
ARG_ATTRIBUTES_BLACKLIST = ('property_path',)
|
||||
ARG_ATTRIBUTES_BLACKLIST = ("property_path",)
|
||||
|
||||
DELETE_OPTS_ARG_SPEC = {
|
||||
'propagationPolicy': {
|
||||
'choices': ['Foreground', 'Background', 'Orphan'],
|
||||
"propagationPolicy": {"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,27 +13,35 @@
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from collections import defaultdict
|
||||
import hashlib
|
||||
import tempfile
|
||||
from collections import defaultdict
|
||||
from functools import partial
|
||||
|
||||
import kubernetes.dynamic
|
||||
import kubernetes.dynamic.discovery
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.client.resource import (
|
||||
ResourceList,
|
||||
)
|
||||
from kubernetes import __version__
|
||||
from kubernetes.dynamic.exceptions import (ResourceNotFoundError, ResourceNotUniqueError,
|
||||
ServiceUnavailableError)
|
||||
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.client.resource import ResourceList
|
||||
from kubernetes.dynamic.exceptions import (
|
||||
ResourceNotFoundError,
|
||||
ResourceNotUniqueError,
|
||||
ServiceUnavailableError,
|
||||
)
|
||||
|
||||
|
||||
class Discoverer(kubernetes.dynamic.discovery.Discoverer):
|
||||
def __init__(self, client, cache_file):
|
||||
self.client = client
|
||||
default_cache_file_name = 'k8srcp-{0}.json'.format(hashlib.sha256(self.__get_default_cache_id()).hexdigest())
|
||||
self.__cache_file = cache_file or os.path.join(tempfile.gettempdir(), default_cache_file_name)
|
||||
default_cache_file_name = "k8srcp-{0}.json".format(
|
||||
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()
|
||||
|
||||
def __get_default_cache_id(self):
|
||||
@@ -42,21 +50,21 @@ class Discoverer(kubernetes.dynamic.discovery.Discoverer):
|
||||
cache_id = "{0}-{1}".format(self.client.configuration.host, user)
|
||||
else:
|
||||
cache_id = self.client.configuration.host
|
||||
return cache_id.encode('utf-8')
|
||||
return cache_id.encode("utf-8")
|
||||
|
||||
def __get_user(self):
|
||||
# This is intended to provide a portable method for getting a username.
|
||||
# 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
|
||||
# place.
|
||||
if hasattr(os, 'getlogin'):
|
||||
if hasattr(os, "getlogin"):
|
||||
try:
|
||||
user = os.getlogin()
|
||||
if user:
|
||||
return str(user)
|
||||
except OSError:
|
||||
pass
|
||||
if hasattr(os, 'getuid'):
|
||||
if hasattr(os, "getuid"):
|
||||
try:
|
||||
user = os.getuid()
|
||||
if user:
|
||||
@@ -70,13 +78,13 @@ class Discoverer(kubernetes.dynamic.discovery.Discoverer):
|
||||
|
||||
def __init_cache(self, refresh=False):
|
||||
if refresh or not os.path.exists(self.__cache_file):
|
||||
self._cache = {'library_version': __version__}
|
||||
self._cache = {"library_version": __version__}
|
||||
refresh = True
|
||||
else:
|
||||
try:
|
||||
with open(self.__cache_file, 'r') as f:
|
||||
with open(self.__cache_file, "r") as f:
|
||||
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
|
||||
self.invalidate_cache()
|
||||
except Exception:
|
||||
@@ -87,26 +95,30 @@ class Discoverer(kubernetes.dynamic.discovery.Discoverer):
|
||||
self._write_cache()
|
||||
|
||||
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)
|
||||
subresources = defaultdict(dict)
|
||||
|
||||
path = '/'.join(filter(None, [prefix, group, version]))
|
||||
path = "/".join(filter(None, [prefix, group, version]))
|
||||
try:
|
||||
resources_response = self.client.request('GET', path).resources or []
|
||||
resources_response = self.client.request("GET", path).resources or []
|
||||
except ServiceUnavailableError:
|
||||
resources_response = []
|
||||
|
||||
resources_raw = list(filter(lambda resource: '/' not in resource['name'], resources_response))
|
||||
subresources_raw = list(filter(lambda resource: '/' in resource['name'], resources_response))
|
||||
resources_raw = list(
|
||||
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:
|
||||
resource, name = subresource['name'].split('/')
|
||||
resource, name = subresource["name"].split("/", 1)
|
||||
subresources[resource][name] = subresource
|
||||
|
||||
for resource in resources_raw:
|
||||
# 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)
|
||||
|
||||
resourceobj = kubernetes.dynamic.Resource(
|
||||
@@ -115,19 +127,25 @@ class Discoverer(kubernetes.dynamic.discovery.Discoverer):
|
||||
api_version=version,
|
||||
client=self.client,
|
||||
preferred=preferred,
|
||||
subresources=subresources.get(resource['name']),
|
||||
subresources=subresources.get(resource["name"]),
|
||||
**resource
|
||||
)
|
||||
resources[resource['kind']].append(resourceobj)
|
||||
resources[resource["kind"]].append(resourceobj)
|
||||
|
||||
resource_lookup = {
|
||||
'prefix': prefix,
|
||||
'group': group,
|
||||
'api_version': version,
|
||||
'kind': resourceobj.kind,
|
||||
'name': resourceobj.name
|
||||
"prefix": prefix,
|
||||
"group": group,
|
||||
"api_version": version,
|
||||
"kind": resourceobj.kind,
|
||||
"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)
|
||||
return resources
|
||||
|
||||
@@ -139,23 +157,32 @@ class Discoverer(kubernetes.dynamic.discovery.Discoverer):
|
||||
"""
|
||||
results = self.search(**kwargs)
|
||||
# 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 = [
|
||||
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 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 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:
|
||||
results = [max(results, key=lambda x: len(x.verbs))]
|
||||
if len(results) == 1:
|
||||
return results[0]
|
||||
elif not results:
|
||||
raise ResourceNotFoundError('No matches found for {0}'.format(kwargs))
|
||||
raise ResourceNotFoundError("No matches found for {0}".format(kwargs))
|
||||
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):
|
||||
@@ -174,13 +201,15 @@ class CacheDecoder(json.JSONDecoder):
|
||||
json.JSONDecoder.__init__(self, object_hook=self.object_hook, *args, **kwargs)
|
||||
|
||||
def object_hook(self, obj):
|
||||
if '_type' not in obj:
|
||||
if "_type" not in obj:
|
||||
return obj
|
||||
_type = obj.pop('_type')
|
||||
if _type == 'Resource':
|
||||
_type = obj.pop("_type")
|
||||
if _type == "Resource":
|
||||
return kubernetes.dynamic.Resource(client=self.client, **obj)
|
||||
elif _type == 'ResourceList':
|
||||
elif _type == "ResourceList":
|
||||
return ResourceList(self.client, **obj)
|
||||
elif _type == 'ResourceGroup':
|
||||
return kubernetes.dynamic.discovery.ResourceGroup(obj['preferred'], resources=self.object_hook(obj['resources']))
|
||||
elif _type == "ResourceGroup":
|
||||
return kubernetes.dynamic.discovery.ResourceGroup(
|
||||
obj["preferred"], resources=self.object_hook(obj["resources"])
|
||||
)
|
||||
return obj
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
@@ -21,11 +22,19 @@ import kubernetes.dynamic
|
||||
|
||||
|
||||
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.group = group
|
||||
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_resource_lookup = base_resource_lookup
|
||||
self.__base_resource = None
|
||||
@@ -34,16 +43,18 @@ class ResourceList(kubernetes.dynamic.resource.ResourceList):
|
||||
if self.__base_resource:
|
||||
return self.__base_resource
|
||||
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 None
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'_type': 'ResourceList',
|
||||
'group': self.group,
|
||||
'api_version': self.api_version,
|
||||
'kind': self.kind,
|
||||
'base_kind': self.base_kind,
|
||||
'base_resource_lookup': self.base_resource_lookup
|
||||
"_type": "ResourceList",
|
||||
"group": self.group,
|
||||
"api_version": self.api_version,
|
||||
"kind": self.kind,
|
||||
"base_kind": self.base_kind,
|
||||
"base_resource_lookup": self.base_resource_lookup,
|
||||
}
|
||||
|
||||
@@ -16,913 +16,50 @@
|
||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
import base64
|
||||
import time
|
||||
import os
|
||||
import traceback
|
||||
import sys
|
||||
import hashlib
|
||||
from datetime import datetime
|
||||
from distutils.version import LooseVersion
|
||||
from tempfile import NamedTemporaryFile
|
||||
|
||||
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.hashes import generate_hash
|
||||
from ansible_collections.kubernetes.core.plugins.module_utils.selector import LabelSelectorFilter
|
||||
|
||||
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 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
|
||||
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
|
||||
from ansible.module_utils.urls import Request
|
||||
|
||||
try:
|
||||
import urllib3
|
||||
|
||||
urllib3.disable_warnings()
|
||||
except ImportError:
|
||||
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 kubernetes.dynamic.resource import ResourceInstance
|
||||
HAS_K8S_INSTANCE_HELPER = True
|
||||
k8s_import_exception = None
|
||||
except ImportError as e:
|
||||
HAS_K8S_INSTANCE_HELPER = False
|
||||
k8s_import_exception = e
|
||||
K8S_IMP_ERR = traceback.format_exc()
|
||||
|
||||
|
||||
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=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) 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 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)
|
||||
|
||||
def _load_config():
|
||||
kubeconfig = auth.get('kubeconfig')
|
||||
optional_arg = {
|
||||
'context': auth.get('context'),
|
||||
'persist_config': auth.get('persist_config'),
|
||||
}
|
||||
if kubeconfig:
|
||||
if isinstance(kubeconfig, string_types):
|
||||
kubernetes.config.load_kube_config(config_file=kubeconfig, **optional_arg)
|
||||
elif isinstance(kubeconfig, dict):
|
||||
if LooseVersion(kubernetes.__version__) < LooseVersion("17.17"):
|
||||
_raise_or_fail(Exception("kubernetes >= 17.17.0 is required to use in-memory kubeconfig."), 'Failed to load kubeconfig due to: %s')
|
||||
kubernetes.config.load_kube_config_from_dict(config_dict=kubeconfig, **optional_arg)
|
||||
else:
|
||||
kubernetes.config.load_kube_config(config_file=None, **optional_arg)
|
||||
|
||||
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:
|
||||
_load_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:
|
||||
_load_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
|
||||
def fetch_file_from_url(module, url):
|
||||
# Download file
|
||||
bufsize = 65536
|
||||
file_name, file_ext = os.path.splitext(str(url.rsplit("/", 1)[1]))
|
||||
temp_file = NamedTemporaryFile(
|
||||
dir=module.tmpdir, prefix=file_name, suffix=file_ext, delete=False
|
||||
)
|
||||
module.add_cleanup_file(temp_file.name)
|
||||
try:
|
||||
configuration = kubernetes.client.Configuration().get_default_copy()
|
||||
except AttributeError:
|
||||
configuration = kubernetes.client.Configuration()
|
||||
|
||||
for key, value in iteritems(auth):
|
||||
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)
|
||||
|
||||
digest = configuration_digest(configuration)
|
||||
if digest in get_api_client._pool:
|
||||
client = get_api_client._pool[digest]
|
||||
return client
|
||||
|
||||
try:
|
||||
client = k8sdynamicclient.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, pyyaml_required=True, *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 pyyaml_required and 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, label_selectors):
|
||||
start = datetime.now()
|
||||
|
||||
def _wait_for_elapsed():
|
||||
return (datetime.now() - start).seconds
|
||||
|
||||
response = None
|
||||
while _wait_for_elapsed() < timeout:
|
||||
try:
|
||||
params = dict(name=name, namespace=namespace)
|
||||
if label_selectors:
|
||||
params['label_selector'] = ','.join(label_selectors)
|
||||
response = resource.get(**params)
|
||||
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, label_selectors=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 _statefulset_ready(statefulset):
|
||||
return (statefulset.status and statefulset.spec.updateStrategy.type == "RollingUpdate"
|
||||
and statefulset.status.observedGeneration == (statefulset.metadata.generation or 0)
|
||||
and statefulset.status.updateRevision == statefulset.status.currentRevision
|
||||
and statefulset.status.updatedReplicas == statefulset.spec.replicas
|
||||
and statefulset.status.readyReplicas == statefulset.spec.replicas
|
||||
and statefulset.status.replicas == statefulset.spec.replicas)
|
||||
|
||||
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 or (resource.kind.endswith('List') and resource.items == [])
|
||||
|
||||
waiter = dict(
|
||||
StatefulSet=_statefulset_ready,
|
||||
Deployment=_deployment_ready,
|
||||
DaemonSet=_daemonset_ready,
|
||||
Pod=_pod_ready
|
||||
)
|
||||
kind = definition['kind']
|
||||
if state == 'present':
|
||||
predicate = waiter.get(kind, lambda x: x) if not condition else _custom_condition
|
||||
else:
|
||||
predicate = _resource_absent
|
||||
name = definition['metadata']['name']
|
||||
namespace = definition['metadata'].get('namespace')
|
||||
return self._wait_for(resource, name, namespace, predicate, sleep, timeout, state, label_selectors)
|
||||
|
||||
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')
|
||||
label_selectors = self.params.get('label_selectors')
|
||||
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
|
||||
if label_selectors:
|
||||
params['label_selector'] = ','.join(label_selectors)
|
||||
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"
|
||||
|
||||
def _empty_resource_list():
|
||||
if existing and existing.kind.endswith('List'):
|
||||
return existing.items == []
|
||||
return False
|
||||
|
||||
if not existing or _empty_resource_list():
|
||||
# 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', label_selectors=label_selectors)
|
||||
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 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=definition['kind'], name=origin_name, namespace=namespace)
|
||||
return result
|
||||
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
|
||||
if self.module._diff:
|
||||
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'
|
||||
if self.module._diff:
|
||||
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'
|
||||
if self.module._diff:
|
||||
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
|
||||
rsp = Request().open("GET", url)
|
||||
if not rsp:
|
||||
module.fail_json(msg="Failure downloading %s" % url)
|
||||
data = rsp.read(bufsize)
|
||||
while data:
|
||||
temp_file.write(data)
|
||||
data = rsp.read(bufsize)
|
||||
temp_file.close()
|
||||
except Exception as e:
|
||||
module.fail_json(msg="Failure downloading %s, %s" % (url, to_native(e)))
|
||||
return temp_file.name
|
||||
|
||||
|
||||
def _encode_stringdata(definition):
|
||||
if definition['kind'] == 'Secret' and 'stringData' in definition:
|
||||
for k, v in definition['stringData'].items():
|
||||
if definition["kind"] == "Secret" and "stringData" in definition:
|
||||
for k, v in definition["stringData"].items():
|
||||
encoded = base64.b64encode(to_bytes(v))
|
||||
definition.setdefault('data', {})[k] = to_text(encoded)
|
||||
del definition['stringData']
|
||||
definition.setdefault("data", {})[k] = to_text(encoded)
|
||||
del definition["stringData"]
|
||||
return definition
|
||||
|
||||
459
plugins/module_utils/copy.py
Normal file
459
plugins/module_utils/copy.py
Normal file
@@ -0,0 +1,459 @@
|
||||
# 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.common.text.converters 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 == []:
|
||||
# Using warn method instead of passing warnings to exit_json as it is
|
||||
# deprecated in ansible-core>=2.19.0
|
||||
self._module.warn(
|
||||
"No file found from directory '{0}' into remote Pod.".format(
|
||||
self.remote_path
|
||||
)
|
||||
)
|
||||
self.module.exit_json(
|
||||
changed=False,
|
||||
)
|
||||
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
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
class ApplyException(Exception):
|
||||
""" Could not apply patch """
|
||||
"""Could not apply patch"""
|
||||
|
||||
@@ -15,14 +15,16 @@
|
||||
# Implement ConfigMapHash and SecretHash equivalents
|
||||
# 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
|
||||
|
||||
import json
|
||||
import hashlib
|
||||
import json
|
||||
|
||||
try:
|
||||
import string
|
||||
|
||||
maketrans = string.maketrans
|
||||
except AttributeError:
|
||||
maketrans = str.maketrans
|
||||
@@ -35,7 +37,7 @@ except ImportError:
|
||||
|
||||
def sorted_dict(unsorted_dict):
|
||||
result = OrderedDict()
|
||||
for (k, v) in sorted(unsorted_dict.items()):
|
||||
for k, v in sorted(unsorted_dict.items()):
|
||||
if isinstance(v, dict):
|
||||
v = sorted_dict(v)
|
||||
result[k] = v
|
||||
@@ -44,14 +46,21 @@ def sorted_dict(unsorted_dict):
|
||||
|
||||
def generate_hash(resource):
|
||||
# Get name from metadata
|
||||
resource['name'] = resource.get('metadata', {}).get('name', '')
|
||||
if resource['kind'] == 'ConfigMap':
|
||||
marshalled = marshal(sorted_dict(resource), ['data', 'kind', 'name'])
|
||||
del(resource['name'])
|
||||
metada = resource.get("metadata", {})
|
||||
key = "name"
|
||||
resource["name"] = metada.get("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)
|
||||
if resource['kind'] == 'Secret':
|
||||
marshalled = marshal(sorted_dict(resource), ['data', 'kind', 'name', 'type'])
|
||||
del(resource['name'])
|
||||
if resource["kind"] == "Secret":
|
||||
marshalled = marshal(sorted_dict(resource), ["data", "kind", key, "type"])
|
||||
del resource[key]
|
||||
return encode(marshalled)
|
||||
raise NotImplementedError
|
||||
|
||||
@@ -60,8 +69,10 @@ def marshal(data, keys):
|
||||
ordered = OrderedDict()
|
||||
for key in keys:
|
||||
ordered[key] = data.get(key, "")
|
||||
return json.dumps(ordered, separators=(',', ':')).encode('utf-8')
|
||||
return json.dumps(ordered, separators=(",", ":")).encode("utf-8")
|
||||
|
||||
|
||||
def encode(resource):
|
||||
return hashlib.sha256(resource).hexdigest()[:10].translate(maketrans("013ae", "ghkmt"))
|
||||
return (
|
||||
hashlib.sha256(resource).hexdigest()[:10].translate(maketrans("013ae", "ghkmt"))
|
||||
)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user