mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-04-30 10:26:52 +00:00
Compare commits
104 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d8b0108796 | ||
|
|
8a0794d330 | ||
|
|
2c1172d5d2 | ||
|
|
e49a26b6ab | ||
|
|
a781573977 | ||
|
|
88b1d1e0c1 | ||
|
|
45dd6a59f8 | ||
|
|
71bf1184ef | ||
|
|
855201d9fb | ||
|
|
4a6ed38ee2 | ||
|
|
c4ea44ffb4 | ||
|
|
2109d10740 | ||
|
|
d32a2e0df9 | ||
|
|
4f5a5a5c3d | ||
|
|
372639ba58 | ||
|
|
0e69322924 | ||
|
|
f436839cb8 | ||
|
|
641f7c0890 | ||
|
|
36bd15c804 | ||
|
|
2d226ad94d | ||
|
|
fade5f539c | ||
|
|
2e1ac61ca9 | ||
|
|
f2d078ebf0 | ||
|
|
fee6fcfbdd | ||
|
|
393358bbb1 | ||
|
|
b98cc00fa3 | ||
|
|
9d51e05cfb | ||
|
|
440bdb1119 | ||
|
|
d02f564019 | ||
|
|
adddf455fb | ||
|
|
0e3d9e1497 | ||
|
|
fec312eb54 | ||
|
|
f7b1393752 | ||
|
|
6f8d1849b5 | ||
|
|
6a4bc401c5 | ||
|
|
f5f1a33a7e | ||
|
|
0b0a4b0eaa | ||
|
|
24e5bf3d5b | ||
|
|
4f0b5b88a1 | ||
|
|
be4e7fc374 | ||
|
|
ba9f295b3f | ||
|
|
4b4a2a5977 | ||
|
|
5a1ee4e3ee | ||
|
|
11c0f9642c | ||
|
|
e42353d690 | ||
|
|
5af750d06b | ||
|
|
f745dd369e | ||
|
|
745c7a856e | ||
|
|
4e1e5a92e3 | ||
|
|
12b39987a0 | ||
|
|
32338f14e5 | ||
|
|
2583e3993d | ||
|
|
e4cef5cb24 | ||
|
|
cde2be8100 | ||
|
|
40ce650d08 | ||
|
|
c09b5e2c66 | ||
|
|
a618203c01 | ||
|
|
882ce25ce2 | ||
|
|
25a6603059 | ||
|
|
065287f260 | ||
|
|
b0cf8ce6e7 | ||
|
|
68eb07a900 | ||
|
|
a7d8397449 | ||
|
|
c71274639d | ||
|
|
5ef9476207 | ||
|
|
36edaaa6ea | ||
|
|
5c80ff00ab | ||
|
|
a45cb0ca04 | ||
|
|
838ff55003 | ||
|
|
8927dc777a | ||
|
|
baeae01797 | ||
|
|
c3df54689c | ||
|
|
e043274ced | ||
|
|
1355b8d533 | ||
|
|
5ea46a581d | ||
|
|
a8be2e2a58 | ||
|
|
07fa35791f | ||
|
|
06a3e3708d | ||
|
|
56532388fd | ||
|
|
6d09a3588e | ||
|
|
a73404ae3f | ||
|
|
ddf566a729 | ||
|
|
0c676df7cf | ||
|
|
3dcdd3b59e | ||
|
|
8b2e658fc0 | ||
|
|
9bf146a67a | ||
|
|
567b573971 | ||
|
|
b7b781a2be | ||
|
|
f852ac90a2 | ||
|
|
77f64cc56d | ||
|
|
faa3b7349f | ||
|
|
3fd8c520c6 | ||
|
|
5e5cba985f | ||
|
|
8bfd8bfb09 | ||
|
|
533df42e6f | ||
|
|
ac86d28687 | ||
|
|
6cffa0f84f | ||
|
|
78847004c2 | ||
|
|
84320bacb2 | ||
|
|
351eb7292c | ||
|
|
952ee5c5e8 | ||
|
|
14a0e387ac | ||
|
|
c5ada449e4 | ||
|
|
22d8e99282 |
@@ -1,9 +0,0 @@
|
|||||||
<!--
|
|
||||||
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
|
|
||||||
-->
|
|
||||||
|
|
||||||
## Azure Pipelines Configuration
|
|
||||||
|
|
||||||
Please see the [Documentation](https://github.com/ansible/community/wiki/Testing:-Azure-Pipelines) for more information.
|
|
||||||
@@ -1,421 +0,0 @@
|
|||||||
---
|
|
||||||
# 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
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
batch: true
|
|
||||||
branches:
|
|
||||||
include:
|
|
||||||
- main
|
|
||||||
- stable-*
|
|
||||||
|
|
||||||
pr:
|
|
||||||
autoCancel: true
|
|
||||||
branches:
|
|
||||||
include:
|
|
||||||
- main
|
|
||||||
- stable-*
|
|
||||||
|
|
||||||
schedules:
|
|
||||||
- cron: 0 8 * * *
|
|
||||||
displayName: Nightly (main)
|
|
||||||
always: true
|
|
||||||
branches:
|
|
||||||
include:
|
|
||||||
- main
|
|
||||||
- cron: 0 10 * * *
|
|
||||||
displayName: Nightly (active stable branches)
|
|
||||||
always: true
|
|
||||||
branches:
|
|
||||||
include:
|
|
||||||
- stable-8
|
|
||||||
- stable-7
|
|
||||||
- cron: 0 11 * * 0
|
|
||||||
displayName: Weekly (old stable branches)
|
|
||||||
always: true
|
|
||||||
branches:
|
|
||||||
include:
|
|
||||||
- stable-6
|
|
||||||
|
|
||||||
variables:
|
|
||||||
- name: checkoutPath
|
|
||||||
value: ansible_collections/community/general
|
|
||||||
- name: coverageBranches
|
|
||||||
value: main
|
|
||||||
- name: pipelinesCoverage
|
|
||||||
value: coverage
|
|
||||||
- name: entryPoint
|
|
||||||
value: tests/utils/shippable/shippable.sh
|
|
||||||
- name: fetchDepth
|
|
||||||
value: 0
|
|
||||||
|
|
||||||
resources:
|
|
||||||
containers:
|
|
||||||
- container: default
|
|
||||||
image: quay.io/ansible/azure-pipelines-test-container:4.0.1
|
|
||||||
|
|
||||||
pool: Standard
|
|
||||||
|
|
||||||
stages:
|
|
||||||
### Sanity
|
|
||||||
- stage: Sanity_devel
|
|
||||||
displayName: Sanity devel
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
nameFormat: Test {0}
|
|
||||||
testFormat: devel/sanity/{0}
|
|
||||||
targets:
|
|
||||||
- test: 1
|
|
||||||
- test: 2
|
|
||||||
- test: 3
|
|
||||||
- test: 4
|
|
||||||
- test: extra
|
|
||||||
- stage: Sanity_2_16
|
|
||||||
displayName: Sanity 2.16
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
nameFormat: Test {0}
|
|
||||||
testFormat: 2.16/sanity/{0}
|
|
||||||
targets:
|
|
||||||
- test: 1
|
|
||||||
- test: 2
|
|
||||||
- test: 3
|
|
||||||
- test: 4
|
|
||||||
- stage: Sanity_2_15
|
|
||||||
displayName: Sanity 2.15
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
nameFormat: Test {0}
|
|
||||||
testFormat: 2.15/sanity/{0}
|
|
||||||
targets:
|
|
||||||
- test: 1
|
|
||||||
- test: 2
|
|
||||||
- test: 3
|
|
||||||
- test: 4
|
|
||||||
- stage: Sanity_2_14
|
|
||||||
displayName: Sanity 2.14
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
nameFormat: Test {0}
|
|
||||||
testFormat: 2.14/sanity/{0}
|
|
||||||
targets:
|
|
||||||
- test: 1
|
|
||||||
- test: 2
|
|
||||||
- test: 3
|
|
||||||
- test: 4
|
|
||||||
### Units
|
|
||||||
- stage: Units_devel
|
|
||||||
displayName: Units devel
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
nameFormat: Python {0}
|
|
||||||
testFormat: devel/units/{0}/1
|
|
||||||
targets:
|
|
||||||
- test: 3.7
|
|
||||||
- test: 3.8
|
|
||||||
- test: 3.9
|
|
||||||
- test: '3.10'
|
|
||||||
- test: '3.11'
|
|
||||||
- test: '3.12'
|
|
||||||
- stage: Units_2_16
|
|
||||||
displayName: Units 2.16
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
nameFormat: Python {0}
|
|
||||||
testFormat: 2.16/units/{0}/1
|
|
||||||
targets:
|
|
||||||
- test: 2.7
|
|
||||||
- test: 3.6
|
|
||||||
- test: "3.11"
|
|
||||||
- stage: Units_2_15
|
|
||||||
displayName: Units 2.15
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
nameFormat: Python {0}
|
|
||||||
testFormat: 2.15/units/{0}/1
|
|
||||||
targets:
|
|
||||||
- test: 3.5
|
|
||||||
- test: "3.10"
|
|
||||||
- stage: Units_2_14
|
|
||||||
displayName: Units 2.14
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
nameFormat: Python {0}
|
|
||||||
testFormat: 2.14/units/{0}/1
|
|
||||||
targets:
|
|
||||||
- test: 3.9
|
|
||||||
|
|
||||||
## Remote
|
|
||||||
- stage: Remote_devel_extra_vms
|
|
||||||
displayName: Remote devel extra VMs
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
testFormat: devel/{0}
|
|
||||||
targets:
|
|
||||||
- name: Alpine 3.18
|
|
||||||
test: alpine/3.18
|
|
||||||
# - name: Fedora 39
|
|
||||||
# test: fedora/39
|
|
||||||
- name: Ubuntu 22.04
|
|
||||||
test: ubuntu/22.04
|
|
||||||
groups:
|
|
||||||
- vm
|
|
||||||
- stage: Remote_devel
|
|
||||||
displayName: Remote devel
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
testFormat: devel/{0}
|
|
||||||
targets:
|
|
||||||
- name: macOS 13.2
|
|
||||||
test: macos/13.2
|
|
||||||
- name: RHEL 9.3
|
|
||||||
test: rhel/9.3
|
|
||||||
- name: FreeBSD 13.2
|
|
||||||
test: freebsd/13.2
|
|
||||||
groups:
|
|
||||||
- 1
|
|
||||||
- 2
|
|
||||||
- 3
|
|
||||||
- stage: Remote_2_16
|
|
||||||
displayName: Remote 2.16
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
testFormat: 2.16/{0}
|
|
||||||
targets:
|
|
||||||
#- name: macOS 13.2
|
|
||||||
# test: macos/13.2
|
|
||||||
- name: RHEL 9.2
|
|
||||||
test: rhel/9.2
|
|
||||||
- name: RHEL 8.8
|
|
||||||
test: rhel/8.8
|
|
||||||
#- name: FreeBSD 13.2
|
|
||||||
# test: freebsd/13.2
|
|
||||||
groups:
|
|
||||||
- 1
|
|
||||||
- 2
|
|
||||||
- 3
|
|
||||||
- stage: Remote_2_15
|
|
||||||
displayName: Remote 2.15
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
testFormat: 2.15/{0}
|
|
||||||
targets:
|
|
||||||
- name: RHEL 9.1
|
|
||||||
test: rhel/9.1
|
|
||||||
- name: RHEL 8.7
|
|
||||||
test: rhel/8.7
|
|
||||||
- name: RHEL 7.9
|
|
||||||
test: rhel/7.9
|
|
||||||
# - name: FreeBSD 13.1
|
|
||||||
# test: freebsd/13.1
|
|
||||||
# - name: FreeBSD 12.4
|
|
||||||
# test: freebsd/12.4
|
|
||||||
groups:
|
|
||||||
- 1
|
|
||||||
- 2
|
|
||||||
- 3
|
|
||||||
- stage: Remote_2_14
|
|
||||||
displayName: Remote 2.14
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
testFormat: 2.14/{0}
|
|
||||||
targets:
|
|
||||||
- name: RHEL 9.0
|
|
||||||
test: rhel/9.0
|
|
||||||
#- name: macOS 12.0
|
|
||||||
# test: macos/12.0
|
|
||||||
#- name: FreeBSD 12.4
|
|
||||||
# test: freebsd/12.4
|
|
||||||
groups:
|
|
||||||
- 1
|
|
||||||
- 2
|
|
||||||
- 3
|
|
||||||
|
|
||||||
### Docker
|
|
||||||
- stage: Docker_devel
|
|
||||||
displayName: Docker devel
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
testFormat: devel/linux/{0}
|
|
||||||
targets:
|
|
||||||
- name: Fedora 39
|
|
||||||
test: fedora39
|
|
||||||
- name: Ubuntu 20.04
|
|
||||||
test: ubuntu2004
|
|
||||||
- name: Ubuntu 22.04
|
|
||||||
test: ubuntu2204
|
|
||||||
- name: Alpine 3
|
|
||||||
test: alpine3
|
|
||||||
groups:
|
|
||||||
- 1
|
|
||||||
- 2
|
|
||||||
- 3
|
|
||||||
- stage: Docker_2_16
|
|
||||||
displayName: Docker 2.16
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
testFormat: 2.16/linux/{0}
|
|
||||||
targets:
|
|
||||||
- name: Fedora 38
|
|
||||||
test: fedora38
|
|
||||||
- name: openSUSE 15
|
|
||||||
test: opensuse15
|
|
||||||
groups:
|
|
||||||
- 1
|
|
||||||
- 2
|
|
||||||
- 3
|
|
||||||
- stage: Docker_2_15
|
|
||||||
displayName: Docker 2.15
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
testFormat: 2.15/linux/{0}
|
|
||||||
targets:
|
|
||||||
- name: Fedora 37
|
|
||||||
test: fedora37
|
|
||||||
- name: CentOS 7
|
|
||||||
test: centos7
|
|
||||||
groups:
|
|
||||||
- 1
|
|
||||||
- 2
|
|
||||||
- 3
|
|
||||||
- stage: Docker_2_14
|
|
||||||
displayName: Docker 2.14
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
testFormat: 2.14/linux/{0}
|
|
||||||
targets:
|
|
||||||
- name: Alpine 3
|
|
||||||
test: alpine3
|
|
||||||
groups:
|
|
||||||
- 1
|
|
||||||
- 2
|
|
||||||
- 3
|
|
||||||
|
|
||||||
### Community Docker
|
|
||||||
- stage: Docker_community_devel
|
|
||||||
displayName: Docker (community images) devel
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
testFormat: devel/linux-community/{0}
|
|
||||||
targets:
|
|
||||||
- name: Debian Bullseye
|
|
||||||
test: debian-bullseye/3.9
|
|
||||||
- name: Debian Bookworm
|
|
||||||
test: debian-bookworm/3.11
|
|
||||||
- name: ArchLinux
|
|
||||||
test: archlinux/3.11
|
|
||||||
groups:
|
|
||||||
- 1
|
|
||||||
- 2
|
|
||||||
- 3
|
|
||||||
|
|
||||||
### Generic
|
|
||||||
- stage: Generic_devel
|
|
||||||
displayName: Generic devel
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
nameFormat: Python {0}
|
|
||||||
testFormat: devel/generic/{0}/1
|
|
||||||
targets:
|
|
||||||
- test: '3.7'
|
|
||||||
- test: '3.12'
|
|
||||||
- stage: Generic_2_16
|
|
||||||
displayName: Generic 2.16
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
nameFormat: Python {0}
|
|
||||||
testFormat: 2.16/generic/{0}/1
|
|
||||||
targets:
|
|
||||||
- test: '2.7'
|
|
||||||
- test: '3.6'
|
|
||||||
- test: '3.11'
|
|
||||||
- stage: Generic_2_15
|
|
||||||
displayName: Generic 2.15
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
nameFormat: Python {0}
|
|
||||||
testFormat: 2.15/generic/{0}/1
|
|
||||||
targets:
|
|
||||||
- test: '3.9'
|
|
||||||
- stage: Generic_2_14
|
|
||||||
displayName: Generic 2.14
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
nameFormat: Python {0}
|
|
||||||
testFormat: 2.14/generic/{0}/1
|
|
||||||
targets:
|
|
||||||
- test: '3.10'
|
|
||||||
|
|
||||||
- stage: Summary
|
|
||||||
condition: succeededOrFailed()
|
|
||||||
dependsOn:
|
|
||||||
- Sanity_devel
|
|
||||||
- Sanity_2_16
|
|
||||||
- Sanity_2_15
|
|
||||||
- Sanity_2_14
|
|
||||||
- Units_devel
|
|
||||||
- Units_2_16
|
|
||||||
- Units_2_15
|
|
||||||
- Units_2_14
|
|
||||||
- Remote_devel_extra_vms
|
|
||||||
- Remote_devel
|
|
||||||
- Remote_2_16
|
|
||||||
- Remote_2_15
|
|
||||||
- Remote_2_14
|
|
||||||
- Docker_devel
|
|
||||||
- Docker_2_16
|
|
||||||
- Docker_2_15
|
|
||||||
- Docker_2_14
|
|
||||||
- Docker_community_devel
|
|
||||||
# Right now all generic tests are disabled. Uncomment when at least one of them is re-enabled.
|
|
||||||
# - Generic_devel
|
|
||||||
# - Generic_2_16
|
|
||||||
# - Generic_2_15
|
|
||||||
# - Generic_2_14
|
|
||||||
jobs:
|
|
||||||
- template: templates/coverage.yml
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# Aggregate code coverage results for later processing.
|
|
||||||
|
|
||||||
set -o pipefail -eu
|
|
||||||
|
|
||||||
agent_temp_directory="$1"
|
|
||||||
|
|
||||||
PATH="${PWD}/bin:${PATH}"
|
|
||||||
|
|
||||||
mkdir "${agent_temp_directory}/coverage/"
|
|
||||||
|
|
||||||
options=(--venv --venv-system-site-packages --color -v)
|
|
||||||
|
|
||||||
ansible-test coverage combine --group-by command --export "${agent_temp_directory}/coverage/" "${options[@]}"
|
|
||||||
|
|
||||||
if ansible-test coverage analyze targets generate --help >/dev/null 2>&1; then
|
|
||||||
# Only analyze coverage if the installed version of ansible-test supports it.
|
|
||||||
# Doing so allows this script to work unmodified for multiple Ansible versions.
|
|
||||||
ansible-test coverage analyze targets generate "${agent_temp_directory}/coverage/coverage-analyze-targets.json" "${options[@]}"
|
|
||||||
fi
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# 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
|
|
||||||
|
|
||||||
"""
|
|
||||||
Combine coverage data from multiple jobs, keeping the data only from the most recent attempt from each job.
|
|
||||||
Coverage artifacts must be named using the format: "Coverage $(System.JobAttempt) {StableUniqueNameForEachJob}"
|
|
||||||
The recommended coverage artifact name format is: Coverage $(System.JobAttempt) $(System.StageDisplayName) $(System.JobDisplayName)
|
|
||||||
Keep in mind that Azure Pipelines does not enforce unique job display names (only names).
|
|
||||||
It is up to pipeline authors to avoid name collisions when deviating from the recommended format.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import shutil
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Main program entry point."""
|
|
||||||
source_directory = sys.argv[1]
|
|
||||||
|
|
||||||
if '/ansible_collections/' in os.getcwd():
|
|
||||||
output_path = "tests/output"
|
|
||||||
else:
|
|
||||||
output_path = "test/results"
|
|
||||||
|
|
||||||
destination_directory = os.path.join(output_path, 'coverage')
|
|
||||||
|
|
||||||
if not os.path.exists(destination_directory):
|
|
||||||
os.makedirs(destination_directory)
|
|
||||||
|
|
||||||
jobs = {}
|
|
||||||
count = 0
|
|
||||||
|
|
||||||
for name in os.listdir(source_directory):
|
|
||||||
match = re.search('^Coverage (?P<attempt>[0-9]+) (?P<label>.+)$', name)
|
|
||||||
label = match.group('label')
|
|
||||||
attempt = int(match.group('attempt'))
|
|
||||||
jobs[label] = max(attempt, jobs.get(label, 0))
|
|
||||||
|
|
||||||
for label, attempt in jobs.items():
|
|
||||||
name = 'Coverage {attempt} {label}'.format(label=label, attempt=attempt)
|
|
||||||
source = os.path.join(source_directory, name)
|
|
||||||
source_files = os.listdir(source)
|
|
||||||
|
|
||||||
for source_file in source_files:
|
|
||||||
source_path = os.path.join(source, source_file)
|
|
||||||
destination_path = os.path.join(destination_directory, source_file + '.' + label)
|
|
||||||
print('"%s" -> "%s"' % (source_path, destination_path))
|
|
||||||
shutil.copyfile(source_path, destination_path)
|
|
||||||
count += 1
|
|
||||||
|
|
||||||
print('Coverage file count: %d' % count)
|
|
||||||
print('##vso[task.setVariable variable=coverageFileCount]%d' % count)
|
|
||||||
print('##vso[task.setVariable variable=outputPath]%s' % output_path)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# Check the test results and set variables for use in later steps.
|
|
||||||
|
|
||||||
set -o pipefail -eu
|
|
||||||
|
|
||||||
if [[ "$PWD" =~ /ansible_collections/ ]]; then
|
|
||||||
output_path="tests/output"
|
|
||||||
else
|
|
||||||
output_path="test/results"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "##vso[task.setVariable variable=outputPath]${output_path}"
|
|
||||||
|
|
||||||
if compgen -G "${output_path}"'/junit/*.xml' > /dev/null; then
|
|
||||||
echo "##vso[task.setVariable variable=haveTestResults]true"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if compgen -G "${output_path}"'/bot/ansible-test-*' > /dev/null; then
|
|
||||||
echo "##vso[task.setVariable variable=haveBotResults]true"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if compgen -G "${output_path}"'/coverage/*' > /dev/null; then
|
|
||||||
echo "##vso[task.setVariable variable=haveCoverageData]true"
|
|
||||||
fi
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# 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
|
|
||||||
|
|
||||||
"""
|
|
||||||
Upload code coverage reports to codecov.io.
|
|
||||||
Multiple coverage files from multiple languages are accepted and aggregated after upload.
|
|
||||||
Python coverage, as well as PowerShell and Python stubs can all be uploaded.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import dataclasses
|
|
||||||
import pathlib
|
|
||||||
import shutil
|
|
||||||
import subprocess
|
|
||||||
import tempfile
|
|
||||||
import typing as t
|
|
||||||
import urllib.request
|
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass(frozen=True)
|
|
||||||
class CoverageFile:
|
|
||||||
name: str
|
|
||||||
path: pathlib.Path
|
|
||||||
flags: t.List[str]
|
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass(frozen=True)
|
|
||||||
class Args:
|
|
||||||
dry_run: bool
|
|
||||||
path: pathlib.Path
|
|
||||||
|
|
||||||
|
|
||||||
def parse_args() -> Args:
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument('-n', '--dry-run', action='store_true')
|
|
||||||
parser.add_argument('path', type=pathlib.Path)
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
# Store arguments in a typed dataclass
|
|
||||||
fields = dataclasses.fields(Args)
|
|
||||||
kwargs = {field.name: getattr(args, field.name) for field in fields}
|
|
||||||
|
|
||||||
return Args(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
def process_files(directory: pathlib.Path) -> t.Tuple[CoverageFile, ...]:
|
|
||||||
processed = []
|
|
||||||
for file in directory.joinpath('reports').glob('coverage*.xml'):
|
|
||||||
name = file.stem.replace('coverage=', '')
|
|
||||||
|
|
||||||
# Get flags from name
|
|
||||||
flags = name.replace('-powershell', '').split('=') # Drop '-powershell' suffix
|
|
||||||
flags = [flag if not flag.startswith('stub') else flag.split('-')[0] for flag in flags] # Remove "-01" from stub files
|
|
||||||
|
|
||||||
processed.append(CoverageFile(name, file, flags))
|
|
||||||
|
|
||||||
return tuple(processed)
|
|
||||||
|
|
||||||
|
|
||||||
def upload_files(codecov_bin: pathlib.Path, files: t.Tuple[CoverageFile, ...], dry_run: bool = False) -> None:
|
|
||||||
for file in files:
|
|
||||||
cmd = [
|
|
||||||
str(codecov_bin),
|
|
||||||
'--name', file.name,
|
|
||||||
'--file', str(file.path),
|
|
||||||
]
|
|
||||||
for flag in file.flags:
|
|
||||||
cmd.extend(['--flags', flag])
|
|
||||||
|
|
||||||
if dry_run:
|
|
||||||
print(f'DRY-RUN: Would run command: {cmd}')
|
|
||||||
continue
|
|
||||||
|
|
||||||
subprocess.run(cmd, check=True)
|
|
||||||
|
|
||||||
|
|
||||||
def download_file(url: str, dest: pathlib.Path, flags: int, dry_run: bool = False) -> None:
|
|
||||||
if dry_run:
|
|
||||||
print(f'DRY-RUN: Would download {url} to {dest} and set mode to {flags:o}')
|
|
||||||
return
|
|
||||||
|
|
||||||
with urllib.request.urlopen(url) as resp:
|
|
||||||
with dest.open('w+b') as f:
|
|
||||||
# Read data in chunks rather than all at once
|
|
||||||
shutil.copyfileobj(resp, f, 64 * 1024)
|
|
||||||
|
|
||||||
dest.chmod(flags)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
args = parse_args()
|
|
||||||
url = 'https://ansible-ci-files.s3.amazonaws.com/codecov/linux/codecov'
|
|
||||||
with tempfile.TemporaryDirectory(prefix='codecov-') as tmpdir:
|
|
||||||
codecov_bin = pathlib.Path(tmpdir) / 'codecov'
|
|
||||||
download_file(url, codecov_bin, 0o755, args.dry_run)
|
|
||||||
|
|
||||||
files = process_files(args.path)
|
|
||||||
upload_files(codecov_bin, files, args.dry_run)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# Generate code coverage reports for uploading to Azure Pipelines and codecov.io.
|
|
||||||
|
|
||||||
set -o pipefail -eu
|
|
||||||
|
|
||||||
PATH="${PWD}/bin:${PATH}"
|
|
||||||
|
|
||||||
if ! ansible-test --help >/dev/null 2>&1; then
|
|
||||||
# Install the devel version of ansible-test for generating code coverage reports.
|
|
||||||
# This is only used by Ansible Collections, which are typically tested against multiple Ansible versions (in separate jobs).
|
|
||||||
# Since a version of ansible-test is required that can work the output from multiple older releases, the devel version is used.
|
|
||||||
pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check
|
|
||||||
fi
|
|
||||||
|
|
||||||
ansible-test coverage xml --group-by command --stub --venv --venv-system-site-packages --color -v
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# Configure the test environment and run the tests.
|
|
||||||
|
|
||||||
set -o pipefail -eu
|
|
||||||
|
|
||||||
entry_point="$1"
|
|
||||||
test="$2"
|
|
||||||
read -r -a coverage_branches <<< "$3" # space separated list of branches to run code coverage on for scheduled builds
|
|
||||||
|
|
||||||
export COMMIT_MESSAGE
|
|
||||||
export COMPLETE
|
|
||||||
export COVERAGE
|
|
||||||
export IS_PULL_REQUEST
|
|
||||||
|
|
||||||
if [ "${SYSTEM_PULLREQUEST_TARGETBRANCH:-}" ]; then
|
|
||||||
IS_PULL_REQUEST=true
|
|
||||||
COMMIT_MESSAGE=$(git log --format=%B -n 1 HEAD^2)
|
|
||||||
else
|
|
||||||
IS_PULL_REQUEST=
|
|
||||||
COMMIT_MESSAGE=$(git log --format=%B -n 1 HEAD)
|
|
||||||
fi
|
|
||||||
|
|
||||||
COMPLETE=
|
|
||||||
COVERAGE=
|
|
||||||
|
|
||||||
if [ "${BUILD_REASON}" = "Schedule" ]; then
|
|
||||||
COMPLETE=yes
|
|
||||||
|
|
||||||
if printf '%s\n' "${coverage_branches[@]}" | grep -q "^${BUILD_SOURCEBRANCHNAME}$"; then
|
|
||||||
COVERAGE=yes
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
"${entry_point}" "${test}" 2>&1 | "$(dirname "$0")/time-command.py"
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# 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
|
|
||||||
|
|
||||||
"""Prepends a relative timestamp to each input line from stdin and writes it to stdout."""
|
|
||||||
|
|
||||||
from __future__ import (absolute_import, division, print_function)
|
|
||||||
__metaclass__ = type
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Main program entry point."""
|
|
||||||
start = time.time()
|
|
||||||
|
|
||||||
sys.stdin.reconfigure(errors='surrogateescape')
|
|
||||||
sys.stdout.reconfigure(errors='surrogateescape')
|
|
||||||
|
|
||||||
for line in sys.stdin:
|
|
||||||
seconds = time.time() - start
|
|
||||||
sys.stdout.write('%02d:%02d %s' % (seconds // 60, seconds % 60, line))
|
|
||||||
sys.stdout.flush()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
---
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# This template adds a job for processing code coverage data.
|
|
||||||
# It will upload results to Azure Pipelines and codecov.io.
|
|
||||||
# Use it from a job stage that completes after all other jobs have completed.
|
|
||||||
# This can be done by placing it in a separate summary stage that runs after the test stage(s) have completed.
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
- job: Coverage
|
|
||||||
displayName: Code Coverage
|
|
||||||
container: default
|
|
||||||
workspace:
|
|
||||||
clean: all
|
|
||||||
steps:
|
|
||||||
- checkout: self
|
|
||||||
fetchDepth: $(fetchDepth)
|
|
||||||
path: $(checkoutPath)
|
|
||||||
- task: DownloadPipelineArtifact@2
|
|
||||||
displayName: Download Coverage Data
|
|
||||||
inputs:
|
|
||||||
path: coverage/
|
|
||||||
patterns: "Coverage */*=coverage.combined"
|
|
||||||
- bash: .azure-pipelines/scripts/combine-coverage.py coverage/
|
|
||||||
displayName: Combine Coverage Data
|
|
||||||
- bash: .azure-pipelines/scripts/report-coverage.sh
|
|
||||||
displayName: Generate Coverage Report
|
|
||||||
condition: gt(variables.coverageFileCount, 0)
|
|
||||||
- task: PublishCodeCoverageResults@1
|
|
||||||
inputs:
|
|
||||||
codeCoverageTool: Cobertura
|
|
||||||
# Azure Pipelines only accepts a single coverage data file.
|
|
||||||
# That means only Python or PowerShell coverage can be uploaded, but not both.
|
|
||||||
# Set the "pipelinesCoverage" variable to determine which type is uploaded.
|
|
||||||
# Use "coverage" for Python and "coverage-powershell" for PowerShell.
|
|
||||||
summaryFileLocation: "$(outputPath)/reports/$(pipelinesCoverage).xml"
|
|
||||||
displayName: Publish to Azure Pipelines
|
|
||||||
condition: gt(variables.coverageFileCount, 0)
|
|
||||||
- bash: .azure-pipelines/scripts/publish-codecov.py "$(outputPath)"
|
|
||||||
displayName: Publish to codecov.io
|
|
||||||
condition: gt(variables.coverageFileCount, 0)
|
|
||||||
continueOnError: true
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
---
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# This template uses the provided targets and optional groups to generate a matrix which is then passed to the test template.
|
|
||||||
# If this matrix template does not provide the required functionality, consider using the test template directly instead.
|
|
||||||
|
|
||||||
parameters:
|
|
||||||
# A required list of dictionaries, one per test target.
|
|
||||||
# Each item in the list must contain a "test" or "name" key.
|
|
||||||
# Both may be provided. If one is omitted, the other will be used.
|
|
||||||
- name: targets
|
|
||||||
type: object
|
|
||||||
|
|
||||||
# An optional list of values which will be used to multiply the targets list into a matrix.
|
|
||||||
# Values can be strings or numbers.
|
|
||||||
- name: groups
|
|
||||||
type: object
|
|
||||||
default: []
|
|
||||||
|
|
||||||
# An optional format string used to generate the job name.
|
|
||||||
# - {0} is the name of an item in the targets list.
|
|
||||||
- name: nameFormat
|
|
||||||
type: string
|
|
||||||
default: "{0}"
|
|
||||||
|
|
||||||
# An optional format string used to generate the test name.
|
|
||||||
# - {0} is the name of an item in the targets list.
|
|
||||||
- name: testFormat
|
|
||||||
type: string
|
|
||||||
default: "{0}"
|
|
||||||
|
|
||||||
# An optional format string used to add the group to the job name.
|
|
||||||
# {0} is the formatted name of an item in the targets list.
|
|
||||||
# {{1}} is the group -- be sure to include the double "{{" and "}}".
|
|
||||||
- name: nameGroupFormat
|
|
||||||
type: string
|
|
||||||
default: "{0} - {{1}}"
|
|
||||||
|
|
||||||
# An optional format string used to add the group to the test name.
|
|
||||||
# {0} is the formatted test of an item in the targets list.
|
|
||||||
# {{1}} is the group -- be sure to include the double "{{" and "}}".
|
|
||||||
- name: testGroupFormat
|
|
||||||
type: string
|
|
||||||
default: "{0}/{{1}}"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
- template: test.yml
|
|
||||||
parameters:
|
|
||||||
jobs:
|
|
||||||
- ${{ if eq(length(parameters.groups), 0) }}:
|
|
||||||
- ${{ each target in parameters.targets }}:
|
|
||||||
- name: ${{ format(parameters.nameFormat, coalesce(target.name, target.test)) }}
|
|
||||||
test: ${{ format(parameters.testFormat, coalesce(target.test, target.name)) }}
|
|
||||||
- ${{ if not(eq(length(parameters.groups), 0)) }}:
|
|
||||||
- ${{ each group in parameters.groups }}:
|
|
||||||
- ${{ each target in parameters.targets }}:
|
|
||||||
- name: ${{ format(format(parameters.nameGroupFormat, parameters.nameFormat), coalesce(target.name, target.test), group) }}
|
|
||||||
test: ${{ format(format(parameters.testGroupFormat, parameters.testFormat), coalesce(target.test, target.name), group) }}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
---
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# This template uses the provided list of jobs to create test one or more test jobs.
|
|
||||||
# It can be used directly if needed, or through the matrix template.
|
|
||||||
|
|
||||||
parameters:
|
|
||||||
# A required list of dictionaries, one per test job.
|
|
||||||
# Each item in the list must contain a "job" and "name" key.
|
|
||||||
- name: jobs
|
|
||||||
type: object
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
- ${{ each job in parameters.jobs }}:
|
|
||||||
- job: test_${{ replace(replace(replace(job.test, '/', '_'), '.', '_'), '-', '_') }}
|
|
||||||
displayName: ${{ job.name }}
|
|
||||||
container: default
|
|
||||||
workspace:
|
|
||||||
clean: all
|
|
||||||
steps:
|
|
||||||
- checkout: self
|
|
||||||
fetchDepth: $(fetchDepth)
|
|
||||||
path: $(checkoutPath)
|
|
||||||
- bash: .azure-pipelines/scripts/run-tests.sh "$(entryPoint)" "${{ job.test }}" "$(coverageBranches)"
|
|
||||||
displayName: Run Tests
|
|
||||||
- bash: .azure-pipelines/scripts/process-results.sh
|
|
||||||
condition: succeededOrFailed()
|
|
||||||
displayName: Process Results
|
|
||||||
- bash: .azure-pipelines/scripts/aggregate-coverage.sh "$(Agent.TempDirectory)"
|
|
||||||
condition: eq(variables.haveCoverageData, 'true')
|
|
||||||
displayName: Aggregate Coverage Data
|
|
||||||
- task: PublishTestResults@2
|
|
||||||
condition: eq(variables.haveTestResults, 'true')
|
|
||||||
inputs:
|
|
||||||
testResultsFiles: "$(outputPath)/junit/*.xml"
|
|
||||||
displayName: Publish Test Results
|
|
||||||
- task: PublishPipelineArtifact@1
|
|
||||||
condition: eq(variables.haveBotResults, 'true')
|
|
||||||
displayName: Publish Bot Results
|
|
||||||
inputs:
|
|
||||||
targetPath: "$(outputPath)/bot/"
|
|
||||||
artifactName: "Bot $(System.JobAttempt) $(System.StageDisplayName) $(System.JobDisplayName)"
|
|
||||||
- task: PublishPipelineArtifact@1
|
|
||||||
condition: eq(variables.haveCoverageData, 'true')
|
|
||||||
displayName: Publish Coverage Data
|
|
||||||
inputs:
|
|
||||||
targetPath: "$(Agent.TempDirectory)/coverage/"
|
|
||||||
artifactName: "Coverage $(System.JobAttempt) $(System.StageDisplayName) $(System.JobDisplayName)"
|
|
||||||
5
.github/BOTMETA.yml
vendored
5
.github/BOTMETA.yml
vendored
@@ -1395,6 +1395,8 @@ files:
|
|||||||
ignore: matze
|
ignore: matze
|
||||||
labels: zypper
|
labels: zypper
|
||||||
maintainers: $team_suse
|
maintainers: $team_suse
|
||||||
|
$plugin_utils/unsafe.py:
|
||||||
|
maintainers: felixfontein
|
||||||
$tests/a_module.py:
|
$tests/a_module.py:
|
||||||
maintainers: felixfontein
|
maintainers: felixfontein
|
||||||
#########################
|
#########################
|
||||||
@@ -1414,7 +1416,6 @@ macros:
|
|||||||
becomes: plugins/become
|
becomes: plugins/become
|
||||||
caches: plugins/cache
|
caches: plugins/cache
|
||||||
callbacks: plugins/callback
|
callbacks: plugins/callback
|
||||||
cliconfs: plugins/cliconf
|
|
||||||
connections: plugins/connection
|
connections: plugins/connection
|
||||||
doc_fragments: plugins/doc_fragments
|
doc_fragments: plugins/doc_fragments
|
||||||
filters: plugins/filter
|
filters: plugins/filter
|
||||||
@@ -1422,7 +1423,7 @@ macros:
|
|||||||
lookups: plugins/lookup
|
lookups: plugins/lookup
|
||||||
module_utils: plugins/module_utils
|
module_utils: plugins/module_utils
|
||||||
modules: plugins/modules
|
modules: plugins/modules
|
||||||
terminals: plugins/terminal
|
plugin_utils: plugins/plugin_utils
|
||||||
tests: plugins/test
|
tests: plugins/test
|
||||||
team_ansible_core:
|
team_ansible_core:
|
||||||
team_aix: MorrisA bcoca d-little flynn1973 gforster kairoaraujo marvin-sinister mator molekuul ramooncamacho wtcross
|
team_aix: MorrisA bcoca d-little flynn1973 gforster kairoaraujo marvin-sinister mator molekuul ramooncamacho wtcross
|
||||||
|
|||||||
287
.github/workflows/ansible-test.yml
vendored
287
.github/workflows/ansible-test.yml
vendored
@@ -1,287 +0,0 @@
|
|||||||
---
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# For the comprehensive list of the inputs supported by the ansible-community/ansible-test-gh-action GitHub Action, see
|
|
||||||
# https://github.com/marketplace/actions/ansible-test
|
|
||||||
|
|
||||||
name: EOL CI
|
|
||||||
on:
|
|
||||||
# Run EOL CI against all pushes (direct commits, also merged PRs), Pull Requests
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- stable-*
|
|
||||||
pull_request:
|
|
||||||
# Run EOL CI once per day (at 10:00 UTC)
|
|
||||||
schedule:
|
|
||||||
- cron: '0 10 * * *'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
# Make sure there is at most one active run per PR, but do not cancel any non-PR runs
|
|
||||||
group: ${{ github.workflow }}-${{ (github.head_ref && github.event.number) || github.run_id }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
sanity:
|
|
||||||
name: EOL Sanity (Ⓐ${{ matrix.ansible }})
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
ansible:
|
|
||||||
- '2.11'
|
|
||||||
- '2.12'
|
|
||||||
- '2.13'
|
|
||||||
# Ansible-test on various stable branches does not yet work well with cgroups v2.
|
|
||||||
# Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04
|
|
||||||
# image for these stable branches. The list of branches where this is necessary will
|
|
||||||
# shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28
|
|
||||||
# for the latest list.
|
|
||||||
runs-on: >-
|
|
||||||
${{ contains(fromJson(
|
|
||||||
'["2.9", "2.10", "2.11"]'
|
|
||||||
), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }}
|
|
||||||
steps:
|
|
||||||
- name: Perform sanity testing
|
|
||||||
uses: felixfontein/ansible-test-gh-action@main
|
|
||||||
with:
|
|
||||||
ansible-core-github-repository-slug: ${{ contains(fromJson('["2.10", "2.11"]'), matrix.ansible) && 'felixfontein/ansible' || 'ansible/ansible' }}
|
|
||||||
ansible-core-version: stable-${{ matrix.ansible }}
|
|
||||||
coverage: ${{ github.event_name == 'schedule' && 'always' || 'never' }}
|
|
||||||
pull-request-change-detection: 'true'
|
|
||||||
testing-type: sanity
|
|
||||||
|
|
||||||
units:
|
|
||||||
# Ansible-test on various stable branches does not yet work well with cgroups v2.
|
|
||||||
# Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04
|
|
||||||
# image for these stable branches. The list of branches where this is necessary will
|
|
||||||
# shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28
|
|
||||||
# for the latest list.
|
|
||||||
runs-on: >-
|
|
||||||
${{ contains(fromJson(
|
|
||||||
'["2.9", "2.10", "2.11"]'
|
|
||||||
), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }}
|
|
||||||
name: EOL Units (Ⓐ${{ matrix.ansible }}+py${{ matrix.python }})
|
|
||||||
strategy:
|
|
||||||
# As soon as the first unit test fails, cancel the others to free up the CI queue
|
|
||||||
fail-fast: true
|
|
||||||
matrix:
|
|
||||||
ansible:
|
|
||||||
- ''
|
|
||||||
python:
|
|
||||||
- ''
|
|
||||||
exclude:
|
|
||||||
- ansible: ''
|
|
||||||
include:
|
|
||||||
- ansible: '2.11'
|
|
||||||
python: '2.7'
|
|
||||||
- ansible: '2.11'
|
|
||||||
python: '3.5'
|
|
||||||
- ansible: '2.12'
|
|
||||||
python: '2.6'
|
|
||||||
- ansible: '2.12'
|
|
||||||
python: '3.8'
|
|
||||||
- ansible: '2.13'
|
|
||||||
python: '2.7'
|
|
||||||
- ansible: '2.13'
|
|
||||||
python: '3.8'
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: >-
|
|
||||||
Perform unit testing against
|
|
||||||
Ansible version ${{ matrix.ansible }}
|
|
||||||
uses: felixfontein/ansible-test-gh-action@main
|
|
||||||
with:
|
|
||||||
ansible-core-github-repository-slug: ${{ contains(fromJson('["2.10", "2.11"]'), matrix.ansible) && 'felixfontein/ansible' || 'ansible/ansible' }}
|
|
||||||
ansible-core-version: stable-${{ matrix.ansible }}
|
|
||||||
coverage: ${{ github.event_name == 'schedule' && 'always' || 'never' }}
|
|
||||||
pre-test-cmd: >-
|
|
||||||
mkdir -p ../../ansible
|
|
||||||
;
|
|
||||||
git clone --depth=1 --single-branch https://github.com/ansible-collections/community.internal_test_tools.git ../../community/internal_test_tools
|
|
||||||
pull-request-change-detection: 'true'
|
|
||||||
target-python-version: ${{ matrix.python }}
|
|
||||||
testing-type: units
|
|
||||||
|
|
||||||
integration:
|
|
||||||
# Ansible-test on various stable branches does not yet work well with cgroups v2.
|
|
||||||
# Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04
|
|
||||||
# image for these stable branches. The list of branches where this is necessary will
|
|
||||||
# shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28
|
|
||||||
# for the latest list.
|
|
||||||
runs-on: >-
|
|
||||||
${{ contains(fromJson(
|
|
||||||
'["2.9", "2.10", "2.11"]'
|
|
||||||
), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }}
|
|
||||||
name: EOL I (Ⓐ${{ matrix.ansible }}+${{ matrix.docker }}+py${{ matrix.python }}:${{ matrix.target }})
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
ansible:
|
|
||||||
- ''
|
|
||||||
docker:
|
|
||||||
- ''
|
|
||||||
python:
|
|
||||||
- ''
|
|
||||||
target:
|
|
||||||
- ''
|
|
||||||
exclude:
|
|
||||||
- ansible: ''
|
|
||||||
include:
|
|
||||||
# 2.11
|
|
||||||
- ansible: '2.11'
|
|
||||||
docker: fedora32
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/1/
|
|
||||||
- ansible: '2.11'
|
|
||||||
docker: fedora32
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/2/
|
|
||||||
- ansible: '2.11'
|
|
||||||
docker: fedora32
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/3/
|
|
||||||
- ansible: '2.11'
|
|
||||||
docker: fedora33
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/1/
|
|
||||||
- ansible: '2.11'
|
|
||||||
docker: fedora33
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/2/
|
|
||||||
- ansible: '2.11'
|
|
||||||
docker: fedora33
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/3/
|
|
||||||
- ansible: '2.11'
|
|
||||||
docker: alpine3
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/1/
|
|
||||||
- ansible: '2.11'
|
|
||||||
docker: alpine3
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/2/
|
|
||||||
- ansible: '2.11'
|
|
||||||
docker: alpine3
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/3/
|
|
||||||
# Right now all generic tests are disabled. Uncomment when at least one of them is re-enabled.
|
|
||||||
# - ansible: '2.11'
|
|
||||||
# docker: default
|
|
||||||
# python: '2.7'
|
|
||||||
# target: azp/generic/1/
|
|
||||||
# - ansible: '2.11'
|
|
||||||
# docker: default
|
|
||||||
# python: '3.5'
|
|
||||||
# target: azp/generic/1/
|
|
||||||
# 2.12
|
|
||||||
- ansible: '2.12'
|
|
||||||
docker: centos6
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/1/
|
|
||||||
- ansible: '2.12'
|
|
||||||
docker: centos6
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/2/
|
|
||||||
- ansible: '2.12'
|
|
||||||
docker: centos6
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/3/
|
|
||||||
- ansible: '2.12'
|
|
||||||
docker: fedora34
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/1/
|
|
||||||
- ansible: '2.12'
|
|
||||||
docker: fedora34
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/2/
|
|
||||||
- ansible: '2.12'
|
|
||||||
docker: fedora34
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/3/
|
|
||||||
- ansible: '2.12'
|
|
||||||
docker: ubuntu1804
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/1/
|
|
||||||
- ansible: '2.12'
|
|
||||||
docker: ubuntu1804
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/2/
|
|
||||||
- ansible: '2.12'
|
|
||||||
docker: ubuntu1804
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/3/
|
|
||||||
# Right now all generic tests are disabled. Uncomment when at least one of them is re-enabled.
|
|
||||||
# - ansible: '2.12'
|
|
||||||
# docker: default
|
|
||||||
# python: '3.8'
|
|
||||||
# target: azp/generic/1/
|
|
||||||
# 2.13
|
|
||||||
- ansible: '2.13'
|
|
||||||
docker: fedora35
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/1/
|
|
||||||
- ansible: '2.13'
|
|
||||||
docker: fedora35
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/2/
|
|
||||||
- ansible: '2.13'
|
|
||||||
docker: fedora35
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/3/
|
|
||||||
- ansible: '2.13'
|
|
||||||
docker: opensuse15py2
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/1/
|
|
||||||
- ansible: '2.13'
|
|
||||||
docker: opensuse15py2
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/2/
|
|
||||||
- ansible: '2.13'
|
|
||||||
docker: opensuse15py2
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/3/
|
|
||||||
- ansible: '2.13'
|
|
||||||
docker: alpine3
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/1/
|
|
||||||
- ansible: '2.13'
|
|
||||||
docker: alpine3
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/2/
|
|
||||||
- ansible: '2.13'
|
|
||||||
docker: alpine3
|
|
||||||
python: ''
|
|
||||||
target: azp/posix/3/
|
|
||||||
# Right now all generic tests are disabled. Uncomment when at least one of them is re-enabled.
|
|
||||||
# - ansible: '2.13'
|
|
||||||
# docker: default
|
|
||||||
# python: '3.9'
|
|
||||||
# target: azp/generic/1/
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: >-
|
|
||||||
Perform integration testing against
|
|
||||||
Ansible version ${{ matrix.ansible }}
|
|
||||||
under Python ${{ matrix.python }}
|
|
||||||
uses: felixfontein/ansible-test-gh-action@main
|
|
||||||
with:
|
|
||||||
ansible-core-github-repository-slug: ${{ contains(fromJson('["2.10", "2.11"]'), matrix.ansible) && 'felixfontein/ansible' || 'ansible/ansible' }}
|
|
||||||
ansible-core-version: stable-${{ matrix.ansible }}
|
|
||||||
coverage: ${{ github.event_name == 'schedule' && 'always' || 'never' }}
|
|
||||||
docker-image: ${{ matrix.docker }}
|
|
||||||
integration-continue-on-error: 'false'
|
|
||||||
integration-diff: 'false'
|
|
||||||
integration-retry-on-error: 'true'
|
|
||||||
pre-test-cmd: >-
|
|
||||||
mkdir -p ../../ansible
|
|
||||||
;
|
|
||||||
git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.posix.git ../../ansible/posix
|
|
||||||
;
|
|
||||||
git clone --depth=1 --single-branch https://github.com/ansible-collections/community.crypto.git ../../community/crypto
|
|
||||||
;
|
|
||||||
git clone --depth=1 --single-branch https://github.com/ansible-collections/community.internal_test_tools.git ../../community/internal_test_tools
|
|
||||||
pull-request-change-detection: 'true'
|
|
||||||
target: ${{ matrix.target }}
|
|
||||||
target-python-version: ${{ matrix.python }}
|
|
||||||
testing-type: integration
|
|
||||||
36
.github/workflows/codeql-analysis.yml
vendored
36
.github/workflows/codeql-analysis.yml
vendored
@@ -1,36 +0,0 @@
|
|||||||
---
|
|
||||||
# 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
|
|
||||||
|
|
||||||
name: "Code scanning - action"
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '26 19 * * 1'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
CodeQL-Build:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
actions: read # for github/codeql-action/init to get workflow details
|
|
||||||
contents: read # for actions/checkout to fetch code
|
|
||||||
security-events: write # for github/codeql-action/autobuild to send a status report
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
uses: github/codeql-action/init@v3
|
|
||||||
with:
|
|
||||||
languages: python
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
|
||||||
uses: github/codeql-action/analyze@v3
|
|
||||||
20
.github/workflows/import-galaxy.yml
vendored
20
.github/workflows/import-galaxy.yml
vendored
@@ -1,20 +0,0 @@
|
|||||||
---
|
|
||||||
# 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
|
|
||||||
|
|
||||||
name: import-galaxy
|
|
||||||
'on':
|
|
||||||
# Run CI against all pushes (direct commits, also merged PRs) to main, and all Pull Requests
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- stable-*
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
import-galaxy:
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
name: Test to import built collection artifact with Galaxy importer
|
|
||||||
uses: ansible-community/github-action-test-galaxy-import/.github/workflows/test-galaxy-import.yml@main
|
|
||||||
30
.github/workflows/reuse.yml
vendored
30
.github/workflows/reuse.yml
vendored
@@ -1,30 +0,0 @@
|
|||||||
---
|
|
||||||
# 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
|
|
||||||
|
|
||||||
name: Verify REUSE
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
pull_request_target:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
branches: [main]
|
|
||||||
# Run CI once per day (at 07:30 UTC)
|
|
||||||
schedule:
|
|
||||||
- cron: '30 7 * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check:
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
ref: ${{ github.event.pull_request.head.sha || '' }}
|
|
||||||
|
|
||||||
- name: REUSE Compliance Check
|
|
||||||
uses: fsfe/reuse-action@v2
|
|
||||||
1012
CHANGELOG.md
Normal file
1012
CHANGELOG.md
Normal file
File diff suppressed because it is too large
Load Diff
3
CHANGELOG.md.license
Normal file
3
CHANGELOG.md.license
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
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
|
||||||
|
SPDX-FileCopyrightText: Ansible Project
|
||||||
186
CHANGELOG.rst
186
CHANGELOG.rst
@@ -6,6 +6,126 @@ Community General Release Notes
|
|||||||
|
|
||||||
This changelog describes changes after version 6.0.0.
|
This changelog describes changes after version 6.0.0.
|
||||||
|
|
||||||
|
v7.5.9
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Maintenance release.
|
||||||
|
|
||||||
|
This is the last 7.x.y release. The 7.x.y release train is now effectively End of Life.
|
||||||
|
|
||||||
|
Thanks to everyone who contributed to the community.general 7.x.y releases!
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- ini_file - pass absolute paths to ``module.atomic_move()`` (https://github.com/ansible/ansible/issues/83950, https://github.com/ansible-collections/community.general/pull/8925).
|
||||||
|
- ipa_hostgroup - fix ``enabled `` and ``disabled`` states (https://github.com/ansible-collections/community.general/issues/8408, https://github.com/ansible-collections/community.general/pull/8900).
|
||||||
|
- java_keystore - pass absolute paths to ``module.atomic_move()`` (https://github.com/ansible/ansible/issues/83950, https://github.com/ansible-collections/community.general/pull/8925).
|
||||||
|
- jenkins_plugin - pass absolute paths to ``module.atomic_move()`` (https://github.com/ansible/ansible/issues/83950, https://github.com/ansible-collections/community.general/pull/8925).
|
||||||
|
- kdeconfig - pass absolute paths to ``module.atomic_move()`` (https://github.com/ansible/ansible/issues/83950, https://github.com/ansible-collections/community.general/pull/8925).
|
||||||
|
- modprobe - fix check mode not being honored for ``persistent`` option (https://github.com/ansible-collections/community.general/issues/9051, https://github.com/ansible-collections/community.general/pull/9052).
|
||||||
|
- pam_limits - pass absolute paths to ``module.atomic_move()`` (https://github.com/ansible/ansible/issues/83950, https://github.com/ansible-collections/community.general/pull/8925).
|
||||||
|
|
||||||
|
v7.5.8
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Regular bugfix release.
|
||||||
|
|
||||||
|
Note that this is the last regular bugfix release. From now on, the 7.x.y release train
|
||||||
|
will only receive major and security bugfixes.
|
||||||
|
|
||||||
|
Minor Changes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- gitlab_deploy_key, gitlab_group_members, gitlab_group_variable, gitlab_hook, gitlab_instance_variable, gitlab_project_badge, gitlab_project_variable, gitlab_user - improve API pagination and compatibility with different versions of ``python-gitlab`` (https://github.com/ansible-collections/community.general/pull/7790).
|
||||||
|
|
||||||
|
Security Fixes
|
||||||
|
--------------
|
||||||
|
|
||||||
|
- keycloak_identity_provider - the client secret was not correctly sanitized by the module. The return values ``proposed``, ``existing``, and ``end_state``, as well as the diff, did contain the client secret unmasked (https://github.com/ansible-collections/community.general/pull/8355).
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- gitlab_runner - fix pagination when checking for existing runners (https://github.com/ansible-collections/community.general/pull/7790).
|
||||||
|
- keycloak_user_federation - fix diff of empty ``krbPrincipalAttribute`` (https://github.com/ansible-collections/community.general/pull/8320).
|
||||||
|
- opentelemetry callback plugin - close spans always (https://github.com/ansible-collections/community.general/pull/8367).
|
||||||
|
- opentelemetry callback plugin - honour the ``disable_logs`` option to avoid storing task results since they are not used regardless (https://github.com/ansible-collections/community.general/pull/8373).
|
||||||
|
|
||||||
|
v7.5.7
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Regular bugfix release.
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- aix_filesystem - fix ``_validate_vg`` not passing VG name to ``lsvg_cmd`` (https://github.com/ansible-collections/community.general/issues/8151).
|
||||||
|
- apt_rpm - when checking whether packages were installed after running ``apt-get -y install <packages>``, only the last package name was checked (https://github.com/ansible-collections/community.general/pull/8263).
|
||||||
|
- bitwarden_secrets_manager lookup plugin - implements retry with exponential backoff to avoid lookup errors when Bitwardn's API rate limiting is encountered (https://github.com/ansible-collections/community.general/issues/8230, https://github.com/ansible-collections/community.general/pull/8238).
|
||||||
|
- haproxy - fix an issue where HAProxy could get stuck in DRAIN mode when the backend was unreachable (https://github.com/ansible-collections/community.general/issues/8092).
|
||||||
|
- inventory plugins - add unsafe wrapper to avoid marking strings that do not contain ``{`` or ``}`` as unsafe, to work around a bug in AWX ((https://github.com/ansible-collections/community.general/issues/8212, https://github.com/ansible-collections/community.general/pull/8225).
|
||||||
|
- ipa - fix get version regex in IPA module_utils (https://github.com/ansible-collections/community.general/pull/8175).
|
||||||
|
- keycloak_client - add sorted ``defaultClientScopes`` and ``optionalClientScopes`` to normalizations (https://github.com/ansible-collections/community.general/pull/8223).
|
||||||
|
- keycloak_realm - add normalizations for ``enabledEventTypes`` and ``supportedLocales`` (https://github.com/ansible-collections/community.general/pull/8224).
|
||||||
|
- puppet - add option ``environment_lang`` to set the environment language encoding. Defaults to lang ``C``. It is recommended to set it to ``C.UTF-8`` or ``en_US.UTF-8`` depending on what is available on your system. (https://github.com/ansible-collections/community.general/issues/8000)
|
||||||
|
- riak - support ``riak admin`` sub-command in newer Riak KV versions beside the legacy ``riak-admin`` main command (https://github.com/ansible-collections/community.general/pull/8211).
|
||||||
|
- xml - make module work with lxml 5.1.1, which removed some internals that the module was relying on (https://github.com/ansible-collections/community.general/pull/8169).
|
||||||
|
|
||||||
|
v7.5.6
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Regular bugfix release with security fixes.
|
||||||
|
|
||||||
|
Security Fixes
|
||||||
|
--------------
|
||||||
|
|
||||||
|
- cobbler, gitlab_runners, icinga2, linode, lxd, nmap, online, opennebula, proxmox, scaleway, stackpath_compute, virtualbox, and xen_orchestra inventory plugin - make sure all data received from the remote servers is marked as unsafe, so remote code execution by obtaining texts that can be evaluated as templates is not possible (https://www.die-welt.net/2024/03/remote-code-execution-in-ansible-dynamic-inventory-plugins/, https://github.com/ansible-collections/community.general/pull/8098).
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- aix_filesystem - fix issue with empty list items in crfs logic and option order (https://github.com/ansible-collections/community.general/pull/8052).
|
||||||
|
- homebrew - error returned from brew command was ignored and tried to parse empty JSON. Fix now checks for an error and raises it to give accurate error message to users (https://github.com/ansible-collections/community.general/issues/8047).
|
||||||
|
- ipa_hbacrule - the module uses a string for ``ipaenabledflag`` for new FreeIPA versions while the returned value is a boolean (https://github.com/ansible-collections/community.general/pull/7880).
|
||||||
|
- ipa_sudorule - the module uses a string for ``ipaenabledflag`` for new FreeIPA versions while the returned value is a boolean (https://github.com/ansible-collections/community.general/pull/7880).
|
||||||
|
- iptables_state - fix idempotency issues when restoring incomplete iptables dumps (https://github.com/ansible-collections/community.general/issues/8029).
|
||||||
|
- linode inventory plugin - add descriptive error message for linode inventory plugin (https://github.com/ansible-collections/community.general/pull/8133).
|
||||||
|
- pacemaker_cluster - actually implement check mode, which the module claims to support. This means that until now the module also did changes in check mode (https://github.com/ansible-collections/community.general/pull/8081).
|
||||||
|
- pam_limits - when the file does not exist, do not create it in check mode (https://github.com/ansible-collections/community.general/issues/8050, https://github.com/ansible-collections/community.general/pull/8057).
|
||||||
|
- proxmox_kvm - fixed status check getting from node-specific API endpoint (https://github.com/ansible-collections/community.general/issues/7817).
|
||||||
|
|
||||||
|
v7.5.5
|
||||||
|
======
|
||||||
|
|
||||||
|
Release Summary
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Regular bugfix release.
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
--------
|
||||||
|
|
||||||
|
- cargo - fix idempotency issues when using a custom installation path for packages (using the ``--path`` parameter). The initial installation runs fine, but subsequent runs use the ``get_installed()`` function which did not check the given installation location, before running ``cargo install``. This resulted in a false ``changed`` state. Also the removal of packeges using ``state: absent`` failed, as the installation check did not use the given parameter (https://github.com/ansible-collections/community.general/pull/7970).
|
||||||
|
- keycloak_client - fixes issue when metadata is provided in desired state when task is in check mode (https://github.com/ansible-collections/community.general/issues/1226, https://github.com/ansible-collections/community.general/pull/7881).
|
||||||
|
- modprobe - listing modules files or modprobe files could trigger a FileNotFoundError if ``/etc/modprobe.d`` or ``/etc/modules-load.d`` did not exist. Relevant functions now return empty lists if the directories do not exist to avoid crashing the module (https://github.com/ansible-collections/community.general/issues/7717).
|
||||||
|
- onepassword lookup plugin - failed for fields that were in sections and had uppercase letters in the label/ID. Field lookups are now case insensitive in all cases (https://github.com/ansible-collections/community.general/pull/7919).
|
||||||
|
- pkgin - pkgin (pkgsrc package manager used by SmartOS) raises erratic exceptions and spurious ``changed=true`` (https://github.com/ansible-collections/community.general/pull/7971).
|
||||||
|
- redfish_info - allow for a GET operation invoked by ``GetUpdateStatus`` to allow for an empty response body for cases where a service returns 204 No Content (https://github.com/ansible-collections/community.general/issues/8003).
|
||||||
|
- redfish_info - correct uncaught exception when attempting to retrieve ``Chassis`` information (https://github.com/ansible-collections/community.general/pull/7952).
|
||||||
|
|
||||||
v7.5.4
|
v7.5.4
|
||||||
======
|
======
|
||||||
|
|
||||||
@@ -109,7 +229,6 @@ Regular bugfix and feature release.
|
|||||||
Please note that this is the last minor 7.x.0 release. Further releases
|
Please note that this is the last minor 7.x.0 release. Further releases
|
||||||
with major version 7 will be bugfix releases 7.5.y.
|
with major version 7 will be bugfix releases 7.5.y.
|
||||||
|
|
||||||
|
|
||||||
Minor Changes
|
Minor Changes
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
@@ -155,11 +274,11 @@ Bugfixes
|
|||||||
New Modules
|
New Modules
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
- consul_role - Manipulate Consul roles
|
- community.general.consul_role - Manipulate Consul roles
|
||||||
- gio_mime - Set default handler for MIME type, for applications using Gnome GIO
|
- community.general.gio_mime - Set default handler for MIME type, for applications using Gnome GIO
|
||||||
- keycloak_authz_custom_policy - Allows administration of Keycloak client custom Javascript policies via Keycloak API
|
- community.general.keycloak_authz_custom_policy - Allows administration of Keycloak client custom Javascript policies via Keycloak API
|
||||||
- keycloak_realm_key - Allows administration of Keycloak realm keys via Keycloak API
|
- community.general.keycloak_realm_key - Allows administration of Keycloak realm keys via Keycloak API
|
||||||
- simpleinit_msb - Manage services on Source Mage GNU/Linux
|
- community.general.simpleinit_msb - Manage services on Source Mage GNU/Linux
|
||||||
|
|
||||||
v7.4.0
|
v7.4.0
|
||||||
======
|
======
|
||||||
@@ -199,8 +318,8 @@ Bugfixes
|
|||||||
New Modules
|
New Modules
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
- jenkins_build_info - Get information about Jenkins builds
|
- community.general.jenkins_build_info - Get information about Jenkins builds
|
||||||
- pnpm - Manage node.js packages with pnpm
|
- community.general.pnpm - Manage node.js packages with pnpm
|
||||||
|
|
||||||
v7.3.0
|
v7.3.0
|
||||||
======
|
======
|
||||||
@@ -349,15 +468,15 @@ New Plugins
|
|||||||
Lookup
|
Lookup
|
||||||
~~~~~~
|
~~~~~~
|
||||||
|
|
||||||
- bitwarden_secrets_manager - Retrieve secrets from Bitwarden Secrets Manager
|
- community.general.bitwarden_secrets_manager - Retrieve secrets from Bitwarden Secrets Manager
|
||||||
|
|
||||||
New Modules
|
New Modules
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
- consul_policy - Manipulate Consul policies
|
- community.general.consul_policy - Manipulate Consul policies
|
||||||
- keycloak_authz_permission - Allows administration of Keycloak client authorization permissions via Keycloak API
|
- community.general.keycloak_authz_permission - Allows administration of Keycloak client authorization permissions via Keycloak API
|
||||||
- keycloak_authz_permission_info - Query Keycloak client authorization permissions information
|
- community.general.keycloak_authz_permission_info - Query Keycloak client authorization permissions information
|
||||||
- proxmox_vm_info - Retrieve information about one or more Proxmox VE virtual machines
|
- community.general.proxmox_vm_info - Retrieve information about one or more Proxmox VE virtual machines
|
||||||
|
|
||||||
v7.1.0
|
v7.1.0
|
||||||
======
|
======
|
||||||
@@ -376,7 +495,6 @@ ansible-core 2.15 or later to see it as it is intended. Alternatively you can
|
|||||||
look at `the devel docsite <https://docs.ansible.com/ansible/devel/collections/community/general/>`__
|
look at `the devel docsite <https://docs.ansible.com/ansible/devel/collections/community/general/>`__
|
||||||
for the rendered HTML version of the documentation of the latest release.
|
for the rendered HTML version of the documentation of the latest release.
|
||||||
|
|
||||||
|
|
||||||
Minor Changes
|
Minor Changes
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
@@ -472,13 +590,13 @@ Known Issues
|
|||||||
New Modules
|
New Modules
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
- gitlab_instance_variable - Creates, updates, or deletes GitLab instance variables
|
- community.general.gitlab_instance_variable - Creates, updates, or deletes GitLab instance variables
|
||||||
- gitlab_merge_request - Create, update, or delete GitLab merge requests
|
- community.general.gitlab_merge_request - Create, update, or delete GitLab merge requests
|
||||||
- keycloak_authentication_required_actions - Allows administration of Keycloak authentication required actions
|
- community.general.keycloak_authentication_required_actions - Allows administration of Keycloak authentication required actions
|
||||||
- keycloak_user - Create and configure a user in Keycloak
|
- community.general.keycloak_user - Create and configure a user in Keycloak
|
||||||
- lvg_rename - Renames LVM volume groups
|
- community.general.lvg_rename - Renames LVM volume groups
|
||||||
- proxmox_pool - Pool management for Proxmox VE cluster
|
- community.general.proxmox_pool - Pool management for Proxmox VE cluster
|
||||||
- proxmox_pool_member - Add or delete members from Proxmox VE cluster pools
|
- community.general.proxmox_pool_member - Add or delete members from Proxmox VE cluster pools
|
||||||
|
|
||||||
v7.0.1
|
v7.0.1
|
||||||
======
|
======
|
||||||
@@ -800,20 +918,20 @@ New Plugins
|
|||||||
Lookup
|
Lookup
|
||||||
~~~~~~
|
~~~~~~
|
||||||
|
|
||||||
- merge_variables - merge variables with a certain suffix
|
- community.general.merge_variables - merge variables with a certain suffix
|
||||||
|
|
||||||
New Modules
|
New Modules
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
- btrfs_info - Query btrfs filesystem info
|
- community.general.btrfs_info - Query btrfs filesystem info
|
||||||
- btrfs_subvolume - Manage btrfs subvolumes
|
- community.general.btrfs_subvolume - Manage btrfs subvolumes
|
||||||
- gitlab_project_badge - Manage project badges on GitLab Server
|
- community.general.gitlab_project_badge - Manage project badges on GitLab Server
|
||||||
- ilo_redfish_command - Manages Out-Of-Band controllers using Redfish APIs
|
- community.general.ilo_redfish_command - Manages Out-Of-Band controllers using Redfish APIs
|
||||||
- ipbase_info - Retrieve IP geolocation and other facts of a host's IP address using the ipbase.com API
|
- community.general.ipbase_info - Retrieve IP geolocation and other facts of a host's IP address using the ipbase.com API
|
||||||
- kdeconfig - Manage KDE configuration files
|
- community.general.kdeconfig - Manage KDE configuration files
|
||||||
- keycloak_authz_authorization_scope - Allows administration of Keycloak client authorization scopes via Keycloak API
|
- community.general.keycloak_authz_authorization_scope - Allows administration of Keycloak client authorization scopes via Keycloak API
|
||||||
- keycloak_clientscope_type - Set the type of aclientscope in realm or client via Keycloak API
|
- community.general.keycloak_clientscope_type - Set the type of aclientscope in realm or client via Keycloak API
|
||||||
- keycloak_clientsecret_info - Retrieve client secret via Keycloak API
|
- community.general.keycloak_clientsecret_info - Retrieve client secret via Keycloak API
|
||||||
- keycloak_clientsecret_regenerate - Regenerate Keycloak client secret via Keycloak API
|
- community.general.keycloak_clientsecret_regenerate - Regenerate Keycloak client secret via Keycloak API
|
||||||
- ocapi_command - Manages Out-Of-Band controllers using Open Composable API (OCAPI)
|
- community.general.ocapi_command - Manages Out-Of-Band controllers using Open Composable API (OCAPI)
|
||||||
- ocapi_info - Manages Out-Of-Band controllers using Open Composable API (OCAPI)
|
- community.general.ocapi_info - Manages Out-Of-Band controllers using Open Composable API (OCAPI)
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ Also, consider taking up a valuable, reviewed, but abandoned pull request which
|
|||||||
* Try committing your changes with an informative but short commit message.
|
* Try committing your changes with an informative but short commit message.
|
||||||
* Do not squash your commits and force-push to your branch if not needed. Reviews of your pull request are much easier with individual commits to comprehend the pull request history. All commits of your pull request branch will be squashed into one commit by GitHub upon merge.
|
* Do not squash your commits and force-push to your branch if not needed. Reviews of your pull request are much easier with individual commits to comprehend the pull request history. All commits of your pull request branch will be squashed into one commit by GitHub upon merge.
|
||||||
* Do not add merge commits to your PR. The bot will complain and you will have to rebase ([instructions for rebasing](https://docs.ansible.com/ansible/latest/dev_guide/developing_rebasing.html)) to remove them before your PR can be merged. To avoid that git automatically does merges during pulls, you can configure it to do rebases instead by running `git config pull.rebase true` inside the repository checkout.
|
* Do not add merge commits to your PR. The bot will complain and you will have to rebase ([instructions for rebasing](https://docs.ansible.com/ansible/latest/dev_guide/developing_rebasing.html)) to remove them before your PR can be merged. To avoid that git automatically does merges during pulls, you can configure it to do rebases instead by running `git config pull.rebase true` inside the repository checkout.
|
||||||
* Make sure your PR includes a [changelog fragment](https://docs.ansible.com/ansible/devel/community/development_process.html#creating-changelog-fragments). (You must not include a fragment for new modules or new plugins. Also you shouldn't include one for docs-only changes. If you're not sure, simply don't include one, we'll tell you whether one is needed or not :) )
|
* Make sure your PR includes a [changelog fragment](https://docs.ansible.com/ansible/devel/community/collection_development_process.html#creating-a-changelog-fragment).
|
||||||
|
* You must not include a fragment for new modules or new plugins. Also you shouldn't include one for docs-only changes. (If you're not sure, simply don't include one, we'll tell you whether one is needed or not :) )
|
||||||
|
* Please always include a link to the pull request itself, and if the PR is about an issue, also a link to the issue. Also make sure the fragment ends with a period, and begins with a lower-case letter after `-`. (Again, if you don't do this, we'll add suggestions to fix it, so don't worry too much :) )
|
||||||
* Avoid reformatting unrelated parts of the codebase in your PR. These types of changes will likely be requested for reversion, create additional work for reviewers, and may cause approval to be delayed.
|
* Avoid reformatting unrelated parts of the codebase in your PR. These types of changes will likely be requested for reversion, create additional work for reviewers, and may cause approval to be delayed.
|
||||||
|
|
||||||
You can also read [our Quick-start development guide](https://github.com/ansible/community-docs/blob/main/create_pr_quick_start_guide.rst).
|
You can also read [our Quick-start development guide](https://github.com/ansible/community-docs/blob/main/create_pr_quick_start_guide.rst).
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
[](https://dev.azure.com/ansible/community.general/_build?definitionId=31)
|
[](https://dev.azure.com/ansible/community.general/_build?definitionId=31)
|
||||||
[](https://github.com/ansible-collections/community.general/actions)
|
[](https://github.com/ansible-collections/community.general/actions)
|
||||||
[](https://codecov.io/gh/ansible-collections/community.general)
|
[](https://codecov.io/gh/ansible-collections/community.general)
|
||||||
|
[](https://api.reuse.software/info/github.com/ansible-collections/community.general)
|
||||||
|
|
||||||
This repository contains the `community.general` Ansible Collection. The collection is a part of the Ansible package and includes many modules and plugins supported by Ansible community which are not part of more specialized community collections.
|
This repository contains the `community.general` Ansible Collection. The collection is a part of the Ansible package and includes many modules and plugins supported by Ansible community which are not part of more specialized community collections.
|
||||||
|
|
||||||
@@ -24,7 +25,7 @@ If you encounter abusive behavior violating the [Ansible Code of Conduct](https:
|
|||||||
|
|
||||||
## Tested with Ansible
|
## Tested with Ansible
|
||||||
|
|
||||||
Tested with the current ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, ansible-core 2.14, ansible-core 2.15, ansible-core 2.16 releases and the current development version of ansible-core. Ansible-core versions before 2.11.0 are not supported. This includes all ansible-base 2.10 and Ansible 2.9 releases.
|
Tested with the current ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, ansible-core 2.14, ansible-core 2.15, ansible-core 2.16, and ansible-core 2.17 releases. Ansible-core versions before 2.11.0 are not supported. This includes all ansible-base 2.10 and Ansible 2.9 releases.
|
||||||
|
|
||||||
Parts of this collection will not work with ansible-core 2.11 on Python 3.12+.
|
Parts of this collection will not work with ansible-core 2.11 on Python 3.12+.
|
||||||
|
|
||||||
@@ -117,7 +118,7 @@ See the [Releasing guidelines](https://github.com/ansible/community-docs/blob/ma
|
|||||||
|
|
||||||
## Release notes
|
## Release notes
|
||||||
|
|
||||||
See the [changelog](https://github.com/ansible-collections/community.general/blob/stable-7/CHANGELOG.rst).
|
See the [changelog](https://github.com/ansible-collections/community.general/blob/stable-7/CHANGELOG.md).
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -12,23 +12,31 @@ mention_ancestor: true
|
|||||||
flatmap: true
|
flatmap: true
|
||||||
new_plugins_after_name: removed_features
|
new_plugins_after_name: removed_features
|
||||||
notesdir: fragments
|
notesdir: fragments
|
||||||
|
output_formats:
|
||||||
|
- md
|
||||||
|
- rst
|
||||||
prelude_section_name: release_summary
|
prelude_section_name: release_summary
|
||||||
prelude_section_title: Release Summary
|
prelude_section_title: Release Summary
|
||||||
sections:
|
sections:
|
||||||
- - major_changes
|
- - major_changes
|
||||||
- Major Changes
|
- Major Changes
|
||||||
- - minor_changes
|
- - minor_changes
|
||||||
- Minor Changes
|
- Minor Changes
|
||||||
- - breaking_changes
|
- - breaking_changes
|
||||||
- Breaking Changes / Porting Guide
|
- Breaking Changes / Porting Guide
|
||||||
- - deprecated_features
|
- - deprecated_features
|
||||||
- Deprecated Features
|
- Deprecated Features
|
||||||
- - removed_features
|
- - removed_features
|
||||||
- Removed Features (previously deprecated)
|
- Removed Features (previously deprecated)
|
||||||
- - security_fixes
|
- - security_fixes
|
||||||
- Security Fixes
|
- Security Fixes
|
||||||
- - bugfixes
|
- - bugfixes
|
||||||
- Bugfixes
|
- Bugfixes
|
||||||
- - known_issues
|
- - known_issues
|
||||||
- Known Issues
|
- Known Issues
|
||||||
title: Community General
|
title: Community General
|
||||||
|
trivial_section_name: trivial
|
||||||
|
use_fqcn: true
|
||||||
|
add_plugin_period: true
|
||||||
|
changelog_nice_yaml: true
|
||||||
|
changelog_sort: version
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ communication:
|
|||||||
- topic: General usage and support questions
|
- topic: General usage and support questions
|
||||||
network: Libera
|
network: Libera
|
||||||
channel: '#ansible'
|
channel: '#ansible'
|
||||||
mailing_lists:
|
forums:
|
||||||
- topic: Ansible Project List
|
- topic: Ansible Forum
|
||||||
url: https://groups.google.com/g/ansible-project
|
# The following URL directly points to the "Get Help" section
|
||||||
|
url: https://forum.ansible.com/c/help/6/none
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
namespace: community
|
namespace: community
|
||||||
name: general
|
name: general
|
||||||
version: 7.5.4
|
version: 7.5.9
|
||||||
readme: README.md
|
readme: README.md
|
||||||
authors:
|
authors:
|
||||||
- Ansible (https://github.com/ansible)
|
- Ansible (https://github.com/ansible)
|
||||||
|
|||||||
@@ -350,7 +350,8 @@ class OpenTelemetrySource(object):
|
|||||||
if not disable_logs:
|
if not disable_logs:
|
||||||
# This will avoid populating span attributes to the logs
|
# This will avoid populating span attributes to the logs
|
||||||
span.add_event(task_data.dump, attributes={} if disable_attributes_in_logs else attributes)
|
span.add_event(task_data.dump, attributes={} if disable_attributes_in_logs else attributes)
|
||||||
span.end(end_time=host_data.finish)
|
# Close span always
|
||||||
|
span.end(end_time=host_data.finish)
|
||||||
|
|
||||||
def set_span_attributes(self, span, attributes):
|
def set_span_attributes(self, span, attributes):
|
||||||
""" update the span attributes with the given attributes if not None """
|
""" update the span attributes with the given attributes if not None """
|
||||||
@@ -497,6 +498,12 @@ class CallbackModule(CallbackBase):
|
|||||||
# See https://github.com/open-telemetry/opentelemetry-specification/issues/740
|
# See https://github.com/open-telemetry/opentelemetry-specification/issues/740
|
||||||
self.traceparent = self.get_option('traceparent')
|
self.traceparent = self.get_option('traceparent')
|
||||||
|
|
||||||
|
def dump_results(self, result):
|
||||||
|
""" dump the results if disable_logs is not enabled """
|
||||||
|
if self.disable_logs:
|
||||||
|
return ""
|
||||||
|
return self._dump_results(result._result)
|
||||||
|
|
||||||
def v2_playbook_on_start(self, playbook):
|
def v2_playbook_on_start(self, playbook):
|
||||||
self.ansible_playbook = basename(playbook._file_name)
|
self.ansible_playbook = basename(playbook._file_name)
|
||||||
|
|
||||||
@@ -546,7 +553,7 @@ class CallbackModule(CallbackBase):
|
|||||||
self.tasks_data,
|
self.tasks_data,
|
||||||
status,
|
status,
|
||||||
result,
|
result,
|
||||||
self._dump_results(result._result)
|
self.dump_results(result)
|
||||||
)
|
)
|
||||||
|
|
||||||
def v2_runner_on_ok(self, result):
|
def v2_runner_on_ok(self, result):
|
||||||
@@ -554,7 +561,7 @@ class CallbackModule(CallbackBase):
|
|||||||
self.tasks_data,
|
self.tasks_data,
|
||||||
'ok',
|
'ok',
|
||||||
result,
|
result,
|
||||||
self._dump_results(result._result)
|
self.dump_results(result)
|
||||||
)
|
)
|
||||||
|
|
||||||
def v2_runner_on_skipped(self, result):
|
def v2_runner_on_skipped(self, result):
|
||||||
@@ -562,7 +569,7 @@ class CallbackModule(CallbackBase):
|
|||||||
self.tasks_data,
|
self.tasks_data,
|
||||||
'skipped',
|
'skipped',
|
||||||
result,
|
result,
|
||||||
self._dump_results(result._result)
|
self.dump_results(result)
|
||||||
)
|
)
|
||||||
|
|
||||||
def v2_playbook_on_include(self, included_file):
|
def v2_playbook_on_include(self, included_file):
|
||||||
|
|||||||
@@ -19,6 +19,16 @@ DOCUMENTATION = '''
|
|||||||
- default_callback
|
- default_callback
|
||||||
requirements:
|
requirements:
|
||||||
- set as stdout in configuration
|
- set as stdout in configuration
|
||||||
|
seealso:
|
||||||
|
- plugin: ansible.builtin.default
|
||||||
|
plugin_type: callback
|
||||||
|
description: >
|
||||||
|
There is a parameter O(ansible.builtin.default#callback:result_format) in P(ansible.builtin.default#callback)
|
||||||
|
that allows you to change the output format to YAML.
|
||||||
|
notes:
|
||||||
|
- >
|
||||||
|
With ansible-core 2.13 or newer, you can instead specify V(yaml) for the parameter O(ansible.builtin.default#callback:result_format)
|
||||||
|
in P(ansible.builtin.default#callback).
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|||||||
@@ -118,6 +118,8 @@ from ansible.module_utils.common.text.converters import to_text
|
|||||||
from ansible.plugins.inventory import BaseInventoryPlugin, Cacheable, to_safe_group_name
|
from ansible.plugins.inventory import BaseInventoryPlugin, Cacheable, to_safe_group_name
|
||||||
from ansible.module_utils.six import text_type
|
from ansible.module_utils.six import text_type
|
||||||
|
|
||||||
|
from ansible_collections.community.general.plugins.plugin_utils.unsafe import make_unsafe
|
||||||
|
|
||||||
# xmlrpc
|
# xmlrpc
|
||||||
try:
|
try:
|
||||||
import xmlrpclib as xmlrpc_client
|
import xmlrpclib as xmlrpc_client
|
||||||
@@ -274,9 +276,9 @@ class InventoryModule(BaseInventoryPlugin, Cacheable):
|
|||||||
for host in self._get_systems():
|
for host in self._get_systems():
|
||||||
# Get the FQDN for the host and add it to the right groups
|
# Get the FQDN for the host and add it to the right groups
|
||||||
if self.inventory_hostname == 'system':
|
if self.inventory_hostname == 'system':
|
||||||
hostname = host['name'] # None
|
hostname = make_unsafe(host['name']) # None
|
||||||
else:
|
else:
|
||||||
hostname = host['hostname'] # None
|
hostname = make_unsafe(host['hostname']) # None
|
||||||
interfaces = host['interfaces']
|
interfaces = host['interfaces']
|
||||||
|
|
||||||
if set(host['mgmt_classes']) & set(self.include_mgmt_classes):
|
if set(host['mgmt_classes']) & set(self.include_mgmt_classes):
|
||||||
@@ -296,7 +298,7 @@ class InventoryModule(BaseInventoryPlugin, Cacheable):
|
|||||||
if ivalue['management'] or not ivalue['static']:
|
if ivalue['management'] or not ivalue['static']:
|
||||||
this_dns_name = ivalue.get('dns_name', None)
|
this_dns_name = ivalue.get('dns_name', None)
|
||||||
if this_dns_name is not None and this_dns_name != "":
|
if this_dns_name is not None and this_dns_name != "":
|
||||||
hostname = this_dns_name
|
hostname = make_unsafe(this_dns_name)
|
||||||
self.display.vvvv('Set hostname to %s from %s\n' % (hostname, iname))
|
self.display.vvvv('Set hostname to %s from %s\n' % (hostname, iname))
|
||||||
|
|
||||||
if hostname == '':
|
if hostname == '':
|
||||||
@@ -361,18 +363,18 @@ class InventoryModule(BaseInventoryPlugin, Cacheable):
|
|||||||
if ip_address is None and ip_address_first is not None:
|
if ip_address is None and ip_address_first is not None:
|
||||||
ip_address = ip_address_first
|
ip_address = ip_address_first
|
||||||
if ip_address is not None:
|
if ip_address is not None:
|
||||||
self.inventory.set_variable(hostname, 'cobbler_ipv4_address', ip_address)
|
self.inventory.set_variable(hostname, 'cobbler_ipv4_address', make_unsafe(ip_address))
|
||||||
if ipv6_address is None and ipv6_address_first is not None:
|
if ipv6_address is None and ipv6_address_first is not None:
|
||||||
ipv6_address = ipv6_address_first
|
ipv6_address = ipv6_address_first
|
||||||
if ipv6_address is not None:
|
if ipv6_address is not None:
|
||||||
self.inventory.set_variable(hostname, 'cobbler_ipv6_address', ipv6_address)
|
self.inventory.set_variable(hostname, 'cobbler_ipv6_address', make_unsafe(ipv6_address))
|
||||||
|
|
||||||
if self.get_option('want_facts'):
|
if self.get_option('want_facts'):
|
||||||
try:
|
try:
|
||||||
self.inventory.set_variable(hostname, 'cobbler', host)
|
self.inventory.set_variable(hostname, 'cobbler', make_unsafe(host))
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
self.display.warning("Could not set host info for %s: %s" % (hostname, to_text(e)))
|
self.display.warning("Could not set host info for %s: %s" % (hostname, to_text(e)))
|
||||||
|
|
||||||
if self.get_option('want_ip_addresses'):
|
if self.get_option('want_ip_addresses'):
|
||||||
self.inventory.set_variable(self.group, 'cobbler_ipv4_addresses', ip_addresses)
|
self.inventory.set_variable(self.group, 'cobbler_ipv4_addresses', make_unsafe(ip_addresses))
|
||||||
self.inventory.set_variable(self.group, 'cobbler_ipv6_addresses', ipv6_addresses)
|
self.inventory.set_variable(self.group, 'cobbler_ipv6_addresses', make_unsafe(ipv6_addresses))
|
||||||
|
|||||||
@@ -85,6 +85,8 @@ from ansible.errors import AnsibleError, AnsibleParserError
|
|||||||
from ansible.module_utils.common.text.converters import to_native
|
from ansible.module_utils.common.text.converters import to_native
|
||||||
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable
|
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable
|
||||||
|
|
||||||
|
from ansible_collections.community.general.plugins.plugin_utils.unsafe import make_unsafe
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import gitlab
|
import gitlab
|
||||||
HAS_GITLAB = True
|
HAS_GITLAB = True
|
||||||
@@ -106,11 +108,11 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
|
|||||||
else:
|
else:
|
||||||
runners = gl.runners.all()
|
runners = gl.runners.all()
|
||||||
for runner in runners:
|
for runner in runners:
|
||||||
host = str(runner['id'])
|
host = make_unsafe(str(runner['id']))
|
||||||
ip_address = runner['ip_address']
|
ip_address = runner['ip_address']
|
||||||
host_attrs = vars(gl.runners.get(runner['id']))['_attrs']
|
host_attrs = make_unsafe(vars(gl.runners.get(runner['id']))['_attrs'])
|
||||||
self.inventory.add_host(host, group='gitlab_runners')
|
self.inventory.add_host(host, group='gitlab_runners')
|
||||||
self.inventory.set_variable(host, 'ansible_host', ip_address)
|
self.inventory.set_variable(host, 'ansible_host', make_unsafe(ip_address))
|
||||||
if self.get_option('verbose_output', True):
|
if self.get_option('verbose_output', True):
|
||||||
self.inventory.set_variable(host, 'gitlab_runner_attributes', host_attrs)
|
self.inventory.set_variable(host, 'gitlab_runner_attributes', host_attrs)
|
||||||
|
|
||||||
|
|||||||
@@ -97,6 +97,8 @@ from ansible.plugins.inventory import BaseInventoryPlugin, Constructable
|
|||||||
from ansible.module_utils.urls import open_url
|
from ansible.module_utils.urls import open_url
|
||||||
from ansible.module_utils.six.moves.urllib.error import HTTPError
|
from ansible.module_utils.six.moves.urllib.error import HTTPError
|
||||||
|
|
||||||
|
from ansible_collections.community.general.plugins.plugin_utils.unsafe import make_unsafe
|
||||||
|
|
||||||
|
|
||||||
class InventoryModule(BaseInventoryPlugin, Constructable):
|
class InventoryModule(BaseInventoryPlugin, Constructable):
|
||||||
''' Host inventory parser for ansible using Icinga2 as source. '''
|
''' Host inventory parser for ansible using Icinga2 as source. '''
|
||||||
@@ -233,15 +235,15 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
|
|||||||
"""Convert Icinga2 API data to JSON format for Ansible"""
|
"""Convert Icinga2 API data to JSON format for Ansible"""
|
||||||
groups_dict = {"_meta": {"hostvars": {}}}
|
groups_dict = {"_meta": {"hostvars": {}}}
|
||||||
for entry in json_data:
|
for entry in json_data:
|
||||||
host_attrs = entry['attrs']
|
host_attrs = make_unsafe(entry['attrs'])
|
||||||
if self.inventory_attr == "name":
|
if self.inventory_attr == "name":
|
||||||
host_name = entry.get('name')
|
host_name = make_unsafe(entry.get('name'))
|
||||||
if self.inventory_attr == "address":
|
if self.inventory_attr == "address":
|
||||||
# When looking for address for inventory, if missing fallback to object name
|
# When looking for address for inventory, if missing fallback to object name
|
||||||
if host_attrs.get('address', '') != '':
|
if host_attrs.get('address', '') != '':
|
||||||
host_name = host_attrs.get('address')
|
host_name = make_unsafe(host_attrs.get('address'))
|
||||||
else:
|
else:
|
||||||
host_name = entry.get('name')
|
host_name = make_unsafe(entry.get('name'))
|
||||||
if self.inventory_attr == "display_name":
|
if self.inventory_attr == "display_name":
|
||||||
host_name = host_attrs.get('display_name')
|
host_name = host_attrs.get('display_name')
|
||||||
if host_attrs['state'] == 0:
|
if host_attrs['state'] == 0:
|
||||||
@@ -257,7 +259,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
|
|||||||
# If the address attribute is populated, override ansible_host with the value
|
# If the address attribute is populated, override ansible_host with the value
|
||||||
if host_attrs.get('address') != '':
|
if host_attrs.get('address') != '':
|
||||||
self.inventory.set_variable(host_name, 'ansible_host', host_attrs.get('address'))
|
self.inventory.set_variable(host_name, 'ansible_host', host_attrs.get('address'))
|
||||||
self.inventory.set_variable(host_name, 'hostname', entry.get('name'))
|
self.inventory.set_variable(host_name, 'hostname', make_unsafe(entry.get('name')))
|
||||||
self.inventory.set_variable(host_name, 'display_name', host_attrs.get('display_name'))
|
self.inventory.set_variable(host_name, 'display_name', host_attrs.get('display_name'))
|
||||||
self.inventory.set_variable(host_name, 'state',
|
self.inventory.set_variable(host_name, 'state',
|
||||||
host_attrs['state'])
|
host_attrs['state'])
|
||||||
|
|||||||
@@ -124,6 +124,8 @@ compose:
|
|||||||
from ansible.errors import AnsibleError
|
from ansible.errors import AnsibleError
|
||||||
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cacheable
|
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cacheable
|
||||||
|
|
||||||
|
from ansible_collections.community.general.plugins.plugin_utils.unsafe import make_unsafe
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from linode_api4 import LinodeClient
|
from linode_api4 import LinodeClient
|
||||||
@@ -199,20 +201,21 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
|||||||
def _add_instances_to_groups(self):
|
def _add_instances_to_groups(self):
|
||||||
"""Add instance names to their dynamic inventory groups."""
|
"""Add instance names to their dynamic inventory groups."""
|
||||||
for instance in self.instances:
|
for instance in self.instances:
|
||||||
self.inventory.add_host(instance.label, group=instance.group)
|
self.inventory.add_host(make_unsafe(instance.label), group=instance.group)
|
||||||
|
|
||||||
def _add_hostvars_for_instances(self):
|
def _add_hostvars_for_instances(self):
|
||||||
"""Add hostvars for instances in the dynamic inventory."""
|
"""Add hostvars for instances in the dynamic inventory."""
|
||||||
ip_style = self.get_option('ip_style')
|
ip_style = self.get_option('ip_style')
|
||||||
for instance in self.instances:
|
for instance in self.instances:
|
||||||
hostvars = instance._raw_json
|
hostvars = instance._raw_json
|
||||||
|
hostname = make_unsafe(instance.label)
|
||||||
for hostvar_key in hostvars:
|
for hostvar_key in hostvars:
|
||||||
if ip_style == 'api' and hostvar_key in ['ipv4', 'ipv6']:
|
if ip_style == 'api' and hostvar_key in ['ipv4', 'ipv6']:
|
||||||
continue
|
continue
|
||||||
self.inventory.set_variable(
|
self.inventory.set_variable(
|
||||||
instance.label,
|
hostname,
|
||||||
hostvar_key,
|
hostvar_key,
|
||||||
hostvars[hostvar_key]
|
make_unsafe(hostvars[hostvar_key])
|
||||||
)
|
)
|
||||||
if ip_style == 'api':
|
if ip_style == 'api':
|
||||||
ips = instance.ips.ipv4.public + instance.ips.ipv4.private
|
ips = instance.ips.ipv4.public + instance.ips.ipv4.private
|
||||||
@@ -221,9 +224,9 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
|||||||
|
|
||||||
for ip_type in set(ip.type for ip in ips):
|
for ip_type in set(ip.type for ip in ips):
|
||||||
self.inventory.set_variable(
|
self.inventory.set_variable(
|
||||||
instance.label,
|
hostname,
|
||||||
ip_type,
|
ip_type,
|
||||||
self._ip_data([ip for ip in ips if ip.type == ip_type])
|
make_unsafe(self._ip_data([ip for ip in ips if ip.type == ip_type]))
|
||||||
)
|
)
|
||||||
|
|
||||||
def _ip_data(self, ip_list):
|
def _ip_data(self, ip_list):
|
||||||
@@ -254,30 +257,44 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
|||||||
self._add_instances_to_groups()
|
self._add_instances_to_groups()
|
||||||
self._add_hostvars_for_instances()
|
self._add_hostvars_for_instances()
|
||||||
for instance in self.instances:
|
for instance in self.instances:
|
||||||
variables = self.inventory.get_host(instance.label).get_vars()
|
hostname = make_unsafe(instance.label)
|
||||||
|
variables = self.inventory.get_host(hostname).get_vars()
|
||||||
self._add_host_to_composed_groups(
|
self._add_host_to_composed_groups(
|
||||||
self.get_option('groups'),
|
self.get_option('groups'),
|
||||||
variables,
|
variables,
|
||||||
instance.label,
|
hostname,
|
||||||
strict=strict)
|
strict=strict)
|
||||||
self._add_host_to_keyed_groups(
|
self._add_host_to_keyed_groups(
|
||||||
self.get_option('keyed_groups'),
|
self.get_option('keyed_groups'),
|
||||||
variables,
|
variables,
|
||||||
instance.label,
|
hostname,
|
||||||
strict=strict)
|
strict=strict)
|
||||||
self._set_composite_vars(
|
self._set_composite_vars(
|
||||||
self.get_option('compose'),
|
self.get_option('compose'),
|
||||||
variables,
|
variables,
|
||||||
instance.label,
|
hostname,
|
||||||
strict=strict)
|
strict=strict)
|
||||||
|
|
||||||
def verify_file(self, path):
|
def verify_file(self, path):
|
||||||
"""Verify the Linode configuration file."""
|
"""Verify the Linode configuration file.
|
||||||
|
|
||||||
|
Return true/false if the config-file is valid for this plugin
|
||||||
|
|
||||||
|
Args:
|
||||||
|
str(path): path to the config
|
||||||
|
Kwargs:
|
||||||
|
None
|
||||||
|
Raises:
|
||||||
|
None
|
||||||
|
Returns:
|
||||||
|
bool(valid): is valid config file"""
|
||||||
|
valid = False
|
||||||
if super(InventoryModule, self).verify_file(path):
|
if super(InventoryModule, self).verify_file(path):
|
||||||
endings = ('linode.yaml', 'linode.yml')
|
if path.endswith(("linode.yaml", "linode.yml")):
|
||||||
if any((path.endswith(ending) for ending in endings)):
|
valid = True
|
||||||
return True
|
else:
|
||||||
return False
|
self.display.vvv('Inventory source not ending in "linode.yaml" or "linode.yml"')
|
||||||
|
return valid
|
||||||
|
|
||||||
def parse(self, inventory, loader, path, cache=True):
|
def parse(self, inventory, loader, path, cache=True):
|
||||||
"""Dynamically parse Linode the cloud inventory."""
|
"""Dynamically parse Linode the cloud inventory."""
|
||||||
|
|||||||
@@ -161,6 +161,7 @@ from ansible.module_utils.six import raise_from
|
|||||||
from ansible.errors import AnsibleError, AnsibleParserError
|
from ansible.errors import AnsibleError, AnsibleParserError
|
||||||
from ansible.module_utils.six.moves.urllib.parse import urlencode
|
from ansible.module_utils.six.moves.urllib.parse import urlencode
|
||||||
from ansible_collections.community.general.plugins.module_utils.lxd import LXDClient, LXDClientException
|
from ansible_collections.community.general.plugins.module_utils.lxd import LXDClient, LXDClientException
|
||||||
|
from ansible_collections.community.general.plugins.plugin_utils.unsafe import make_unsafe
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import ipaddress
|
import ipaddress
|
||||||
@@ -656,7 +657,7 @@ class InventoryModule(BaseInventoryPlugin):
|
|||||||
|
|
||||||
if self._get_data_entry('inventory/{0}/network_interfaces'.format(instance_name)): # instance have network interfaces
|
if self._get_data_entry('inventory/{0}/network_interfaces'.format(instance_name)): # instance have network interfaces
|
||||||
self.inventory.set_variable(instance_name, 'ansible_connection', 'ssh')
|
self.inventory.set_variable(instance_name, 'ansible_connection', 'ssh')
|
||||||
self.inventory.set_variable(instance_name, 'ansible_host', interface_selection(instance_name))
|
self.inventory.set_variable(instance_name, 'ansible_host', make_unsafe(interface_selection(instance_name)))
|
||||||
else:
|
else:
|
||||||
self.inventory.set_variable(instance_name, 'ansible_connection', 'local')
|
self.inventory.set_variable(instance_name, 'ansible_connection', 'local')
|
||||||
|
|
||||||
@@ -682,31 +683,39 @@ class InventoryModule(BaseInventoryPlugin):
|
|||||||
if self.filter.lower() != instance_state:
|
if self.filter.lower() != instance_state:
|
||||||
continue
|
continue
|
||||||
# add instance
|
# add instance
|
||||||
|
instance_name = make_unsafe(instance_name)
|
||||||
self.inventory.add_host(instance_name)
|
self.inventory.add_host(instance_name)
|
||||||
# add network information
|
# add network information
|
||||||
self.build_inventory_network(instance_name)
|
self.build_inventory_network(instance_name)
|
||||||
# add os
|
# add os
|
||||||
v = self._get_data_entry('inventory/{0}/os'.format(instance_name))
|
v = self._get_data_entry('inventory/{0}/os'.format(instance_name))
|
||||||
if v:
|
if v:
|
||||||
self.inventory.set_variable(instance_name, 'ansible_lxd_os', v.lower())
|
self.inventory.set_variable(instance_name, 'ansible_lxd_os', make_unsafe(v.lower()))
|
||||||
# add release
|
# add release
|
||||||
v = self._get_data_entry('inventory/{0}/release'.format(instance_name))
|
v = self._get_data_entry('inventory/{0}/release'.format(instance_name))
|
||||||
if v:
|
if v:
|
||||||
self.inventory.set_variable(instance_name, 'ansible_lxd_release', v.lower())
|
self.inventory.set_variable(
|
||||||
|
instance_name, 'ansible_lxd_release', make_unsafe(v.lower()))
|
||||||
# add profile
|
# add profile
|
||||||
self.inventory.set_variable(instance_name, 'ansible_lxd_profile', self._get_data_entry('inventory/{0}/profile'.format(instance_name)))
|
self.inventory.set_variable(
|
||||||
|
instance_name, 'ansible_lxd_profile', make_unsafe(self._get_data_entry('inventory/{0}/profile'.format(instance_name))))
|
||||||
# add state
|
# add state
|
||||||
self.inventory.set_variable(instance_name, 'ansible_lxd_state', instance_state)
|
self.inventory.set_variable(
|
||||||
|
instance_name, 'ansible_lxd_state', make_unsafe(instance_state))
|
||||||
# add type
|
# add type
|
||||||
self.inventory.set_variable(instance_name, 'ansible_lxd_type', self._get_data_entry('inventory/{0}/type'.format(instance_name)))
|
self.inventory.set_variable(
|
||||||
|
instance_name, 'ansible_lxd_type', make_unsafe(self._get_data_entry('inventory/{0}/type'.format(instance_name))))
|
||||||
# add location information
|
# add location information
|
||||||
if self._get_data_entry('inventory/{0}/location'.format(instance_name)) != "none": # wrong type by lxd 'none' != 'None'
|
if self._get_data_entry('inventory/{0}/location'.format(instance_name)) != "none": # wrong type by lxd 'none' != 'None'
|
||||||
self.inventory.set_variable(instance_name, 'ansible_lxd_location', self._get_data_entry('inventory/{0}/location'.format(instance_name)))
|
self.inventory.set_variable(
|
||||||
|
instance_name, 'ansible_lxd_location', make_unsafe(self._get_data_entry('inventory/{0}/location'.format(instance_name))))
|
||||||
# add VLAN_ID information
|
# add VLAN_ID information
|
||||||
if self._get_data_entry('inventory/{0}/vlan_ids'.format(instance_name)):
|
if self._get_data_entry('inventory/{0}/vlan_ids'.format(instance_name)):
|
||||||
self.inventory.set_variable(instance_name, 'ansible_lxd_vlan_ids', self._get_data_entry('inventory/{0}/vlan_ids'.format(instance_name)))
|
self.inventory.set_variable(
|
||||||
|
instance_name, 'ansible_lxd_vlan_ids', make_unsafe(self._get_data_entry('inventory/{0}/vlan_ids'.format(instance_name))))
|
||||||
# add project
|
# add project
|
||||||
self.inventory.set_variable(instance_name, 'ansible_lxd_project', self._get_data_entry('inventory/{0}/project'.format(instance_name)))
|
self.inventory.set_variable(
|
||||||
|
instance_name, 'ansible_lxd_project', make_unsafe(self._get_data_entry('inventory/{0}/project'.format(instance_name))))
|
||||||
|
|
||||||
def build_inventory_groups_location(self, group_name):
|
def build_inventory_groups_location(self, group_name):
|
||||||
"""create group by attribute: location
|
"""create group by attribute: location
|
||||||
@@ -979,7 +988,7 @@ class InventoryModule(BaseInventoryPlugin):
|
|||||||
for group_name in self.groupby:
|
for group_name in self.groupby:
|
||||||
if not group_name.isalnum():
|
if not group_name.isalnum():
|
||||||
raise AnsibleParserError('Invalid character(s) in groupname: {0}'.format(to_native(group_name)))
|
raise AnsibleParserError('Invalid character(s) in groupname: {0}'.format(to_native(group_name)))
|
||||||
group_type(group_name)
|
group_type(make_unsafe(group_name))
|
||||||
|
|
||||||
def build_inventory(self):
|
def build_inventory(self):
|
||||||
"""Build dynamic inventory
|
"""Build dynamic inventory
|
||||||
|
|||||||
@@ -127,6 +127,8 @@ from ansible.module_utils.common.text.converters import to_native, to_text
|
|||||||
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cacheable
|
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cacheable
|
||||||
from ansible.module_utils.common.process import get_bin_path
|
from ansible.module_utils.common.process import get_bin_path
|
||||||
|
|
||||||
|
from ansible_collections.community.general.plugins.plugin_utils.unsafe import make_unsafe
|
||||||
|
|
||||||
|
|
||||||
class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||||
|
|
||||||
@@ -143,6 +145,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
|||||||
strict = self.get_option('strict')
|
strict = self.get_option('strict')
|
||||||
|
|
||||||
for host in hosts:
|
for host in hosts:
|
||||||
|
host = make_unsafe(host)
|
||||||
hostname = host['name']
|
hostname = host['name']
|
||||||
self.inventory.add_host(hostname)
|
self.inventory.add_host(hostname)
|
||||||
for var, value in host.items():
|
for var, value in host.items():
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ from ansible.module_utils.common.text.converters import to_text
|
|||||||
from ansible.module_utils.ansible_release import __version__ as ansible_version
|
from ansible.module_utils.ansible_release import __version__ as ansible_version
|
||||||
from ansible.module_utils.six.moves.urllib.parse import urljoin
|
from ansible.module_utils.six.moves.urllib.parse import urljoin
|
||||||
|
|
||||||
|
from ansible_collections.community.general.plugins.plugin_utils.unsafe import make_unsafe
|
||||||
|
|
||||||
|
|
||||||
class InventoryModule(BaseInventoryPlugin):
|
class InventoryModule(BaseInventoryPlugin):
|
||||||
NAME = 'community.general.online'
|
NAME = 'community.general.online'
|
||||||
@@ -169,20 +171,20 @@ class InventoryModule(BaseInventoryPlugin):
|
|||||||
"support"
|
"support"
|
||||||
)
|
)
|
||||||
for attribute in targeted_attributes:
|
for attribute in targeted_attributes:
|
||||||
self.inventory.set_variable(hostname, attribute, host_infos[attribute])
|
self.inventory.set_variable(hostname, attribute, make_unsafe(host_infos[attribute]))
|
||||||
|
|
||||||
if self.extract_public_ipv4(host_infos=host_infos):
|
if self.extract_public_ipv4(host_infos=host_infos):
|
||||||
self.inventory.set_variable(hostname, "public_ipv4", self.extract_public_ipv4(host_infos=host_infos))
|
self.inventory.set_variable(hostname, "public_ipv4", make_unsafe(self.extract_public_ipv4(host_infos=host_infos)))
|
||||||
self.inventory.set_variable(hostname, "ansible_host", self.extract_public_ipv4(host_infos=host_infos))
|
self.inventory.set_variable(hostname, "ansible_host", make_unsafe(self.extract_public_ipv4(host_infos=host_infos)))
|
||||||
|
|
||||||
if self.extract_private_ipv4(host_infos=host_infos):
|
if self.extract_private_ipv4(host_infos=host_infos):
|
||||||
self.inventory.set_variable(hostname, "public_ipv4", self.extract_private_ipv4(host_infos=host_infos))
|
self.inventory.set_variable(hostname, "public_ipv4", make_unsafe(self.extract_private_ipv4(host_infos=host_infos)))
|
||||||
|
|
||||||
if self.extract_os_name(host_infos=host_infos):
|
if self.extract_os_name(host_infos=host_infos):
|
||||||
self.inventory.set_variable(hostname, "os_name", self.extract_os_name(host_infos=host_infos))
|
self.inventory.set_variable(hostname, "os_name", make_unsafe(self.extract_os_name(host_infos=host_infos)))
|
||||||
|
|
||||||
if self.extract_os_version(host_infos=host_infos):
|
if self.extract_os_version(host_infos=host_infos):
|
||||||
self.inventory.set_variable(hostname, "os_version", self.extract_os_name(host_infos=host_infos))
|
self.inventory.set_variable(hostname, "os_version", make_unsafe(self.extract_os_name(host_infos=host_infos)))
|
||||||
|
|
||||||
def _filter_host(self, host_infos, hostname_preferences):
|
def _filter_host(self, host_infos, hostname_preferences):
|
||||||
|
|
||||||
@@ -201,6 +203,8 @@ class InventoryModule(BaseInventoryPlugin):
|
|||||||
if not hostname:
|
if not hostname:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
hostname = make_unsafe(hostname)
|
||||||
|
|
||||||
self.inventory.add_host(host=hostname)
|
self.inventory.add_host(host=hostname)
|
||||||
self._fill_host_variables(hostname=hostname, host_infos=host_infos)
|
self._fill_host_variables(hostname=hostname, host_infos=host_infos)
|
||||||
|
|
||||||
@@ -210,6 +214,8 @@ class InventoryModule(BaseInventoryPlugin):
|
|||||||
if not group:
|
if not group:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
group = make_unsafe(group)
|
||||||
|
|
||||||
self.inventory.add_group(group=group)
|
self.inventory.add_group(group=group)
|
||||||
self.inventory.add_host(group=group, host=hostname)
|
self.inventory.add_host(group=group, host=hostname)
|
||||||
|
|
||||||
|
|||||||
@@ -98,6 +98,8 @@ from ansible.errors import AnsibleError
|
|||||||
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable
|
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable
|
||||||
from ansible.module_utils.common.text.converters import to_native
|
from ansible.module_utils.common.text.converters import to_native
|
||||||
|
|
||||||
|
from ansible_collections.community.general.plugins.plugin_utils.unsafe import make_unsafe
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
import os
|
import os
|
||||||
|
|
||||||
@@ -215,6 +217,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
|
|||||||
filter_by_label = self.get_option('filter_by_label')
|
filter_by_label = self.get_option('filter_by_label')
|
||||||
servers = self._retrieve_servers(filter_by_label)
|
servers = self._retrieve_servers(filter_by_label)
|
||||||
for server in servers:
|
for server in servers:
|
||||||
|
server = make_unsafe(server)
|
||||||
hostname = server['name']
|
hostname = server['name']
|
||||||
# check for labels
|
# check for labels
|
||||||
if group_by_labels and server['LABELS']:
|
if group_by_labels and server['LABELS']:
|
||||||
|
|||||||
@@ -224,6 +224,7 @@ from ansible.module_utils.six.moves.urllib.parse import urlencode
|
|||||||
from ansible.utils.display import Display
|
from ansible.utils.display import Display
|
||||||
|
|
||||||
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
|
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
|
||||||
|
from ansible_collections.community.general.plugins.plugin_utils.unsafe import make_unsafe
|
||||||
|
|
||||||
# 3rd party imports
|
# 3rd party imports
|
||||||
try:
|
try:
|
||||||
@@ -330,7 +331,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
|||||||
|
|
||||||
self._cache[self.cache_key][url] = data
|
self._cache[self.cache_key][url] = data
|
||||||
|
|
||||||
return self._cache[self.cache_key][url]
|
return make_unsafe(self._cache[self.cache_key][url])
|
||||||
|
|
||||||
def _get_nodes(self):
|
def _get_nodes(self):
|
||||||
return self._get_json("%s/api2/json/nodes" % self.proxmox_url)
|
return self._get_json("%s/api2/json/nodes" % self.proxmox_url)
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ else:
|
|||||||
from ansible.errors import AnsibleError
|
from ansible.errors import AnsibleError
|
||||||
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable
|
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable
|
||||||
from ansible_collections.community.general.plugins.module_utils.scaleway import SCALEWAY_LOCATION, parse_pagination_link
|
from ansible_collections.community.general.plugins.module_utils.scaleway import SCALEWAY_LOCATION, parse_pagination_link
|
||||||
|
from ansible_collections.community.general.plugins.plugin_utils.unsafe import make_unsafe
|
||||||
from ansible.module_utils.urls import open_url
|
from ansible.module_utils.urls import open_url
|
||||||
from ansible.module_utils.common.text.converters import to_native, to_text
|
from ansible.module_utils.common.text.converters import to_native, to_text
|
||||||
from ansible.module_utils.six import raise_from
|
from ansible.module_utils.six import raise_from
|
||||||
@@ -279,7 +280,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
|
|||||||
zone_info = SCALEWAY_LOCATION[zone]
|
zone_info = SCALEWAY_LOCATION[zone]
|
||||||
|
|
||||||
url = _build_server_url(zone_info["api_endpoint"])
|
url = _build_server_url(zone_info["api_endpoint"])
|
||||||
raw_zone_hosts_infos = _fetch_information(url=url, token=token)
|
raw_zone_hosts_infos = make_unsafe(_fetch_information(url=url, token=token))
|
||||||
|
|
||||||
for host_infos in raw_zone_hosts_infos:
|
for host_infos in raw_zone_hosts_infos:
|
||||||
|
|
||||||
@@ -341,4 +342,4 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
|
|||||||
hostname_preference = self.get_option("hostnames")
|
hostname_preference = self.get_option("hostnames")
|
||||||
|
|
||||||
for zone in self._get_zones(config_zones):
|
for zone in self._get_zones(config_zones):
|
||||||
self.do_zone_inventory(zone=zone, token=token, tags=tags, hostname_preferences=hostname_preference)
|
self.do_zone_inventory(zone=make_unsafe(zone), token=token, tags=tags, hostname_preferences=hostname_preference)
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ from ansible.plugins.inventory import (
|
|||||||
)
|
)
|
||||||
from ansible.utils.display import Display
|
from ansible.utils.display import Display
|
||||||
|
|
||||||
|
from ansible_collections.community.general.plugins.plugin_utils.unsafe import make_unsafe
|
||||||
|
|
||||||
|
|
||||||
display = Display()
|
display = Display()
|
||||||
|
|
||||||
@@ -271,7 +273,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
|||||||
if not cache or cache_needs_update:
|
if not cache or cache_needs_update:
|
||||||
results = self._query()
|
results = self._query()
|
||||||
|
|
||||||
self._populate(results)
|
self._populate(make_unsafe(results))
|
||||||
|
|
||||||
# If the cache has expired/doesn't exist or
|
# If the cache has expired/doesn't exist or
|
||||||
# if refresh_inventory/flush cache is used
|
# if refresh_inventory/flush cache is used
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ from ansible.module_utils.common._collections_compat import MutableMapping
|
|||||||
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cacheable
|
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cacheable
|
||||||
from ansible.module_utils.common.process import get_bin_path
|
from ansible.module_utils.common.process import get_bin_path
|
||||||
|
|
||||||
|
from ansible_collections.community.general.plugins.plugin_utils.unsafe import make_unsafe
|
||||||
|
|
||||||
|
|
||||||
class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||||
''' Host inventory parser for ansible using local virtualbox. '''
|
''' Host inventory parser for ansible using local virtualbox. '''
|
||||||
@@ -116,6 +118,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
|||||||
self._add_host_to_keyed_groups(self.get_option('keyed_groups'), hostvars[host], host, strict=strict)
|
self._add_host_to_keyed_groups(self.get_option('keyed_groups'), hostvars[host], host, strict=strict)
|
||||||
|
|
||||||
def _populate_from_cache(self, source_data):
|
def _populate_from_cache(self, source_data):
|
||||||
|
source_data = make_unsafe(source_data)
|
||||||
hostvars = source_data.pop('_meta', {}).get('hostvars', {})
|
hostvars = source_data.pop('_meta', {}).get('hostvars', {})
|
||||||
for group in source_data:
|
for group in source_data:
|
||||||
if group == 'all':
|
if group == 'all':
|
||||||
@@ -162,7 +165,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
|||||||
v = v.strip()
|
v = v.strip()
|
||||||
# found host
|
# found host
|
||||||
if k.startswith('Name') and ',' not in v: # some setting strings appear in Name
|
if k.startswith('Name') and ',' not in v: # some setting strings appear in Name
|
||||||
current_host = v
|
current_host = make_unsafe(v)
|
||||||
if current_host not in hostvars:
|
if current_host not in hostvars:
|
||||||
hostvars[current_host] = {}
|
hostvars[current_host] = {}
|
||||||
self.inventory.add_host(current_host)
|
self.inventory.add_host(current_host)
|
||||||
@@ -170,12 +173,13 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
|||||||
# try to get network info
|
# try to get network info
|
||||||
netdata = self._query_vbox_data(current_host, netinfo)
|
netdata = self._query_vbox_data(current_host, netinfo)
|
||||||
if netdata:
|
if netdata:
|
||||||
self.inventory.set_variable(current_host, 'ansible_host', netdata)
|
self.inventory.set_variable(current_host, 'ansible_host', make_unsafe(netdata))
|
||||||
|
|
||||||
# found groups
|
# found groups
|
||||||
elif k == 'Groups':
|
elif k == 'Groups':
|
||||||
for group in v.split('/'):
|
for group in v.split('/'):
|
||||||
if group:
|
if group:
|
||||||
|
group = make_unsafe(group)
|
||||||
group = self.inventory.add_group(group)
|
group = self.inventory.add_group(group)
|
||||||
self.inventory.add_child(group, current_host)
|
self.inventory.add_child(group, current_host)
|
||||||
if group not in cacheable_results:
|
if group not in cacheable_results:
|
||||||
@@ -185,17 +189,17 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
# found vars, accumulate in hostvars for clean inventory set
|
# found vars, accumulate in hostvars for clean inventory set
|
||||||
pref_k = 'vbox_' + k.strip().replace(' ', '_')
|
pref_k = make_unsafe('vbox_' + k.strip().replace(' ', '_'))
|
||||||
leading_spaces = len(k) - len(k.lstrip(' '))
|
leading_spaces = len(k) - len(k.lstrip(' '))
|
||||||
if 0 < leading_spaces <= 2:
|
if 0 < leading_spaces <= 2:
|
||||||
if prevkey not in hostvars[current_host] or not isinstance(hostvars[current_host][prevkey], dict):
|
if prevkey not in hostvars[current_host] or not isinstance(hostvars[current_host][prevkey], dict):
|
||||||
hostvars[current_host][prevkey] = {}
|
hostvars[current_host][prevkey] = {}
|
||||||
hostvars[current_host][prevkey][pref_k] = v
|
hostvars[current_host][prevkey][pref_k] = make_unsafe(v)
|
||||||
elif leading_spaces > 2:
|
elif leading_spaces > 2:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
if v != '':
|
if v != '':
|
||||||
hostvars[current_host][pref_k] = v
|
hostvars[current_host][pref_k] = make_unsafe(v)
|
||||||
if self._ungrouped_host(current_host, cacheable_results):
|
if self._ungrouped_host(current_host, cacheable_results):
|
||||||
if 'ungrouped' not in cacheable_results:
|
if 'ungrouped' not in cacheable_results:
|
||||||
cacheable_results['ungrouped'] = {'hosts': []}
|
cacheable_results['ungrouped'] = {'hosts': []}
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ from ansible.errors import AnsibleError
|
|||||||
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cacheable
|
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cacheable
|
||||||
|
|
||||||
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
|
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
|
||||||
|
from ansible_collections.community.general.plugins.plugin_utils.unsafe import make_unsafe
|
||||||
|
|
||||||
# 3rd party imports
|
# 3rd party imports
|
||||||
try:
|
try:
|
||||||
@@ -347,4 +348,4 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
|||||||
self.protocol = 'ws'
|
self.protocol = 'ws'
|
||||||
|
|
||||||
objects = self._get_objects()
|
objects = self._get_objects()
|
||||||
self._populate(objects)
|
self._populate(make_unsafe(objects))
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ RETURN = """
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from subprocess import Popen, PIPE
|
from subprocess import Popen, PIPE
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
from ansible.errors import AnsibleLookupError
|
from ansible.errors import AnsibleLookupError
|
||||||
from ansible.module_utils.common.text.converters import to_text
|
from ansible.module_utils.common.text.converters import to_text
|
||||||
@@ -84,11 +85,29 @@ class BitwardenSecretsManagerException(AnsibleLookupError):
|
|||||||
class BitwardenSecretsManager(object):
|
class BitwardenSecretsManager(object):
|
||||||
def __init__(self, path='bws'):
|
def __init__(self, path='bws'):
|
||||||
self._cli_path = path
|
self._cli_path = path
|
||||||
|
self._max_retries = 3
|
||||||
|
self._retry_delay = 1
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def cli_path(self):
|
def cli_path(self):
|
||||||
return self._cli_path
|
return self._cli_path
|
||||||
|
|
||||||
|
def _run_with_retry(self, args, stdin=None, retries=0):
|
||||||
|
out, err, rc = self._run(args, stdin)
|
||||||
|
|
||||||
|
if rc != 0:
|
||||||
|
if retries >= self._max_retries:
|
||||||
|
raise BitwardenSecretsManagerException("Max retries exceeded. Unable to retrieve secret.")
|
||||||
|
|
||||||
|
if "Too many requests" in err:
|
||||||
|
delay = self._retry_delay * (2 ** retries)
|
||||||
|
sleep(delay)
|
||||||
|
return self._run_with_retry(args, stdin, retries + 1)
|
||||||
|
else:
|
||||||
|
raise BitwardenSecretsManagerException("Command failed with return code {rc}: {err}".format(rc=rc, err=err))
|
||||||
|
|
||||||
|
return out, err, rc
|
||||||
|
|
||||||
def _run(self, args, stdin=None):
|
def _run(self, args, stdin=None):
|
||||||
p = Popen([self.cli_path] + args, stdout=PIPE, stderr=PIPE, stdin=PIPE)
|
p = Popen([self.cli_path] + args, stdout=PIPE, stderr=PIPE, stdin=PIPE)
|
||||||
out, err = p.communicate(stdin)
|
out, err = p.communicate(stdin)
|
||||||
@@ -107,7 +126,7 @@ class BitwardenSecretsManager(object):
|
|||||||
'get', 'secret', secret_id
|
'get', 'secret', secret_id
|
||||||
]
|
]
|
||||||
|
|
||||||
out, err, rc = self._run(params)
|
out, err, rc = self._run_with_retry(params)
|
||||||
if rc != 0:
|
if rc != 0:
|
||||||
raise BitwardenSecretsManagerException(to_text(err))
|
raise BitwardenSecretsManagerException(to_text(err))
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ DOCUMENTATION = """
|
|||||||
- Roy Lenferink (@rlenferink)
|
- Roy Lenferink (@rlenferink)
|
||||||
- Mark Ettema (@m-a-r-k-e)
|
- Mark Ettema (@m-a-r-k-e)
|
||||||
name: merge_variables
|
name: merge_variables
|
||||||
short_description: merge variables with a certain suffix
|
short_description: merge variables whose names match a given pattern
|
||||||
description:
|
description:
|
||||||
- This lookup returns the merged result of all variables in scope that match the given prefixes, suffixes, or
|
- This lookup returns the merged result of all variables in scope that match the given prefixes, suffixes, or
|
||||||
regular expressions, optionally.
|
regular expressions, optionally.
|
||||||
|
|||||||
@@ -512,10 +512,10 @@ class OnePassCLIv2(OnePassCLIBase):
|
|||||||
current_section_title = section.get("label", section.get("id", "")).lower()
|
current_section_title = section.get("label", section.get("id", "")).lower()
|
||||||
if section_title == current_section_title:
|
if section_title == current_section_title:
|
||||||
# In the correct section. Check "label" then "id" for the desired field_name
|
# In the correct section. Check "label" then "id" for the desired field_name
|
||||||
if field.get("label") == field_name:
|
if field.get("label", "").lower() == field_name:
|
||||||
return field.get("value", "")
|
return field.get("value", "")
|
||||||
|
|
||||||
if field.get("id") == field_name:
|
if field.get("id", "").lower() == field_name:
|
||||||
return field.get("value", "")
|
return field.get("value", "")
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
|
|||||||
@@ -21,15 +21,30 @@ except ImportError:
|
|||||||
|
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
|
def _determine_list_all_kwargs(version):
|
||||||
|
gitlab_version = LooseVersion(version)
|
||||||
|
if gitlab_version >= LooseVersion('4.0.0'):
|
||||||
|
# 4.0.0 removed 'as_list'
|
||||||
|
return {'iterator': True, 'per_page': 100}
|
||||||
|
elif gitlab_version >= LooseVersion('3.7.0'):
|
||||||
|
# 3.7.0 added 'get_all'
|
||||||
|
return {'as_list': False, 'get_all': True, 'per_page': 100}
|
||||||
|
else:
|
||||||
|
return {'as_list': False, 'all': True, 'per_page': 100}
|
||||||
|
|
||||||
|
|
||||||
GITLAB_IMP_ERR = None
|
GITLAB_IMP_ERR = None
|
||||||
try:
|
try:
|
||||||
import gitlab
|
import gitlab
|
||||||
import requests
|
import requests
|
||||||
HAS_GITLAB_PACKAGE = True
|
HAS_GITLAB_PACKAGE = True
|
||||||
|
list_all_kwargs = _determine_list_all_kwargs(gitlab.__version__)
|
||||||
except Exception:
|
except Exception:
|
||||||
gitlab = None
|
gitlab = None
|
||||||
GITLAB_IMP_ERR = traceback.format_exc()
|
GITLAB_IMP_ERR = traceback.format_exc()
|
||||||
HAS_GITLAB_PACKAGE = False
|
HAS_GITLAB_PACKAGE = False
|
||||||
|
list_all_kwargs = {}
|
||||||
|
|
||||||
|
|
||||||
def auth_argument_spec(spec=None):
|
def auth_argument_spec(spec=None):
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ class IPAClient(object):
|
|||||||
|
|
||||||
def get_ipa_version(self):
|
def get_ipa_version(self):
|
||||||
response = self.ping()['summary']
|
response = self.ping()['summary']
|
||||||
ipa_ver_regex = re.compile(r'IPA server version (\d\.\d\.\d).*')
|
ipa_ver_regex = re.compile(r'IPA server version (\d+\.\d+\.\d+).*')
|
||||||
version_match = ipa_ver_regex.match(response)
|
version_match = ipa_ver_regex.match(response)
|
||||||
ipa_version = None
|
ipa_version = None
|
||||||
if version_match:
|
if version_match:
|
||||||
|
|||||||
@@ -107,5 +107,6 @@ def puppet_runner(module):
|
|||||||
verbose=cmd_runner_fmt.as_bool("--verbose"),
|
verbose=cmd_runner_fmt.as_bool("--verbose"),
|
||||||
),
|
),
|
||||||
check_rc=False,
|
check_rc=False,
|
||||||
|
force_lang=module.params["environment_lang"],
|
||||||
)
|
)
|
||||||
return runner
|
return runner
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ from ansible.module_utils.six import text_type
|
|||||||
from ansible.module_utils.six.moves import http_client
|
from ansible.module_utils.six.moves import http_client
|
||||||
from ansible.module_utils.six.moves.urllib.error import URLError, HTTPError
|
from ansible.module_utils.six.moves.urllib.error import URLError, HTTPError
|
||||||
from ansible.module_utils.six.moves.urllib.parse import urlparse
|
from ansible.module_utils.six.moves.urllib.parse import urlparse
|
||||||
|
from ansible.module_utils.ansible_release import __version__ as ansible_version
|
||||||
|
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
|
||||||
|
|
||||||
GET_HEADERS = {'accept': 'application/json', 'OData-Version': '4.0'}
|
GET_HEADERS = {'accept': 'application/json', 'OData-Version': '4.0'}
|
||||||
POST_HEADERS = {'content-type': 'application/json', 'accept': 'application/json',
|
POST_HEADERS = {'content-type': 'application/json', 'accept': 'application/json',
|
||||||
@@ -130,7 +132,7 @@ class RedfishUtils(object):
|
|||||||
return resp
|
return resp
|
||||||
|
|
||||||
# The following functions are to send GET/POST/PATCH/DELETE requests
|
# The following functions are to send GET/POST/PATCH/DELETE requests
|
||||||
def get_request(self, uri, override_headers=None):
|
def get_request(self, uri, override_headers=None, allow_no_resp=False):
|
||||||
req_headers = dict(GET_HEADERS)
|
req_headers = dict(GET_HEADERS)
|
||||||
if override_headers:
|
if override_headers:
|
||||||
req_headers.update(override_headers)
|
req_headers.update(override_headers)
|
||||||
@@ -145,13 +147,19 @@ class RedfishUtils(object):
|
|||||||
force_basic_auth=basic_auth, validate_certs=False,
|
force_basic_auth=basic_auth, validate_certs=False,
|
||||||
follow_redirects='all',
|
follow_redirects='all',
|
||||||
use_proxy=True, timeout=self.timeout)
|
use_proxy=True, timeout=self.timeout)
|
||||||
if override_headers:
|
headers = dict((k.lower(), v) for (k, v) in resp.info().items())
|
||||||
resp = gzip.open(BytesIO(resp.read()), 'rt', encoding='utf-8')
|
try:
|
||||||
data = json.loads(to_native(resp.read()))
|
if headers.get('content-encoding') == 'gzip' and LooseVersion(ansible_version) < LooseVersion('2.14'):
|
||||||
headers = req_headers
|
# Older versions of Ansible do not automatically decompress the data
|
||||||
else:
|
# Starting in 2.14, open_url will decompress the response data by default
|
||||||
data = json.loads(to_native(resp.read()))
|
data = json.loads(to_native(gzip.open(BytesIO(resp.read()), 'rt', encoding='utf-8').read()))
|
||||||
headers = dict((k.lower(), v) for (k, v) in resp.info().items())
|
else:
|
||||||
|
data = json.loads(to_native(resp.read()))
|
||||||
|
except Exception as e:
|
||||||
|
# No response data; this is okay in certain cases
|
||||||
|
data = None
|
||||||
|
if not allow_no_resp:
|
||||||
|
raise
|
||||||
except HTTPError as e:
|
except HTTPError as e:
|
||||||
msg = self._get_extended_message(e)
|
msg = self._get_extended_message(e)
|
||||||
return {'ret': False,
|
return {'ret': False,
|
||||||
@@ -1813,7 +1821,7 @@ class RedfishUtils(object):
|
|||||||
return {'ret': False, 'msg': 'Must provide a handle tracking the update.'}
|
return {'ret': False, 'msg': 'Must provide a handle tracking the update.'}
|
||||||
|
|
||||||
# Get the task or job tracking the update
|
# Get the task or job tracking the update
|
||||||
response = self.get_request(self.root_uri + update_handle)
|
response = self.get_request(self.root_uri + update_handle, allow_no_resp=True)
|
||||||
if response['ret'] is False:
|
if response['ret'] is False:
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@@ -2907,8 +2915,7 @@ class RedfishUtils(object):
|
|||||||
|
|
||||||
# Get a list of all Chassis and build URIs, then get all PowerSupplies
|
# Get a list of all Chassis and build URIs, then get all PowerSupplies
|
||||||
# from each Power entry in the Chassis
|
# from each Power entry in the Chassis
|
||||||
chassis_uri_list = self.chassis_uris
|
for chassis_uri in self.chassis_uris:
|
||||||
for chassis_uri in chassis_uri_list:
|
|
||||||
response = self.get_request(self.root_uri + chassis_uri)
|
response = self.get_request(self.root_uri + chassis_uri)
|
||||||
if response['ret'] is False:
|
if response['ret'] is False:
|
||||||
return response
|
return response
|
||||||
@@ -3470,33 +3477,30 @@ class RedfishUtils(object):
|
|||||||
result = {}
|
result = {}
|
||||||
key = "Thermal"
|
key = "Thermal"
|
||||||
# Go through list
|
# Go through list
|
||||||
for chassis_uri in self.chassis_uri_list:
|
for chassis_uri in self.chassis_uris:
|
||||||
response = self.get_request(self.root_uri + chassis_uri)
|
response = self.get_request(self.root_uri + chassis_uri)
|
||||||
if response['ret'] is False:
|
if response['ret'] is False:
|
||||||
return response
|
return response
|
||||||
result['ret'] = True
|
result['ret'] = True
|
||||||
data = response['data']
|
data = response['data']
|
||||||
oem = data.get['Oem']
|
val = data.get('Oem', {}).get('Hpe', {}).get('ThermalConfiguration')
|
||||||
hpe = oem.get['Hpe']
|
if val is not None:
|
||||||
thermal_config = hpe.get('ThermalConfiguration')
|
return {"ret": True, "current_thermal_config": val}
|
||||||
result["current_thermal_config"] = thermal_config
|
return {"ret": False}
|
||||||
return result
|
|
||||||
|
|
||||||
def get_hpe_fan_percent_min(self):
|
def get_hpe_fan_percent_min(self):
|
||||||
result = {}
|
result = {}
|
||||||
key = "Thermal"
|
key = "Thermal"
|
||||||
# Go through list
|
# Go through list
|
||||||
for chassis_uri in self.chassis_uri_list:
|
for chassis_uri in self.chassis_uris:
|
||||||
response = self.get_request(self.root_uri + chassis_uri)
|
response = self.get_request(self.root_uri + chassis_uri)
|
||||||
if response['ret'] is False:
|
if response['ret'] is False:
|
||||||
return response
|
return response
|
||||||
result['ret'] = True
|
|
||||||
data = response['data']
|
data = response['data']
|
||||||
oem = data.get['Oem']
|
val = data.get('Oem', {}).get('Hpe', {}).get('FanPercentMinimum')
|
||||||
hpe = oem.get['Hpe']
|
if val is not None:
|
||||||
fan_percent_min_config = hpe.get('FanPercentMinimum')
|
return {"ret": True, "fan_percent_min": val}
|
||||||
result["fan_percent_min"] = fan_percent_min_config
|
return {"ret": False}
|
||||||
return result
|
|
||||||
|
|
||||||
def delete_volumes(self, storage_subsystem_id, volume_ids):
|
def delete_volumes(self, storage_subsystem_id, volume_ids):
|
||||||
# Find the Storage resource from the requested ComputerSystem resource
|
# Find the Storage resource from the requested ComputerSystem resource
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ options:
|
|||||||
type: list
|
type: list
|
||||||
elements: str
|
elements: str
|
||||||
default:
|
default:
|
||||||
- agblksize='4096'
|
- agblksize=4096
|
||||||
- isnapshot='no'
|
- isnapshot=no
|
||||||
auto_mount:
|
auto_mount:
|
||||||
description:
|
description:
|
||||||
- File system is automatically mounted at system restart.
|
- File system is automatically mounted at system restart.
|
||||||
@@ -242,7 +242,7 @@ def _validate_vg(module, vg):
|
|||||||
if rc != 0:
|
if rc != 0:
|
||||||
module.fail_json(msg="Failed executing %s command." % lsvg_cmd)
|
module.fail_json(msg="Failed executing %s command." % lsvg_cmd)
|
||||||
|
|
||||||
rc, current_all_vgs, err = module.run_command([lsvg_cmd, "%s"])
|
rc, current_all_vgs, err = module.run_command([lsvg_cmd])
|
||||||
if rc != 0:
|
if rc != 0:
|
||||||
module.fail_json(msg="Failed executing %s command." % lsvg_cmd)
|
module.fail_json(msg="Failed executing %s command." % lsvg_cmd)
|
||||||
|
|
||||||
@@ -365,7 +365,53 @@ def create_fs(
|
|||||||
# Creates a LVM file system.
|
# Creates a LVM file system.
|
||||||
crfs_cmd = module.get_bin_path('crfs', True)
|
crfs_cmd = module.get_bin_path('crfs', True)
|
||||||
if not module.check_mode:
|
if not module.check_mode:
|
||||||
cmd = [crfs_cmd, "-v", fs_type, "-m", filesystem, vg, device, mount_group, auto_mount, account_subsystem, "-p", permissions, size, "-a", attributes]
|
cmd = [crfs_cmd]
|
||||||
|
|
||||||
|
cmd.append("-v")
|
||||||
|
cmd.append(fs_type)
|
||||||
|
|
||||||
|
if vg:
|
||||||
|
(flag, value) = vg.split()
|
||||||
|
cmd.append(flag)
|
||||||
|
cmd.append(value)
|
||||||
|
|
||||||
|
if device:
|
||||||
|
(flag, value) = device.split()
|
||||||
|
cmd.append(flag)
|
||||||
|
cmd.append(value)
|
||||||
|
|
||||||
|
cmd.append("-m")
|
||||||
|
cmd.append(filesystem)
|
||||||
|
|
||||||
|
if mount_group:
|
||||||
|
(flag, value) = mount_group.split()
|
||||||
|
cmd.append(flag)
|
||||||
|
cmd.append(value)
|
||||||
|
|
||||||
|
if auto_mount:
|
||||||
|
(flag, value) = auto_mount.split()
|
||||||
|
cmd.append(flag)
|
||||||
|
cmd.append(value)
|
||||||
|
|
||||||
|
if account_subsystem:
|
||||||
|
(flag, value) = account_subsystem.split()
|
||||||
|
cmd.append(flag)
|
||||||
|
cmd.append(value)
|
||||||
|
|
||||||
|
cmd.append("-p")
|
||||||
|
cmd.append(permissions)
|
||||||
|
|
||||||
|
if size:
|
||||||
|
(flag, value) = size.split()
|
||||||
|
cmd.append(flag)
|
||||||
|
cmd.append(value)
|
||||||
|
|
||||||
|
if attributes:
|
||||||
|
splitted_attributes = attributes.split()
|
||||||
|
cmd.append("-a")
|
||||||
|
for value in splitted_attributes:
|
||||||
|
cmd.append(value)
|
||||||
|
|
||||||
rc, crfs_out, err = module.run_command(cmd)
|
rc, crfs_out, err = module.run_command(cmd)
|
||||||
|
|
||||||
if rc == 10:
|
if rc == 10:
|
||||||
@@ -461,7 +507,7 @@ def main():
|
|||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
argument_spec=dict(
|
argument_spec=dict(
|
||||||
account_subsystem=dict(type='bool', default=False),
|
account_subsystem=dict(type='bool', default=False),
|
||||||
attributes=dict(type='list', elements='str', default=["agblksize='4096'", "isnapshot='no'"]),
|
attributes=dict(type='list', elements='str', default=["agblksize=4096", "isnapshot=no"]),
|
||||||
auto_mount=dict(type='bool', default=True),
|
auto_mount=dict(type='bool', default=True),
|
||||||
device=dict(type='str'),
|
device=dict(type='str'),
|
||||||
filesystem=dict(type='str', required=True),
|
filesystem=dict(type='str', required=True),
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ options:
|
|||||||
default: false
|
default: false
|
||||||
name:
|
name:
|
||||||
description:
|
description:
|
||||||
- A package name, like V(foo), or multiple packages, like V(foo, bar).
|
- A package name, like V(foo), or multiple packages, like V(foo,bar).
|
||||||
|
- Do not include additional whitespace when specifying multiple packages as a string.
|
||||||
|
Prefer YAML lists over comma-separating multiple package names.
|
||||||
type: list
|
type: list
|
||||||
elements: str
|
elements: str
|
||||||
no_cache:
|
no_cache:
|
||||||
@@ -61,7 +63,7 @@ options:
|
|||||||
type: str
|
type: str
|
||||||
update_cache:
|
update_cache:
|
||||||
description:
|
description:
|
||||||
- Update repository indexes. Can be run with other steps or on it's own.
|
- Update repository indexes. Can be run with other steps or on its own.
|
||||||
type: bool
|
type: bool
|
||||||
default: false
|
default: false
|
||||||
upgrade:
|
upgrade:
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ def install_packages(module, pkgspec):
|
|||||||
rc, out, err = module.run_command("%s -y install %s" % (APT_PATH, packages), environ_update={"LANG": "C"})
|
rc, out, err = module.run_command("%s -y install %s" % (APT_PATH, packages), environ_update={"LANG": "C"})
|
||||||
|
|
||||||
installed = True
|
installed = True
|
||||||
for packages in pkgspec:
|
for package in pkgspec:
|
||||||
if not query_package_provides(module, package):
|
if not query_package_provides(module, package):
|
||||||
installed = False
|
installed = False
|
||||||
|
|
||||||
|
|||||||
@@ -102,40 +102,40 @@ EXAMPLES = r'''
|
|||||||
- name: Create a @home subvolume under the root subvolume
|
- name: Create a @home subvolume under the root subvolume
|
||||||
community.general.btrfs_subvolume:
|
community.general.btrfs_subvolume:
|
||||||
name: /@home
|
name: /@home
|
||||||
device: /dev/vda2
|
filesystem_device: /dev/vda2
|
||||||
|
|
||||||
- name: Remove the @home subvolume if it exists
|
- name: Remove the @home subvolume if it exists
|
||||||
community.general.btrfs_subvolume:
|
community.general.btrfs_subvolume:
|
||||||
name: /@home
|
name: /@home
|
||||||
state: absent
|
state: absent
|
||||||
device: /dev/vda2
|
filesystem_device: /dev/vda2
|
||||||
|
|
||||||
- name: Create a snapshot of the root subvolume named @
|
- name: Create a snapshot of the root subvolume named @
|
||||||
community.general.btrfs_subvolume:
|
community.general.btrfs_subvolume:
|
||||||
name: /@
|
name: /@
|
||||||
snapshot_source: /
|
snapshot_source: /
|
||||||
device: /dev/vda2
|
filesystem_device: /dev/vda2
|
||||||
|
|
||||||
- name: Create a snapshot of the root subvolume and make it the new default subvolume
|
- name: Create a snapshot of the root subvolume and make it the new default subvolume
|
||||||
community.general.btrfs_subvolume:
|
community.general.btrfs_subvolume:
|
||||||
name: /@
|
name: /@
|
||||||
snapshot_source: /
|
snapshot_source: /
|
||||||
default: Yes
|
default: Yes
|
||||||
device: /dev/vda2
|
filesystem_device: /dev/vda2
|
||||||
|
|
||||||
- name: Create a snapshot of the /@ subvolume and recursively creating intermediate subvolumes as required
|
- name: Create a snapshot of the /@ subvolume and recursively creating intermediate subvolumes as required
|
||||||
community.general.btrfs_subvolume:
|
community.general.btrfs_subvolume:
|
||||||
name: /@snapshots/@2022_06_09
|
name: /@snapshots/@2022_06_09
|
||||||
snapshot_source: /@
|
snapshot_source: /@
|
||||||
recursive: True
|
recursive: True
|
||||||
device: /dev/vda2
|
filesystem_device: /dev/vda2
|
||||||
|
|
||||||
- name: Remove the /@ subvolume and recursively delete child subvolumes as required
|
- name: Remove the /@ subvolume and recursively delete child subvolumes as required
|
||||||
community.general.btrfs_subvolume:
|
community.general.btrfs_subvolume:
|
||||||
name: /@snapshots/@2022_06_09
|
name: /@snapshots/@2022_06_09
|
||||||
snapshot_source: /@
|
snapshot_source: /@
|
||||||
recursive: True
|
recursive: True
|
||||||
device: /dev/vda2
|
filesystem_device: /dev/vda2
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|||||||
@@ -137,6 +137,10 @@ class Cargo(object):
|
|||||||
|
|
||||||
def get_installed(self):
|
def get_installed(self):
|
||||||
cmd = ["install", "--list"]
|
cmd = ["install", "--list"]
|
||||||
|
if self.path:
|
||||||
|
cmd.append("--root")
|
||||||
|
cmd.append(self.path)
|
||||||
|
|
||||||
data, dummy = self._exec(cmd, True, False, False)
|
data, dummy = self._exec(cmd, True, False, False)
|
||||||
|
|
||||||
package_regex = re.compile(r"^([\w\-]+) v(.+):$")
|
package_regex = re.compile(r"^([\w\-]+) v(.+):$")
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ class EjabberdUser(object):
|
|||||||
object manages user creation and deletion using ejabberdctl. The following
|
object manages user creation and deletion using ejabberdctl. The following
|
||||||
commands are currently supported:
|
commands are currently supported:
|
||||||
* ejabberdctl register
|
* ejabberdctl register
|
||||||
* ejabberdctl deregister
|
* ejabberdctl unregister
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, module):
|
def __init__(self, module):
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ from ansible.module_utils.basic import AnsibleModule
|
|||||||
from ansible.module_utils.common.text.converters import to_native
|
from ansible.module_utils.common.text.converters import to_native
|
||||||
|
|
||||||
from ansible_collections.community.general.plugins.module_utils.gitlab import (
|
from ansible_collections.community.general.plugins.module_utils.gitlab import (
|
||||||
auth_argument_spec, find_project, gitlab_authentication, gitlab, ensure_gitlab_package
|
auth_argument_spec, find_project, gitlab_authentication, gitlab, ensure_gitlab_package, list_all_kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -209,8 +209,7 @@ class GitLabDeployKey(object):
|
|||||||
@param key_title Title of the key
|
@param key_title Title of the key
|
||||||
'''
|
'''
|
||||||
def find_deploy_key(self, project, key_title):
|
def find_deploy_key(self, project, key_title):
|
||||||
deploy_keys = project.keys.list(all=True)
|
for deploy_key in project.keys.list(**list_all_kwargs):
|
||||||
for deploy_key in deploy_keys:
|
|
||||||
if (deploy_key.title == key_title):
|
if (deploy_key.title == key_title):
|
||||||
return deploy_key
|
return deploy_key
|
||||||
|
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ from ansible.module_utils.api import basic_auth_argument_spec
|
|||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
|
||||||
from ansible_collections.community.general.plugins.module_utils.gitlab import (
|
from ansible_collections.community.general.plugins.module_utils.gitlab import (
|
||||||
auth_argument_spec, gitlab_authentication, gitlab, ensure_gitlab_package
|
auth_argument_spec, gitlab_authentication, gitlab, ensure_gitlab_package, list_all_kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -171,16 +171,20 @@ class GitLabGroup(object):
|
|||||||
|
|
||||||
# get user id if the user exists
|
# get user id if the user exists
|
||||||
def get_user_id(self, gitlab_user):
|
def get_user_id(self, gitlab_user):
|
||||||
user_exists = self._gitlab.users.list(username=gitlab_user, all=True)
|
return next(
|
||||||
if user_exists:
|
(u.id for u in self._gitlab.users.list(username=gitlab_user, **list_all_kwargs)),
|
||||||
return user_exists[0].id
|
None
|
||||||
|
)
|
||||||
|
|
||||||
# get group id if group exists
|
# get group id if group exists
|
||||||
def get_group_id(self, gitlab_group):
|
def get_group_id(self, gitlab_group):
|
||||||
groups = self._gitlab.groups.list(search=gitlab_group, all=True)
|
return next(
|
||||||
for group in groups:
|
(
|
||||||
if group.full_path == gitlab_group:
|
g.id for g in self._gitlab.groups.list(search=gitlab_group, **list_all_kwargs)
|
||||||
return group.id
|
if g.full_path == gitlab_group
|
||||||
|
),
|
||||||
|
None
|
||||||
|
)
|
||||||
|
|
||||||
# get all members in a group
|
# get all members in a group
|
||||||
def get_members_in_a_group(self, gitlab_group_id):
|
def get_members_in_a_group(self, gitlab_group_id):
|
||||||
|
|||||||
@@ -207,7 +207,8 @@ group_variable:
|
|||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible.module_utils.api import basic_auth_argument_spec
|
from ansible.module_utils.api import basic_auth_argument_spec
|
||||||
from ansible_collections.community.general.plugins.module_utils.gitlab import (
|
from ansible_collections.community.general.plugins.module_utils.gitlab import (
|
||||||
auth_argument_spec, gitlab_authentication, ensure_gitlab_package, filter_returned_variables, vars_to_variables
|
auth_argument_spec, gitlab_authentication, ensure_gitlab_package, filter_returned_variables, vars_to_variables,
|
||||||
|
list_all_kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -222,14 +223,7 @@ class GitlabGroupVariables(object):
|
|||||||
return self.repo.groups.get(group_name)
|
return self.repo.groups.get(group_name)
|
||||||
|
|
||||||
def list_all_group_variables(self):
|
def list_all_group_variables(self):
|
||||||
page_nb = 1
|
return list(self.group.variables.list(**list_all_kwargs))
|
||||||
variables = []
|
|
||||||
vars_page = self.group.variables.list(page=page_nb)
|
|
||||||
while len(vars_page) > 0:
|
|
||||||
variables += vars_page
|
|
||||||
page_nb += 1
|
|
||||||
vars_page = self.group.variables.list(page=page_nb)
|
|
||||||
return variables
|
|
||||||
|
|
||||||
def create_variable(self, var_obj):
|
def create_variable(self, var_obj):
|
||||||
if self._module.check_mode:
|
if self._module.check_mode:
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ from ansible.module_utils.api import basic_auth_argument_spec
|
|||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
|
||||||
from ansible_collections.community.general.plugins.module_utils.gitlab import (
|
from ansible_collections.community.general.plugins.module_utils.gitlab import (
|
||||||
auth_argument_spec, find_project, gitlab_authentication, ensure_gitlab_package
|
auth_argument_spec, find_project, gitlab_authentication, ensure_gitlab_package, list_all_kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -266,8 +266,7 @@ class GitLabHook(object):
|
|||||||
@param hook_url Url to call on event
|
@param hook_url Url to call on event
|
||||||
'''
|
'''
|
||||||
def find_hook(self, project, hook_url):
|
def find_hook(self, project, hook_url):
|
||||||
hooks = project.hooks.list(all=True)
|
for hook in project.hooks.list(**list_all_kwargs):
|
||||||
for hook in hooks:
|
|
||||||
if (hook.url == hook_url):
|
if (hook.url == hook_url):
|
||||||
return hook
|
return hook
|
||||||
|
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ instance_variable:
|
|||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible.module_utils.api import basic_auth_argument_spec
|
from ansible.module_utils.api import basic_auth_argument_spec
|
||||||
from ansible_collections.community.general.plugins.module_utils.gitlab import (
|
from ansible_collections.community.general.plugins.module_utils.gitlab import (
|
||||||
auth_argument_spec, gitlab_authentication, ensure_gitlab_package, filter_returned_variables
|
auth_argument_spec, gitlab_authentication, ensure_gitlab_package, filter_returned_variables, list_all_kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -150,14 +150,7 @@ class GitlabInstanceVariables(object):
|
|||||||
self._module = module
|
self._module = module
|
||||||
|
|
||||||
def list_all_instance_variables(self):
|
def list_all_instance_variables(self):
|
||||||
page_nb = 1
|
return list(self.instance.variables.list(**list_all_kwargs))
|
||||||
variables = []
|
|
||||||
gl_varibales_page = self.instance.variables.list(page=page_nb)
|
|
||||||
while len(gl_varibales_page) > 0:
|
|
||||||
variables += gl_varibales_page
|
|
||||||
page_nb += 1
|
|
||||||
gl_varibales_page = self.instance.variables.list(page=page_nb)
|
|
||||||
return variables
|
|
||||||
|
|
||||||
def create_variable(self, var_obj):
|
def create_variable(self, var_obj):
|
||||||
if self._module.check_mode:
|
if self._module.check_mode:
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ from ansible.module_utils.api import basic_auth_argument_spec
|
|||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
|
||||||
from ansible_collections.community.general.plugins.module_utils.gitlab import (
|
from ansible_collections.community.general.plugins.module_utils.gitlab import (
|
||||||
auth_argument_spec, gitlab_authentication, find_project, ensure_gitlab_package
|
auth_argument_spec, gitlab_authentication, find_project, ensure_gitlab_package, list_all_kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ def present_strategy(module, gl, project, wished_badge):
|
|||||||
changed = False
|
changed = False
|
||||||
|
|
||||||
existing_badge = None
|
existing_badge = None
|
||||||
for badge in project.badges.list(iterator=True):
|
for badge in project.badges.list(**list_all_kwargs):
|
||||||
if badge.image_url == wished_badge["image_url"]:
|
if badge.image_url == wished_badge["image_url"]:
|
||||||
existing_badge = badge
|
existing_badge = badge
|
||||||
break
|
break
|
||||||
@@ -135,7 +135,7 @@ def absent_strategy(module, gl, project, wished_badge):
|
|||||||
changed = False
|
changed = False
|
||||||
|
|
||||||
existing_badge = None
|
existing_badge = None
|
||||||
for badge in project.badges.list(iterator=True):
|
for badge in project.badges.list(**list_all_kwargs):
|
||||||
if badge.image_url == wished_badge["image_url"]:
|
if badge.image_url == wished_badge["image_url"]:
|
||||||
existing_badge = badge
|
existing_badge = badge
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ from ansible.module_utils.api import basic_auth_argument_spec
|
|||||||
|
|
||||||
from ansible_collections.community.general.plugins.module_utils.gitlab import (
|
from ansible_collections.community.general.plugins.module_utils.gitlab import (
|
||||||
auth_argument_spec, gitlab_authentication, ensure_gitlab_package, filter_returned_variables, vars_to_variables,
|
auth_argument_spec, gitlab_authentication, ensure_gitlab_package, filter_returned_variables, vars_to_variables,
|
||||||
HAS_GITLAB_PACKAGE, GITLAB_IMP_ERR
|
list_all_kwargs, HAS_GITLAB_PACKAGE, GITLAB_IMP_ERR
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -242,14 +242,7 @@ class GitlabProjectVariables(object):
|
|||||||
return self.repo.projects.get(project_name)
|
return self.repo.projects.get(project_name)
|
||||||
|
|
||||||
def list_all_project_variables(self):
|
def list_all_project_variables(self):
|
||||||
page_nb = 1
|
return list(self.project.variables.list(**list_all_kwargs))
|
||||||
variables = []
|
|
||||||
vars_page = self.project.variables.list(page=page_nb)
|
|
||||||
while len(vars_page) > 0:
|
|
||||||
variables += vars_page
|
|
||||||
page_nb += 1
|
|
||||||
vars_page = self.project.variables.list(page=page_nb)
|
|
||||||
return variables
|
|
||||||
|
|
||||||
def create_variable(self, var_obj):
|
def create_variable(self, var_obj):
|
||||||
if self._module.check_mode:
|
if self._module.check_mode:
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ from ansible.module_utils.basic import AnsibleModule
|
|||||||
from ansible.module_utils.common.text.converters import to_native
|
from ansible.module_utils.common.text.converters import to_native
|
||||||
|
|
||||||
from ansible_collections.community.general.plugins.module_utils.gitlab import (
|
from ansible_collections.community.general.plugins.module_utils.gitlab import (
|
||||||
auth_argument_spec, gitlab_authentication, gitlab, ensure_gitlab_package
|
auth_argument_spec, gitlab_authentication, gitlab, ensure_gitlab_package, list_all_kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -309,7 +309,7 @@ class GitLabRunner(object):
|
|||||||
@param description Description of the runner
|
@param description Description of the runner
|
||||||
'''
|
'''
|
||||||
def find_runner(self, description):
|
def find_runner(self, description):
|
||||||
runners = self._runners_endpoint(as_list=False)
|
runners = self._runners_endpoint(**list_all_kwargs)
|
||||||
|
|
||||||
for runner in runners:
|
for runner in runners:
|
||||||
# python-gitlab 2.2 through at least 2.5 returns a list of dicts for list() instead of a Runner
|
# python-gitlab 2.2 through at least 2.5 returns a list of dicts for list() instead of a Runner
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ from ansible.module_utils.basic import AnsibleModule
|
|||||||
from ansible.module_utils.common.text.converters import to_native
|
from ansible.module_utils.common.text.converters import to_native
|
||||||
|
|
||||||
from ansible_collections.community.general.plugins.module_utils.gitlab import (
|
from ansible_collections.community.general.plugins.module_utils.gitlab import (
|
||||||
auth_argument_spec, find_group, gitlab_authentication, gitlab, ensure_gitlab_package
|
auth_argument_spec, find_group, gitlab_authentication, gitlab, ensure_gitlab_package, list_all_kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -349,9 +349,10 @@ class GitLabUser(object):
|
|||||||
@param sshkey_name Name of the ssh key
|
@param sshkey_name Name of the ssh key
|
||||||
'''
|
'''
|
||||||
def ssh_key_exists(self, user, sshkey_name):
|
def ssh_key_exists(self, user, sshkey_name):
|
||||||
keyList = map(lambda k: k.title, user.keys.list(all=True))
|
return any(
|
||||||
|
k.title == sshkey_name
|
||||||
return sshkey_name in keyList
|
for k in user.keys.list(**list_all_kwargs)
|
||||||
|
)
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@param user User object
|
@param user User object
|
||||||
@@ -519,10 +520,13 @@ class GitLabUser(object):
|
|||||||
@param username Username of the user
|
@param username Username of the user
|
||||||
'''
|
'''
|
||||||
def find_user(self, username):
|
def find_user(self, username):
|
||||||
users = self._gitlab.users.list(search=username, all=True)
|
return next(
|
||||||
for user in users:
|
(
|
||||||
if (user.username == username):
|
user for user in self._gitlab.users.list(search=username, **list_all_kwargs)
|
||||||
return user
|
if user.username == username
|
||||||
|
),
|
||||||
|
None
|
||||||
|
)
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@param username Username of the user
|
@param username Username of the user
|
||||||
|
|||||||
@@ -343,7 +343,7 @@ class HAProxy(object):
|
|||||||
|
|
||||||
if state is not None:
|
if state is not None:
|
||||||
self.execute(Template(cmd).substitute(pxname=backend, svname=svname))
|
self.execute(Template(cmd).substitute(pxname=backend, svname=svname))
|
||||||
if self.wait:
|
if self.wait and not (wait_for_status == "DRAIN" and state == "DOWN"):
|
||||||
self.wait_until_status(backend, svname, wait_for_status)
|
self.wait_until_status(backend, svname, wait_for_status)
|
||||||
|
|
||||||
def get_state_for(self, pxname, svname):
|
def get_state_for(self, pxname, svname):
|
||||||
|
|||||||
@@ -488,6 +488,10 @@ class Homebrew(object):
|
|||||||
self.current_package,
|
self.current_package,
|
||||||
]
|
]
|
||||||
rc, out, err = self.module.run_command(cmd)
|
rc, out, err = self.module.run_command(cmd)
|
||||||
|
if err:
|
||||||
|
self.failed = True
|
||||||
|
self.message = err.strip()
|
||||||
|
raise HomebrewException(self.message)
|
||||||
data = json.loads(out)
|
data = json.loads(out)
|
||||||
|
|
||||||
return _check_package_in_json(data, "formulae") or _check_package_in_json(data, "casks")
|
return _check_package_in_json(data, "formulae") or _check_package_in_json(data, "casks")
|
||||||
|
|||||||
@@ -70,7 +70,8 @@ options:
|
|||||||
does not exist it will fail.
|
does not exist it will fail.
|
||||||
notes:
|
notes:
|
||||||
- "This module depends on the C(passlib) Python library, which needs to be installed on all target systems."
|
- "This module depends on the C(passlib) Python library, which needs to be installed on all target systems."
|
||||||
- "On Debian, Ubuntu, or Fedora: install C(python-passlib)."
|
- "On Debian < 11, Ubuntu <= 20.04, or Fedora: install C(python-passlib)."
|
||||||
|
- "On Debian, Ubuntu: install C(python3-passlib)."
|
||||||
- "On RHEL or CentOS: Enable EPEL, then install C(python-passlib)."
|
- "On RHEL or CentOS: Enable EPEL, then install C(python-passlib)."
|
||||||
requirements: [ passlib>=1.6 ]
|
requirements: [ passlib>=1.6 ]
|
||||||
author: "Ansible Core Team"
|
author: "Ansible Core Team"
|
||||||
|
|||||||
@@ -450,7 +450,7 @@ def do_ini(module, filename, section=None, option=None, values=None,
|
|||||||
module.fail_json(msg="Unable to create temporary file %s", traceback=traceback.format_exc())
|
module.fail_json(msg="Unable to create temporary file %s", traceback=traceback.format_exc())
|
||||||
|
|
||||||
try:
|
try:
|
||||||
module.atomic_move(tmpfile, target_filename)
|
module.atomic_move(tmpfile, os.path.abspath(target_filename))
|
||||||
except IOError:
|
except IOError:
|
||||||
module.ansible.fail_json(msg='Unable to move temporary \
|
module.ansible.fail_json(msg='Unable to move temporary \
|
||||||
file %s to %s, IOError' % (tmpfile, target_filename), traceback=traceback.format_exc())
|
file %s to %s, IOError' % (tmpfile, target_filename), traceback=traceback.format_exc())
|
||||||
|
|||||||
@@ -161,6 +161,7 @@ import traceback
|
|||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible_collections.community.general.plugins.module_utils.ipa import IPAClient, ipa_argument_spec
|
from ansible_collections.community.general.plugins.module_utils.ipa import IPAClient, ipa_argument_spec
|
||||||
from ansible.module_utils.common.text.converters import to_native
|
from ansible.module_utils.common.text.converters import to_native
|
||||||
|
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
|
||||||
|
|
||||||
|
|
||||||
class HBACRuleIPAClient(IPAClient):
|
class HBACRuleIPAClient(IPAClient):
|
||||||
@@ -231,10 +232,17 @@ def ensure(module, client):
|
|||||||
name = module.params['cn']
|
name = module.params['cn']
|
||||||
state = module.params['state']
|
state = module.params['state']
|
||||||
|
|
||||||
|
ipa_version = client.get_ipa_version()
|
||||||
if state in ['present', 'enabled']:
|
if state in ['present', 'enabled']:
|
||||||
ipaenabledflag = 'TRUE'
|
if LooseVersion(ipa_version) < LooseVersion('4.9.10'):
|
||||||
|
ipaenabledflag = 'TRUE'
|
||||||
|
else:
|
||||||
|
ipaenabledflag = True
|
||||||
else:
|
else:
|
||||||
ipaenabledflag = 'FALSE'
|
if LooseVersion(ipa_version) < LooseVersion('4.9.10'):
|
||||||
|
ipaenabledflag = 'FALSE'
|
||||||
|
else:
|
||||||
|
ipaenabledflag = False
|
||||||
|
|
||||||
host = module.params['host']
|
host = module.params['host']
|
||||||
hostcategory = module.params['hostcategory']
|
hostcategory = module.params['hostcategory']
|
||||||
|
|||||||
@@ -57,13 +57,14 @@ options:
|
|||||||
state:
|
state:
|
||||||
description:
|
description:
|
||||||
- State to ensure.
|
- State to ensure.
|
||||||
|
- V("absent") and V("disabled") give the same results.
|
||||||
|
- V("present") and V("enabled") give the same results.
|
||||||
default: "present"
|
default: "present"
|
||||||
choices: ["absent", "disabled", "enabled", "present"]
|
choices: ["absent", "disabled", "enabled", "present"]
|
||||||
type: str
|
type: str
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- community.general.ipa.documentation
|
- community.general.ipa.documentation
|
||||||
- community.general.attributes
|
- community.general.attributes
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
EXAMPLES = r'''
|
EXAMPLES = r'''
|
||||||
@@ -160,7 +161,7 @@ def ensure(module, client):
|
|||||||
module_hostgroup = get_hostgroup_dict(description=module.params['description'])
|
module_hostgroup = get_hostgroup_dict(description=module.params['description'])
|
||||||
|
|
||||||
changed = False
|
changed = False
|
||||||
if state == 'present':
|
if state in ['present', 'enabled']:
|
||||||
if not ipa_hostgroup:
|
if not ipa_hostgroup:
|
||||||
changed = True
|
changed = True
|
||||||
if not module.check_mode:
|
if not module.check_mode:
|
||||||
|
|||||||
@@ -186,6 +186,7 @@ import traceback
|
|||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible_collections.community.general.plugins.module_utils.ipa import IPAClient, ipa_argument_spec
|
from ansible_collections.community.general.plugins.module_utils.ipa import IPAClient, ipa_argument_spec
|
||||||
from ansible.module_utils.common.text.converters import to_native
|
from ansible.module_utils.common.text.converters import to_native
|
||||||
|
from ansible_collections.community.general.plugins.module_utils.version import LooseVersion
|
||||||
|
|
||||||
|
|
||||||
class SudoRuleIPAClient(IPAClient):
|
class SudoRuleIPAClient(IPAClient):
|
||||||
@@ -310,10 +311,17 @@ def ensure(module, client):
|
|||||||
runasgroupcategory = module.params['runasgroupcategory']
|
runasgroupcategory = module.params['runasgroupcategory']
|
||||||
runasextusers = module.params['runasextusers']
|
runasextusers = module.params['runasextusers']
|
||||||
|
|
||||||
|
ipa_version = client.get_ipa_version()
|
||||||
if state in ['present', 'enabled']:
|
if state in ['present', 'enabled']:
|
||||||
ipaenabledflag = 'TRUE'
|
if LooseVersion(ipa_version) < LooseVersion('4.9.10'):
|
||||||
|
ipaenabledflag = 'TRUE'
|
||||||
|
else:
|
||||||
|
ipaenabledflag = True
|
||||||
else:
|
else:
|
||||||
ipaenabledflag = 'FALSE'
|
if LooseVersion(ipa_version) < LooseVersion('4.9.10'):
|
||||||
|
ipaenabledflag = 'FALSE'
|
||||||
|
else:
|
||||||
|
ipaenabledflag = False
|
||||||
|
|
||||||
sudoopt = module.params['sudoopt']
|
sudoopt = module.params['sudoopt']
|
||||||
user = module.params['user']
|
user = module.params['user']
|
||||||
|
|||||||
@@ -207,7 +207,9 @@ saved:
|
|||||||
"# Completed"
|
"# Completed"
|
||||||
]
|
]
|
||||||
tables:
|
tables:
|
||||||
description: The iptables we have interest for when module starts.
|
description:
|
||||||
|
- The iptables on the system before the module has run, separated by table.
|
||||||
|
- If the option O(table) is used, only this table is included.
|
||||||
type: dict
|
type: dict
|
||||||
contains:
|
contains:
|
||||||
table:
|
table:
|
||||||
@@ -346,20 +348,27 @@ def filter_and_format_state(string):
|
|||||||
return lines
|
return lines
|
||||||
|
|
||||||
|
|
||||||
def per_table_state(command, state):
|
def parse_per_table_state(all_states_dump):
|
||||||
'''
|
'''
|
||||||
Convert raw iptables-save output into usable datastructure, for reliable
|
Convert raw iptables-save output into usable datastructure, for reliable
|
||||||
comparisons between initial and final states.
|
comparisons between initial and final states.
|
||||||
'''
|
'''
|
||||||
|
lines = filter_and_format_state(all_states_dump)
|
||||||
tables = dict()
|
tables = dict()
|
||||||
for t in TABLES:
|
current_table = ''
|
||||||
COMMAND = list(command)
|
current_list = list()
|
||||||
if '*%s' % t in state.splitlines():
|
for line in lines:
|
||||||
COMMAND.extend(['--table', t])
|
if re.match(r'^[*](filter|mangle|nat|raw|security)$', line):
|
||||||
dummy, out, dummy = module.run_command(COMMAND, check_rc=True)
|
current_table = line[1:]
|
||||||
out = re.sub(r'(^|\n)(# Generated|# Completed|[*]%s|COMMIT)[^\n]*' % t, r'', out)
|
continue
|
||||||
out = re.sub(r' *\[[0-9]+:[0-9]+\] *', r'', out)
|
if line == 'COMMIT':
|
||||||
tables[t] = [tt for tt in out.splitlines() if tt != '']
|
tables[current_table] = current_list
|
||||||
|
current_table = ''
|
||||||
|
current_list = list()
|
||||||
|
continue
|
||||||
|
if line.startswith('# '):
|
||||||
|
continue
|
||||||
|
current_list.append(line)
|
||||||
return tables
|
return tables
|
||||||
|
|
||||||
|
|
||||||
@@ -486,7 +495,7 @@ def main():
|
|||||||
# Depending on the value of 'table', initref_state may differ from
|
# Depending on the value of 'table', initref_state may differ from
|
||||||
# initial_state.
|
# initial_state.
|
||||||
(rc, stdout, stderr) = module.run_command(SAVECOMMAND, check_rc=True)
|
(rc, stdout, stderr) = module.run_command(SAVECOMMAND, check_rc=True)
|
||||||
tables_before = per_table_state(SAVECOMMAND, stdout)
|
tables_before = parse_per_table_state(stdout)
|
||||||
initref_state = filter_and_format_state(stdout)
|
initref_state = filter_and_format_state(stdout)
|
||||||
|
|
||||||
if state == 'saved':
|
if state == 'saved':
|
||||||
@@ -583,14 +592,17 @@ def main():
|
|||||||
|
|
||||||
(rc, stdout, stderr) = module.run_command(SAVECOMMAND, check_rc=True)
|
(rc, stdout, stderr) = module.run_command(SAVECOMMAND, check_rc=True)
|
||||||
restored_state = filter_and_format_state(stdout)
|
restored_state = filter_and_format_state(stdout)
|
||||||
|
tables_after = parse_per_table_state('\n'.join(restored_state))
|
||||||
if restored_state not in (initref_state, initial_state):
|
if restored_state not in (initref_state, initial_state):
|
||||||
if module.check_mode:
|
for table_name, table_content in tables_after.items():
|
||||||
changed = True
|
if table_name not in tables_before:
|
||||||
else:
|
# Would initialize a table, which doesn't exist yet
|
||||||
tables_after = per_table_state(SAVECOMMAND, stdout)
|
|
||||||
if tables_after != tables_before:
|
|
||||||
changed = True
|
changed = True
|
||||||
|
break
|
||||||
|
if tables_before[table_name] != table_content:
|
||||||
|
# Content of some table changes
|
||||||
|
changed = True
|
||||||
|
break
|
||||||
|
|
||||||
if _back is None or module.check_mode:
|
if _back is None or module.check_mode:
|
||||||
module.exit_json(
|
module.exit_json(
|
||||||
@@ -633,7 +645,7 @@ def main():
|
|||||||
os.remove(b_back)
|
os.remove(b_back)
|
||||||
|
|
||||||
(rc, stdout, stderr) = module.run_command(SAVECOMMAND, check_rc=True)
|
(rc, stdout, stderr) = module.run_command(SAVECOMMAND, check_rc=True)
|
||||||
tables_rollback = per_table_state(SAVECOMMAND, stdout)
|
tables_rollback = parse_per_table_state(stdout)
|
||||||
|
|
||||||
msg = (
|
msg = (
|
||||||
"Failed to confirm state restored from %s after %ss. "
|
"Failed to confirm state restored from %s after %ss. "
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ options:
|
|||||||
type: str
|
type: str
|
||||||
required: true
|
required: true
|
||||||
notes:
|
notes:
|
||||||
- The C(pycdlib) library states it supports Python 2.7 and 3.4 only.
|
- The C(pycdlib) library states it supports Python 2.7 and 3.4+.
|
||||||
- >
|
- >
|
||||||
The function C(add_file) in pycdlib will overwrite the existing file in ISO with type ISO9660 / Rock Ridge 1.12 / Joliet / UDF.
|
The function C(add_file) in pycdlib will overwrite the existing file in ISO with type ISO9660 / Rock Ridge 1.12 / Joliet / UDF.
|
||||||
But it will not overwrite the existing file in ISO with Rock Ridge 1.09 / 1.10.
|
But it will not overwrite the existing file in ISO with Rock Ridge 1.09 / 1.10.
|
||||||
|
|||||||
@@ -150,13 +150,11 @@ EXAMPLES = '''
|
|||||||
name: example
|
name: example
|
||||||
certificate: |
|
certificate: |
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
h19dUZ2co2fI/ibYiwxWk4aeNE6KWvCaTQOMQ8t6Uo2XKhpL/xnjoAgh1uCQN/69
|
h19dUZ2co2f...
|
||||||
MG+34+RhUWzCfdZH7T8/qDxJw2kEPKluaYh7KnMsba+5jHjmtzix5QIDAQABo4IB
|
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
private_key: |
|
private_key: |
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
DBVFTEVDVFJJQ0lURSBERSBGUkFOQ0UxFzAVBgNVBAsMDjAwMDIgNTUyMDgxMzE3
|
DBVFTEVDVFJ...
|
||||||
GLlDNMw/uHyME7gHFsqJA7O11VY6O5WQ4IDP3m/s5ZV6s+Nn6Lerz17VZ99
|
|
||||||
-----END RSA PRIVATE KEY-----
|
-----END RSA PRIVATE KEY-----
|
||||||
password: changeit
|
password: changeit
|
||||||
dest: /etc/security/keystore.jks
|
dest: /etc/security/keystore.jks
|
||||||
@@ -472,7 +470,7 @@ class JavaKeystore:
|
|||||||
|
|
||||||
if self.keystore_type == 'pkcs12':
|
if self.keystore_type == 'pkcs12':
|
||||||
# Preserve properties of the destination file, if any.
|
# Preserve properties of the destination file, if any.
|
||||||
self.module.atomic_move(keystore_p12_path, self.keystore_path)
|
self.module.atomic_move(os.path.abspath(keystore_p12_path), os.path.abspath(self.keystore_path))
|
||||||
self.update_permissions()
|
self.update_permissions()
|
||||||
self.result['changed'] = True
|
self.result['changed'] = True
|
||||||
return self.result
|
return self.result
|
||||||
|
|||||||
@@ -685,7 +685,7 @@ class JenkinsPlugin(object):
|
|||||||
|
|
||||||
# Move the updates file to the right place if we could read it
|
# Move the updates file to the right place if we could read it
|
||||||
if tmp_updates_file != updates_file:
|
if tmp_updates_file != updates_file:
|
||||||
self.module.atomic_move(tmp_updates_file, updates_file)
|
self.module.atomic_move(os.path.abspath(tmp_updates_file), os.path.abspath(updates_file))
|
||||||
|
|
||||||
# Check if we have the plugin data available
|
# Check if we have the plugin data available
|
||||||
if not data.get('plugins', {}).get(self.params['name']):
|
if not data.get('plugins', {}).get(self.params['name']):
|
||||||
@@ -718,7 +718,7 @@ class JenkinsPlugin(object):
|
|||||||
details=to_native(e))
|
details=to_native(e))
|
||||||
|
|
||||||
# Move the file onto the right place
|
# Move the file onto the right place
|
||||||
self.module.atomic_move(tmp_f, f)
|
self.module.atomic_move(os.path.abspath(tmp_f), os.path.abspath(f))
|
||||||
|
|
||||||
def uninstall(self):
|
def uninstall(self):
|
||||||
changed = False
|
changed = False
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ def run_module(module, tmpdir, kwriteconfig):
|
|||||||
if module.params['backup'] and os.path.exists(b_path):
|
if module.params['backup'] and os.path.exists(b_path):
|
||||||
result['backup_file'] = module.backup_local(result['path'])
|
result['backup_file'] = module.backup_local(result['path'])
|
||||||
try:
|
try:
|
||||||
module.atomic_move(b_tmpfile, b_path)
|
module.atomic_move(b_tmpfile, os.path.abspath(b_path))
|
||||||
except IOError:
|
except IOError:
|
||||||
module.ansible.fail_json(msg='Unable to move temporary file %s to %s, IOError' % (tmpfile, result['path']), traceback=traceback.format_exc())
|
module.ansible.fail_json(msg='Unable to move temporary file %s to %s, IOError' % (tmpfile, result['path']), traceback=traceback.format_exc())
|
||||||
|
|
||||||
|
|||||||
@@ -717,13 +717,14 @@ end_state:
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
from ansible_collections.community.general.plugins.module_utils.identity.keycloak.keycloak import KeycloakAPI, camel, \
|
from ansible_collections.community.general.plugins.module_utils.identity.keycloak.keycloak import KeycloakAPI, camel, \
|
||||||
keycloak_argument_spec, get_token, KeycloakError
|
keycloak_argument_spec, get_token, KeycloakError, is_struct_included
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
|
|
||||||
PROTOCOL_OPENID_CONNECT = 'openid-connect'
|
PROTOCOL_OPENID_CONNECT = 'openid-connect'
|
||||||
PROTOCOL_SAML = 'saml'
|
PROTOCOL_SAML = 'saml'
|
||||||
|
CLIENT_META_DATA = ['authorizationServicesEnabled']
|
||||||
|
|
||||||
|
|
||||||
def normalise_cr(clientrep, remove_ids=False):
|
def normalise_cr(clientrep, remove_ids=False):
|
||||||
@@ -741,6 +742,12 @@ def normalise_cr(clientrep, remove_ids=False):
|
|||||||
if 'attributes' in clientrep:
|
if 'attributes' in clientrep:
|
||||||
clientrep['attributes'] = list(sorted(clientrep['attributes']))
|
clientrep['attributes'] = list(sorted(clientrep['attributes']))
|
||||||
|
|
||||||
|
if 'defaultClientScopes' in clientrep:
|
||||||
|
clientrep['defaultClientScopes'] = list(sorted(clientrep['defaultClientScopes']))
|
||||||
|
|
||||||
|
if 'optionalClientScopes' in clientrep:
|
||||||
|
clientrep['optionalClientScopes'] = list(sorted(clientrep['optionalClientScopes']))
|
||||||
|
|
||||||
if 'redirectUris' in clientrep:
|
if 'redirectUris' in clientrep:
|
||||||
clientrep['redirectUris'] = list(sorted(clientrep['redirectUris']))
|
clientrep['redirectUris'] = list(sorted(clientrep['redirectUris']))
|
||||||
|
|
||||||
@@ -946,7 +953,7 @@ def main():
|
|||||||
if module._diff:
|
if module._diff:
|
||||||
result['diff'] = dict(before=sanitize_cr(before_norm),
|
result['diff'] = dict(before=sanitize_cr(before_norm),
|
||||||
after=sanitize_cr(desired_norm))
|
after=sanitize_cr(desired_norm))
|
||||||
result['changed'] = (before_norm != desired_norm)
|
result['changed'] = not is_struct_included(desired_norm, before_norm, CLIENT_META_DATA)
|
||||||
|
|
||||||
module.exit_json(**result)
|
module.exit_json(**result)
|
||||||
|
|
||||||
|
|||||||
@@ -437,7 +437,7 @@ def sanitize(idp):
|
|||||||
idpcopy = deepcopy(idp)
|
idpcopy = deepcopy(idp)
|
||||||
if 'config' in idpcopy:
|
if 'config' in idpcopy:
|
||||||
if 'clientSecret' in idpcopy['config']:
|
if 'clientSecret' in idpcopy['config']:
|
||||||
idpcopy['clientSecret'] = '**********'
|
idpcopy['config']['clientSecret'] = '**********'
|
||||||
return idpcopy
|
return idpcopy
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -582,6 +582,27 @@ from ansible_collections.community.general.plugins.module_utils.identity.keycloa
|
|||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
|
||||||
|
|
||||||
|
def normalise_cr(realmrep):
|
||||||
|
""" Re-sorts any properties where the order is important so that diff's is minimised and the change detection is more effective.
|
||||||
|
|
||||||
|
:param realmrep: the realmrep dict to be sanitized
|
||||||
|
:return: normalised realmrep dict
|
||||||
|
"""
|
||||||
|
# Avoid the dict passed in to be modified
|
||||||
|
realmrep = realmrep.copy()
|
||||||
|
|
||||||
|
if 'enabledEventTypes' in realmrep:
|
||||||
|
realmrep['enabledEventTypes'] = list(sorted(realmrep['enabledEventTypes']))
|
||||||
|
|
||||||
|
if 'otpSupportedApplications' in realmrep:
|
||||||
|
realmrep['otpSupportedApplications'] = list(sorted(realmrep['otpSupportedApplications']))
|
||||||
|
|
||||||
|
if 'supportedLocales' in realmrep:
|
||||||
|
realmrep['supportedLocales'] = list(sorted(realmrep['supportedLocales']))
|
||||||
|
|
||||||
|
return realmrep
|
||||||
|
|
||||||
|
|
||||||
def sanitize_cr(realmrep):
|
def sanitize_cr(realmrep):
|
||||||
""" Removes probably sensitive details from a realm representation.
|
""" Removes probably sensitive details from a realm representation.
|
||||||
|
|
||||||
@@ -595,7 +616,7 @@ def sanitize_cr(realmrep):
|
|||||||
if 'saml.signing.private.key' in result['attributes']:
|
if 'saml.signing.private.key' in result['attributes']:
|
||||||
result['attributes'] = result['attributes'].copy()
|
result['attributes'] = result['attributes'].copy()
|
||||||
result['attributes']['saml.signing.private.key'] = '********'
|
result['attributes']['saml.signing.private.key'] = '********'
|
||||||
return result
|
return normalise_cr(result)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -777,9 +798,11 @@ def main():
|
|||||||
result['changed'] = True
|
result['changed'] = True
|
||||||
if module.check_mode:
|
if module.check_mode:
|
||||||
# We can only compare the current realm with the proposed updates we have
|
# We can only compare the current realm with the proposed updates we have
|
||||||
|
before_norm = normalise_cr(before_realm)
|
||||||
|
desired_norm = normalise_cr(desired_realm)
|
||||||
if module._diff:
|
if module._diff:
|
||||||
result['diff'] = dict(before=before_realm_sanitized,
|
result['diff'] = dict(before=sanitize_cr(before_norm),
|
||||||
after=sanitize_cr(desired_realm))
|
after=sanitize_cr(desired_norm))
|
||||||
result['changed'] = (before_realm != desired_realm)
|
result['changed'] = (before_realm != desired_realm)
|
||||||
|
|
||||||
module.exit_json(**result)
|
module.exit_json(**result)
|
||||||
|
|||||||
@@ -712,6 +712,9 @@ def sanitize(comp):
|
|||||||
compcopy['config'] = dict((k, v[0]) for k, v in compcopy['config'].items())
|
compcopy['config'] = dict((k, v[0]) for k, v in compcopy['config'].items())
|
||||||
if 'bindCredential' in compcopy['config']:
|
if 'bindCredential' in compcopy['config']:
|
||||||
compcopy['config']['bindCredential'] = '**********'
|
compcopy['config']['bindCredential'] = '**********'
|
||||||
|
# an empty string is valid for krbPrincipalAttribute but is filtered out in diff
|
||||||
|
if 'krbPrincipalAttribute' not in compcopy['config']:
|
||||||
|
compcopy['config']['krbPrincipalAttribute'] = ''
|
||||||
if 'mappers' in compcopy:
|
if 'mappers' in compcopy:
|
||||||
for mapper in compcopy['mappers']:
|
for mapper in compcopy['mappers']:
|
||||||
if 'config' in mapper:
|
if 'config' in mapper:
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ options:
|
|||||||
type: str
|
type: str
|
||||||
description:
|
description:
|
||||||
- The LDAP scope to use.
|
- The LDAP scope to use.
|
||||||
|
- V(subordinate) requires the LDAPv3 subordinate feature extension.
|
||||||
|
- V(children) is equivalent to a "subtree" scope.
|
||||||
filter:
|
filter:
|
||||||
default: '(objectClass=*)'
|
default: '(objectClass=*)'
|
||||||
type: str
|
type: str
|
||||||
|
|||||||
@@ -86,8 +86,8 @@ options:
|
|||||||
source:
|
source:
|
||||||
description:
|
description:
|
||||||
- 'The source for the instance
|
- 'The source for the instance
|
||||||
(for example V({ "type": "image", "mode": "pull", "server": "https://images.linuxcontainers.org",
|
(for example V({ "type": "image", "mode": "pull", "server": "https://cloud-images.ubuntu.com/releases/",
|
||||||
"protocol": "lxd", "alias": "ubuntu/xenial/amd64" })).'
|
"protocol": "simplestreams", "alias": "22.04" })).'
|
||||||
- 'See U(https://documentation.ubuntu.com/lxd/en/latest/api/) for complete API documentation.'
|
- 'See U(https://documentation.ubuntu.com/lxd/en/latest/api/) for complete API documentation.'
|
||||||
- 'Note that C(protocol) accepts two choices: V(lxd) or V(simplestreams).'
|
- 'Note that C(protocol) accepts two choices: V(lxd) or V(simplestreams).'
|
||||||
required: false
|
required: false
|
||||||
@@ -205,6 +205,9 @@ notes:
|
|||||||
- You can copy a file in the created instance to the localhost
|
- You can copy a file in the created instance to the localhost
|
||||||
with C(command=lxc file pull instance_name/dir/filename filename).
|
with C(command=lxc file pull instance_name/dir/filename filename).
|
||||||
See the first example below.
|
See the first example below.
|
||||||
|
- linuxcontainers.org has phased out LXC/LXD support with March 2024
|
||||||
|
(U(https://discuss.linuxcontainers.org/t/important-notice-for-lxd-users-image-server/18479)).
|
||||||
|
Currently only Ubuntu is still providing images.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
EXAMPLES = '''
|
EXAMPLES = '''
|
||||||
@@ -220,9 +223,9 @@ EXAMPLES = '''
|
|||||||
source:
|
source:
|
||||||
type: image
|
type: image
|
||||||
mode: pull
|
mode: pull
|
||||||
server: https://images.linuxcontainers.org
|
server: https://cloud-images.ubuntu.com/releases/
|
||||||
protocol: lxd # if you get a 404, try setting protocol: simplestreams
|
protocol: simplestreams
|
||||||
alias: ubuntu/xenial/amd64
|
alias: "22.04"
|
||||||
profiles: ["default"]
|
profiles: ["default"]
|
||||||
wait_for_ipv4_addresses: true
|
wait_for_ipv4_addresses: true
|
||||||
timeout: 600
|
timeout: 600
|
||||||
@@ -264,6 +267,26 @@ EXAMPLES = '''
|
|||||||
wait_for_ipv4_addresses: true
|
wait_for_ipv4_addresses: true
|
||||||
timeout: 600
|
timeout: 600
|
||||||
|
|
||||||
|
# An example of creating a ubuntu-minial container
|
||||||
|
- hosts: localhost
|
||||||
|
connection: local
|
||||||
|
tasks:
|
||||||
|
- name: Create a started container
|
||||||
|
community.general.lxd_container:
|
||||||
|
name: mycontainer
|
||||||
|
ignore_volatile_options: true
|
||||||
|
state: started
|
||||||
|
source:
|
||||||
|
type: image
|
||||||
|
mode: pull
|
||||||
|
# Provides Ubuntu minimal images
|
||||||
|
server: https://cloud-images.ubuntu.com/minimal/releases/
|
||||||
|
protocol: simplestreams
|
||||||
|
alias: "22.04"
|
||||||
|
profiles: ["default"]
|
||||||
|
wait_for_ipv4_addresses: true
|
||||||
|
timeout: 600
|
||||||
|
|
||||||
# An example for creating container in project other than default
|
# An example for creating container in project other than default
|
||||||
- hosts: localhost
|
- hosts: localhost
|
||||||
connection: local
|
connection: local
|
||||||
@@ -278,8 +301,8 @@ EXAMPLES = '''
|
|||||||
protocol: simplestreams
|
protocol: simplestreams
|
||||||
type: image
|
type: image
|
||||||
mode: pull
|
mode: pull
|
||||||
server: https://images.linuxcontainers.org
|
server: https://cloud-images.ubuntu.com/releases/
|
||||||
alias: ubuntu/20.04/cloud
|
alias: "22.04"
|
||||||
profiles: ["default"]
|
profiles: ["default"]
|
||||||
wait_for_ipv4_addresses: true
|
wait_for_ipv4_addresses: true
|
||||||
timeout: 600
|
timeout: 600
|
||||||
@@ -347,7 +370,7 @@ EXAMPLES = '''
|
|||||||
source:
|
source:
|
||||||
type: image
|
type: image
|
||||||
mode: pull
|
mode: pull
|
||||||
alias: ubuntu/xenial/amd64
|
alias: "22.04"
|
||||||
target: node01
|
target: node01
|
||||||
|
|
||||||
- name: Create container on another node
|
- name: Create container on another node
|
||||||
@@ -358,7 +381,7 @@ EXAMPLES = '''
|
|||||||
source:
|
source:
|
||||||
type: image
|
type: image
|
||||||
mode: pull
|
mode: pull
|
||||||
alias: ubuntu/xenial/amd64
|
alias: "22.04"
|
||||||
target: node02
|
target: node02
|
||||||
|
|
||||||
# An example for creating a virtual machine
|
# An example for creating a virtual machine
|
||||||
|
|||||||
@@ -207,22 +207,7 @@ EXAMPLES = '''
|
|||||||
security_protocol: 'ssl-with-validation-custom-ca'
|
security_protocol: 'ssl-with-validation-custom-ca'
|
||||||
certificate_authority: |
|
certificate_authority: |
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
FAKECERTsdKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDDBtvcGVu
|
FAKECERTsdKgAwI...
|
||||||
c2hpZnQtc2lnbmVyQDE1MDMzMjAxMTkwHhcNMTcwODIxMTI1NTE5WhcNMjIwODIw
|
|
||||||
MTI1NTIwWjAmMSQwIgYDVQQDDBtvcGVuc2hpZnQtc2lnbmVyQDE1MDMzMjAxMTkw
|
|
||||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDUDnL2tQ2xf/zO7F7hmZ4S
|
|
||||||
ZuwKENdI4IYuWSxye4i3hPhKg6eKPzGzmDNWkIMDOrDAj1EgVSNPtPwsOL8OWvJm
|
|
||||||
AaTjr070D7ZGWWnrrDrWEClBx9Rx/6JAM38RT8Pu7c1hXBm0J81KufSLLYiZ/gOw
|
|
||||||
Znks5v5RUSGcAXvLkBJeATbsbh6fKX0RgQ3fFTvqQaE/r8LxcTN1uehPX1g5AaRa
|
|
||||||
z/SNDHaFtQlE3XcqAAukyMn4N5kdNcuwF3GlQ+tJnJv8SstPkfQcZbTMUQ7I2KpJ
|
|
||||||
ajXnMxmBhV5fCN4rb0QUNCrk2/B+EUMBY4MnxIakqNxnN1kvgI7FBbFgrHUe6QvJ
|
|
||||||
AgMBAAGjIzAhMA4GA1UdDwEB/wQEAwICpDAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
|
|
||||||
SIb3DQEBCwUAA4IBAQAYRV57LUsqznSLZHA77o9+0fQetIE115DYP7wea42PODJI
|
|
||||||
QJ+JETEfoCr0+YOMAbVmznP9GH5cMTKEWHExcIpbMBU7nMZp6A3htcJgF2fgPzOA
|
|
||||||
aTUtzkuVCSrV//mbbYVxoFOc6sR3Br0wBs5+5iz3dBSt7xmgpMzZvqsQl655i051
|
|
||||||
gGSTIY3z5EJmBZBjwuTjal9mMoPGA4eoTPqlITJDHQ2bdCV2oDbc7zqupGrUfZFA
|
|
||||||
qzgieEyGzdCSRwjr1/PibA3bpwHyhD9CGD0PRVVTLhw6h6L5kuN1jA20OfzWxf/o
|
|
||||||
XUsdmRaWiF+l4s6Dcd56SuRp5SGNa2+vP9Of/FX5
|
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
metrics:
|
metrics:
|
||||||
auth_key: 'topSecret'
|
auth_key: 'topSecret'
|
||||||
@@ -233,22 +218,7 @@ EXAMPLES = '''
|
|||||||
security_protocol: 'ssl-with-validation-custom-ca'
|
security_protocol: 'ssl-with-validation-custom-ca'
|
||||||
certificate_authority: |
|
certificate_authority: |
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
FAKECERTsdKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDDBtvcGVu
|
FAKECERTsdKgAwI...
|
||||||
c2hpZnQtc2lnbmVyQDE1MDMzMjAxMTkwHhcNMTcwODIxMTI1NTE5WhcNMjIwODIw
|
|
||||||
MTI1NTIwWjAmMSQwIgYDVQQDDBtvcGVuc2hpZnQtc2lnbmVyQDE1MDMzMjAxMTkw
|
|
||||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDUDnL2tQ2xf/zO7F7hmZ4S
|
|
||||||
ZuwKENdI4IYuWSxye4i3hPhKg6eKPzGzmDNWkIMDOrDAj1EgVSNPtPwsOL8OWvJm
|
|
||||||
AaTjr070D7ZGWWnrrDrWEClBx9Rx/6JAM38RT8Pu7c1hXBm0J81KufSLLYiZ/gOw
|
|
||||||
Znks5v5RUSGcAXvLkBJeATbsbh6fKX0RgQ3fFTvqQaE/r8LxcTN1uehPX1g5AaRa
|
|
||||||
z/SNDHaFtQlE3XcqAAukyMn4N5kdNcuwF3GlQ+tJnJv8SstPkfQcZbTMUQ7I2KpJ
|
|
||||||
ajXnMxmBhV5fCN4rb0QUNCrk2/B+EUMBY4MnxIakqNxnN1kvgI7FBbFgrHUe6QvJ
|
|
||||||
AgMBAAGjIzAhMA4GA1UdDwEB/wQEAwICpDAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
|
|
||||||
SIb3DQEBCwUAA4IBAQAYRV57LUsqznSLZHA77o9+0fQetIE115DYP7wea42PODJI
|
|
||||||
QJ+JETEfoCr0+YOMAbVmznP9GH5cMTKEWHExcIpbMBU7nMZp6A3htcJgF2fgPzOA
|
|
||||||
aTUtzkuVCSrV//mbbYVxoFOc6sR3Br0wBs5+5iz3dBSt7xmgpMzZvqsQl655i051
|
|
||||||
gGSTIY3z5EJmBZBjwuTjal9mMoPGA4eoTPqlITJDHQ2bdCV2oDbc7zqupGrUfZFA
|
|
||||||
qzgieEyGzdCSRwjr1/PibA3bpwHyhD9CGD0PRVVTLhw6h6L5kuN1jA20OfzWxf/o
|
|
||||||
XUsdmRaWiF+l4s6Dcd56SuRp5SGNa2+vP9Of/FX5
|
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
manageiq_connection:
|
manageiq_connection:
|
||||||
url: 'https://127.0.0.1:80'
|
url: 'https://127.0.0.1:80'
|
||||||
@@ -270,22 +240,7 @@ EXAMPLES = '''
|
|||||||
security_protocol: 'ssl-with-validation-custom-ca'
|
security_protocol: 'ssl-with-validation-custom-ca'
|
||||||
certificate_authority: |
|
certificate_authority: |
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
FAKECERTsdKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDDBtvcGVu
|
FAKECERTsdKgAwI...
|
||||||
c2hpZnQtc2lnbmVyQDE1MDMzMjAxMTkwHhcNMTcwODIxMTI1NTE5WhcNMjIwODIw
|
|
||||||
MTI1NTIwWjAmMSQwIgYDVQQDDBtvcGVuc2hpZnQtc2lnbmVyQDE1MDMzMjAxMTkw
|
|
||||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDUDnL2tQ2xf/zO7F7hmZ4S
|
|
||||||
ZuwKENdI4IYuWSxye4i3hPhKg6eKPzGzmDNWkIMDOrDAj1EgVSNPtPwsOL8OWvJm
|
|
||||||
AaTjr070D7ZGWWnrrDrWEClBx9Rx/6JAM38RT8Pu7c1hXBm0J81KufSLLYiZ/gOw
|
|
||||||
Znks5v5RUSGcAXvLkBJeATbsbh6fKX0RgQ3fFTvqQaE/r8LxcTN1uehPX1g5AaRa
|
|
||||||
z/SNDHaFtQlE3XcqAAukyMn4N5kdNcuwF3GlQ+tJnJv8SstPkfQcZbTMUQ7I2KpJ
|
|
||||||
ajXnMxmBhV5fCN4rb0QUNCrk2/B+EUMBY4MnxIakqNxnN1kvgI7FBbFgrHUe6QvJ
|
|
||||||
AgMBAAGjIzAhMA4GA1UdDwEB/wQEAwICpDAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
|
|
||||||
SIb3DQEBCwUAA4IBAQAYRV57LUsqznSLZHA77o9+0fQetIE115DYP7wea42PODJI
|
|
||||||
QJ+JETEfoCr0+YOMAbVmznP9GH5cMTKEWHExcIpbMBU7nMZp6A3htcJgF2fgPzOA
|
|
||||||
aTUtzkuVCSrV//mbbYVxoFOc6sR3Br0wBs5+5iz3dBSt7xmgpMzZvqsQl655i051
|
|
||||||
gGSTIY3z5EJmBZBjwuTjal9mMoPGA4eoTPqlITJDHQ2bdCV2oDbc7zqupGrUfZFA
|
|
||||||
qzgieEyGzdCSRwjr1/PibA3bpwHyhD9CGD0PRVVTLhw6h6L5kuN1jA20OfzWxf/o
|
|
||||||
XUsdmRaWiF+l4s6Dcd56SuRp5SGNa2+vP9Of/FX5
|
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
metrics:
|
metrics:
|
||||||
auth_key: 'topSecret'
|
auth_key: 'topSecret'
|
||||||
@@ -295,22 +250,7 @@ EXAMPLES = '''
|
|||||||
security_protocol: 'ssl-with-validation-custom-ca'
|
security_protocol: 'ssl-with-validation-custom-ca'
|
||||||
certificate_authority: |
|
certificate_authority: |
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
FAKECERTsdKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDDBtvcGVu
|
FAKECERTsdKgAwI...
|
||||||
c2hpZnQtc2lnbmVyQDE1MDMzMjAxMTkwHhcNMTcwODIxMTI1NTE5WhcNMjIwODIw
|
|
||||||
MTI1NTIwWjAmMSQwIgYDVQQDDBtvcGVuc2hpZnQtc2lnbmVyQDE1MDMzMjAxMTkw
|
|
||||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDUDnL2tQ2xf/zO7F7hmZ4S
|
|
||||||
ZuwKENdI4IYuWSxye4i3hPhKg6eKPzGzmDNWkIMDOrDAj1EgVSNPtPwsOL8OWvJm
|
|
||||||
AaTjr070D7ZGWWnrrDrWEClBx9Rx/6JAM38RT8Pu7c1hXBm0J81KufSLLYiZ/gOw
|
|
||||||
Znks5v5RUSGcAXvLkBJeATbsbh6fKX0RgQ3fFTvqQaE/r8LxcTN1uehPX1g5AaRa
|
|
||||||
z/SNDHaFtQlE3XcqAAukyMn4N5kdNcuwF3GlQ+tJnJv8SstPkfQcZbTMUQ7I2KpJ
|
|
||||||
ajXnMxmBhV5fCN4rb0QUNCrk2/B+EUMBY4MnxIakqNxnN1kvgI7FBbFgrHUe6QvJ
|
|
||||||
AgMBAAGjIzAhMA4GA1UdDwEB/wQEAwICpDAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
|
|
||||||
SIb3DQEBCwUAA4IBAQAYRV57LUsqznSLZHA77o9+0fQetIE115DYP7wea42PODJI
|
|
||||||
QJ+JETEfoCr0+YOMAbVmznP9GH5cMTKEWHExcIpbMBU7nMZp6A3htcJgF2fgPzOA
|
|
||||||
aTUtzkuVCSrV//mbbYVxoFOc6sR3Br0wBs5+5iz3dBSt7xmgpMzZvqsQl655i051
|
|
||||||
gGSTIY3z5EJmBZBjwuTjal9mMoPGA4eoTPqlITJDHQ2bdCV2oDbc7zqupGrUfZFA
|
|
||||||
qzgieEyGzdCSRwjr1/PibA3bpwHyhD9CGD0PRVVTLhw6h6L5kuN1jA20OfzWxf/o
|
|
||||||
XUsdmRaWiF+l4s6Dcd56SuRp5SGNa2+vP9Of/FX5
|
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
manageiq_connection:
|
manageiq_connection:
|
||||||
url: 'https://127.0.0.1'
|
url: 'https://127.0.0.1'
|
||||||
@@ -358,22 +298,7 @@ EXAMPLES = '''
|
|||||||
validate_certs: true
|
validate_certs: true
|
||||||
certificate_authority: |
|
certificate_authority: |
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
FAKECERTsdKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDDBtvcGVu
|
FAKECERTsdKgAwI...
|
||||||
c2hpZnQtc2lnbmVyQDE1MDMzMjAxMTkwHhcNMTcwODIxMTI1NTE5WhcNMjIwODIw
|
|
||||||
MTI1NTIwWjAmMSQwIgYDVQQDDBtvcGVuc2hpZnQtc2lnbmVyQDE1MDMzMjAxMTkw
|
|
||||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDUDnL2tQ2xf/zO7F7hmZ4S
|
|
||||||
ZuwKENdI4IYuWSxye4i3hPhKg6eKPzGzmDNWkIMDOrDAj1EgVSNPtPwsOL8OWvJm
|
|
||||||
AaTjr070D7ZGWWnrrDrWEClBx9Rx/6JAM38RT8Pu7c1hXBm0J81KufSLLYiZ/gOw
|
|
||||||
Znks5v5RUSGcAXvLkBJeATbsbh6fKX0RgQ3fFTvqQaE/r8LxcTN1uehPX1g5AaRa
|
|
||||||
z/SNDHaFtQlE3XcqAAukyMn4N5kdNcuwF3GlQ+tJnJv8SstPkfQcZbTMUQ7I2KpJ
|
|
||||||
ajXnMxmBhV5fCN4rb0QUNCrk2/B+EUMBY4MnxIakqNxnN1kvgI7FBbFgrHUe6QvJ
|
|
||||||
AgMBAAGjIzAhMA4GA1UdDwEB/wQEAwICpDAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
|
|
||||||
SIb3DQEBCwUAA4IBAQAYRV57LUsqznSLZHA77o9+0fQetIE115DYP7wea42PODJI
|
|
||||||
QJ+JETEfoCr0+YOMAbVmznP9GH5cMTKEWHExcIpbMBU7nMZp6A3htcJgF2fgPzOA
|
|
||||||
aTUtzkuVCSrV//mbbYVxoFOc6sR3Br0wBs5+5iz3dBSt7xmgpMzZvqsQl655i051
|
|
||||||
gGSTIY3z5EJmBZBjwuTjal9mMoPGA4eoTPqlITJDHQ2bdCV2oDbc7zqupGrUfZFA
|
|
||||||
qzgieEyGzdCSRwjr1/PibA3bpwHyhD9CGD0PRVVTLhw6h6L5kuN1jA20OfzWxf/o
|
|
||||||
XUsdmRaWiF+l4s6Dcd56SuRp5SGNa2+vP9Of/FX5
|
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
metrics:
|
metrics:
|
||||||
hostname: 'metrics.example.com'
|
hostname: 'metrics.example.com'
|
||||||
@@ -383,22 +308,7 @@ EXAMPLES = '''
|
|||||||
validate_certs: true
|
validate_certs: true
|
||||||
certificate_authority: |
|
certificate_authority: |
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
FAKECERTsdKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDDBtvcGVu
|
FAKECERTsdKgAwI...
|
||||||
c2hpZnQtc2lnbmVyQDE1MDMzMjAxMTkwHhcNMTcwODIxMTI1NTE5WhcNMjIwODIw
|
|
||||||
MTI1NTIwWjAmMSQwIgYDVQQDDBtvcGVuc2hpZnQtc2lnbmVyQDE1MDMzMjAxMTkw
|
|
||||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDUDnL2tQ2xf/zO7F7hmZ4S
|
|
||||||
ZuwKENdI4IYuWSxye4i3hPhKg6eKPzGzmDNWkIMDOrDAj1EgVSNPtPwsOL8OWvJm
|
|
||||||
AaTjr070D7ZGWWnrrDrWEClBx9Rx/6JAM38RT8Pu7c1hXBm0J81KufSLLYiZ/gOw
|
|
||||||
Znks5v5RUSGcAXvLkBJeATbsbh6fKX0RgQ3fFTvqQaE/r8LxcTN1uehPX1g5AaRa
|
|
||||||
z/SNDHaFtQlE3XcqAAukyMn4N5kdNcuwF3GlQ+tJnJv8SstPkfQcZbTMUQ7I2KpJ
|
|
||||||
ajXnMxmBhV5fCN4rb0QUNCrk2/B+EUMBY4MnxIakqNxnN1kvgI7FBbFgrHUe6QvJ
|
|
||||||
AgMBAAGjIzAhMA4GA1UdDwEB/wQEAwICpDAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
|
|
||||||
SIb3DQEBCwUAA4IBAQAYRV57LUsqznSLZHA77o9+0fQetIE115DYP7wea42PODJI
|
|
||||||
QJ+JETEfoCr0+YOMAbVmznP9GH5cMTKEWHExcIpbMBU7nMZp6A3htcJgF2fgPzOA
|
|
||||||
aTUtzkuVCSrV//mbbYVxoFOc6sR3Br0wBs5+5iz3dBSt7xmgpMzZvqsQl655i051
|
|
||||||
gGSTIY3z5EJmBZBjwuTjal9mMoPGA4eoTPqlITJDHQ2bdCV2oDbc7zqupGrUfZFA
|
|
||||||
qzgieEyGzdCSRwjr1/PibA3bpwHyhD9CGD0PRVVTLhw6h6L5kuN1jA20OfzWxf/o
|
|
||||||
XUsdmRaWiF+l4s6Dcd56SuRp5SGNa2+vP9Of/FX5
|
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
manageiq_connection:
|
manageiq_connection:
|
||||||
url: 'https://127.0.0.1'
|
url: 'https://127.0.0.1'
|
||||||
@@ -454,22 +364,7 @@ EXAMPLES = '''
|
|||||||
validate_certs: 'true'
|
validate_certs: 'true'
|
||||||
certificate_authority: |
|
certificate_authority: |
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
FAKECERTsdKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDDBtvcGVu
|
FAKECERTsdKgAwI...
|
||||||
c2hpZnQtc2lnbmVyQDE1MDMzMjAxMTkwHhcNMTcwODIxMTI1NTE5WhcNMjIwODIw
|
|
||||||
MTI1NTIwWjAmMSQwIgYDVQQDDBtvcGVuc2hpZnQtc2lnbmVyQDE1MDMzMjAxMTkw
|
|
||||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDUDnL2tQ2xf/zO7F7hmZ4S
|
|
||||||
ZuwKENdI4IYuWSxye4i3hPhKg6eKPzGzmDNWkIMDOrDAj1EgVSNPtPwsOL8OWvJm
|
|
||||||
AaTjr070D7ZGWWnrrDrWEClBx9Rx/6JAM38RT8Pu7c1hXBm0J81KufSLLYiZ/gOw
|
|
||||||
Znks5v5RUSGcAXvLkBJeATbsbh6fKX0RgQ3fFTvqQaE/r8LxcTN1uehPX1g5AaRa
|
|
||||||
z/SNDHaFtQlE3XcqAAukyMn4N5kdNcuwF3GlQ+tJnJv8SstPkfQcZbTMUQ7I2KpJ
|
|
||||||
ajXnMxmBhV5fCN4rb0QUNCrk2/B+EUMBY4MnxIakqNxnN1kvgI7FBbFgrHUe6QvJ
|
|
||||||
AgMBAAGjIzAhMA4GA1UdDwEB/wQEAwICpDAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
|
|
||||||
SIb3DQEBCwUAA4IBAQAYRV57LUsqznSLZHA77o9+0fQetIE115DYP7wea42PODJI
|
|
||||||
QJ+JETEfoCr0+YOMAbVmznP9GH5cMTKEWHExcIpbMBU7nMZp6A3htcJgF2fgPzOA
|
|
||||||
aTUtzkuVCSrV//mbbYVxoFOc6sR3Br0wBs5+5iz3dBSt7xmgpMzZvqsQl655i051
|
|
||||||
gGSTIY3z5EJmBZBjwuTjal9mMoPGA4eoTPqlITJDHQ2bdCV2oDbc7zqupGrUfZFA
|
|
||||||
qzgieEyGzdCSRwjr1/PibA3bpwHyhD9CGD0PRVVTLhw6h6L5kuN1jA20OfzWxf/o
|
|
||||||
XUsdmRaWiF+l4s6Dcd56SuRp5SGNa2+vP9Of/FX5
|
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
ssh_keypair:
|
ssh_keypair:
|
||||||
hostname: director.example.com
|
hostname: director.example.com
|
||||||
@@ -493,22 +388,7 @@ EXAMPLES = '''
|
|||||||
validate_certs: 'true'
|
validate_certs: 'true'
|
||||||
certificate_authority: |
|
certificate_authority: |
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
FAKECERTsdKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDDBtvcGVu
|
FAKECERTsdKgAwI...
|
||||||
c2hpZnQtc2lnbmVyQDE1MDMzMjAxMTkwHhcNMTcwODIxMTI1NTE5WhcNMjIwODIw
|
|
||||||
MTI1NTIwWjAmMSQwIgYDVQQDDBtvcGVuc2hpZnQtc2lnbmVyQDE1MDMzMjAxMTkw
|
|
||||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDUDnL2tQ2xf/zO7F7hmZ4S
|
|
||||||
ZuwKENdI4IYuWSxye4i3hPhKg6eKPzGzmDNWkIMDOrDAj1EgVSNPtPwsOL8OWvJm
|
|
||||||
AaTjr070D7ZGWWnrrDrWEClBx9Rx/6JAM38RT8Pu7c1hXBm0J81KufSLLYiZ/gOw
|
|
||||||
Znks5v5RUSGcAXvLkBJeATbsbh6fKX0RgQ3fFTvqQaE/r8LxcTN1uehPX1g5AaRa
|
|
||||||
z/SNDHaFtQlE3XcqAAukyMn4N5kdNcuwF3GlQ+tJnJv8SstPkfQcZbTMUQ7I2KpJ
|
|
||||||
ajXnMxmBhV5fCN4rb0QUNCrk2/B+EUMBY4MnxIakqNxnN1kvgI7FBbFgrHUe6QvJ
|
|
||||||
AgMBAAGjIzAhMA4GA1UdDwEB/wQEAwICpDAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
|
|
||||||
SIb3DQEBCwUAA4IBAQAYRV57LUsqznSLZHA77o9+0fQetIE115DYP7wea42PODJI
|
|
||||||
QJ+JETEfoCr0+YOMAbVmznP9GH5cMTKEWHExcIpbMBU7nMZp6A3htcJgF2fgPzOA
|
|
||||||
aTUtzkuVCSrV//mbbYVxoFOc6sR3Br0wBs5+5iz3dBSt7xmgpMzZvqsQl655i051
|
|
||||||
gGSTIY3z5EJmBZBjwuTjal9mMoPGA4eoTPqlITJDHQ2bdCV2oDbc7zqupGrUfZFA
|
|
||||||
qzgieEyGzdCSRwjr1/PibA3bpwHyhD9CGD0PRVVTLhw6h6L5kuN1jA20OfzWxf/o
|
|
||||||
XUsdmRaWiF+l4s6Dcd56SuRp5SGNa2+vP9Of/FX5
|
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
metrics:
|
metrics:
|
||||||
role: amqp
|
role: amqp
|
||||||
|
|||||||
@@ -163,8 +163,9 @@ class Modprobe(object):
|
|||||||
def create_module_file(self):
|
def create_module_file(self):
|
||||||
file_path = os.path.join(MODULES_LOAD_LOCATION,
|
file_path = os.path.join(MODULES_LOAD_LOCATION,
|
||||||
self.name + '.conf')
|
self.name + '.conf')
|
||||||
with open(file_path, 'w') as file:
|
if not self.check_mode:
|
||||||
file.write(self.name + '\n')
|
with open(file_path, 'w') as file:
|
||||||
|
file.write(self.name + '\n')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def module_options_file_content(self):
|
def module_options_file_content(self):
|
||||||
@@ -175,8 +176,9 @@ class Modprobe(object):
|
|||||||
def create_module_options_file(self):
|
def create_module_options_file(self):
|
||||||
new_file_path = os.path.join(PARAMETERS_FILES_LOCATION,
|
new_file_path = os.path.join(PARAMETERS_FILES_LOCATION,
|
||||||
self.name + '.conf')
|
self.name + '.conf')
|
||||||
with open(new_file_path, 'w') as file:
|
if not self.check_mode:
|
||||||
file.write(self.module_options_file_content)
|
with open(new_file_path, 'w') as file:
|
||||||
|
file.write(self.module_options_file_content)
|
||||||
|
|
||||||
def disable_old_params(self):
|
def disable_old_params(self):
|
||||||
|
|
||||||
@@ -190,7 +192,7 @@ class Modprobe(object):
|
|||||||
file_content[index] = '#' + line
|
file_content[index] = '#' + line
|
||||||
content_changed = True
|
content_changed = True
|
||||||
|
|
||||||
if content_changed:
|
if not self.check_mode and content_changed:
|
||||||
with open(modprobe_file, 'w') as file:
|
with open(modprobe_file, 'w') as file:
|
||||||
file.write('\n'.join(file_content))
|
file.write('\n'.join(file_content))
|
||||||
|
|
||||||
@@ -206,7 +208,7 @@ class Modprobe(object):
|
|||||||
file_content[index] = '#' + line
|
file_content[index] = '#' + line
|
||||||
content_changed = True
|
content_changed = True
|
||||||
|
|
||||||
if content_changed:
|
if not self.check_mode and content_changed:
|
||||||
with open(module_file, 'w') as file:
|
with open(module_file, 'w') as file:
|
||||||
file.write('\n'.join(file_content))
|
file.write('\n'.join(file_content))
|
||||||
|
|
||||||
@@ -232,12 +234,16 @@ class Modprobe(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def modules_files(self):
|
def modules_files(self):
|
||||||
|
if not os.path.isdir(MODULES_LOAD_LOCATION):
|
||||||
|
return []
|
||||||
modules_paths = [os.path.join(MODULES_LOAD_LOCATION, path)
|
modules_paths = [os.path.join(MODULES_LOAD_LOCATION, path)
|
||||||
for path in os.listdir(MODULES_LOAD_LOCATION)]
|
for path in os.listdir(MODULES_LOAD_LOCATION)]
|
||||||
return [path for path in modules_paths if os.path.isfile(path)]
|
return [path for path in modules_paths if os.path.isfile(path)]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def modprobe_files(self):
|
def modprobe_files(self):
|
||||||
|
if not os.path.isdir(PARAMETERS_FILES_LOCATION):
|
||||||
|
return []
|
||||||
modules_paths = [os.path.join(PARAMETERS_FILES_LOCATION, path)
|
modules_paths = [os.path.join(PARAMETERS_FILES_LOCATION, path)
|
||||||
for path in os.listdir(PARAMETERS_FILES_LOCATION)]
|
for path in os.listdir(PARAMETERS_FILES_LOCATION)]
|
||||||
return [path for path in modules_paths if os.path.isfile(path)]
|
return [path for path in modules_paths if os.path.isfile(path)]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2021, Georg Gadinger <nilsding@nilsding.org>
|
# Copyright (c) 2021, Jyrki Gadinger <nilsding@nilsding.org>
|
||||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# 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
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ extends_documentation_fragment:
|
|||||||
- community.general.attributes
|
- community.general.attributes
|
||||||
|
|
||||||
author:
|
author:
|
||||||
- "Georg Gadinger (@nilsding)"
|
- "Jyrki Gadinger (@nilsding)"
|
||||||
'''
|
'''
|
||||||
|
|
||||||
EXAMPLES = '''
|
EXAMPLES = '''
|
||||||
|
|||||||
@@ -188,6 +188,8 @@ def main():
|
|||||||
if cluster_state == state:
|
if cluster_state == state:
|
||||||
module.exit_json(changed=changed, out=cluster_state)
|
module.exit_json(changed=changed, out=cluster_state)
|
||||||
else:
|
else:
|
||||||
|
if module.check_mode:
|
||||||
|
module.exit_json(changed=True)
|
||||||
set_cluster(module, state, timeout, force)
|
set_cluster(module, state, timeout, force)
|
||||||
cluster_state = get_cluster_status(module)
|
cluster_state = get_cluster_status(module)
|
||||||
if cluster_state == state:
|
if cluster_state == state:
|
||||||
@@ -201,12 +203,16 @@ def main():
|
|||||||
if node_state[1].strip().lower() == state:
|
if node_state[1].strip().lower() == state:
|
||||||
module.exit_json(changed=changed, out=cluster_state)
|
module.exit_json(changed=changed, out=cluster_state)
|
||||||
else:
|
else:
|
||||||
|
if module.check_mode:
|
||||||
|
module.exit_json(changed=True)
|
||||||
# Set cluster status if needed
|
# Set cluster status if needed
|
||||||
set_cluster(module, state, timeout, force)
|
set_cluster(module, state, timeout, force)
|
||||||
cluster_state = get_node_status(module, node)
|
cluster_state = get_node_status(module, node)
|
||||||
module.exit_json(changed=True, out=cluster_state)
|
module.exit_json(changed=True, out=cluster_state)
|
||||||
|
|
||||||
if state in ['restart']:
|
if state in ['restart']:
|
||||||
|
if module.check_mode:
|
||||||
|
module.exit_json(changed=True)
|
||||||
set_cluster(module, 'offline', timeout, force)
|
set_cluster(module, 'offline', timeout, force)
|
||||||
cluster_state = get_cluster_status(module)
|
cluster_state = get_cluster_status(module)
|
||||||
if cluster_state == 'offline':
|
if cluster_state == 'offline':
|
||||||
@@ -220,6 +226,8 @@ def main():
|
|||||||
module.fail_json(msg="Failed during the restart of the cluster, the cluster can't be stopped")
|
module.fail_json(msg="Failed during the restart of the cluster, the cluster can't be stopped")
|
||||||
|
|
||||||
if state in ['cleanup']:
|
if state in ['cleanup']:
|
||||||
|
if module.check_mode:
|
||||||
|
module.exit_json(changed=True)
|
||||||
clean_cluster(module, timeout)
|
clean_cluster(module, timeout)
|
||||||
cluster_state = get_cluster_status(module)
|
cluster_state = get_cluster_status(module)
|
||||||
module.exit_json(changed=True,
|
module.exit_json(changed=True,
|
||||||
|
|||||||
@@ -175,7 +175,6 @@ def main():
|
|||||||
limits_conf = '/etc/security/limits.conf'
|
limits_conf = '/etc/security/limits.conf'
|
||||||
|
|
||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
# not checking because of daisy chain to file module
|
|
||||||
argument_spec=dict(
|
argument_spec=dict(
|
||||||
domain=dict(required=True, type='str'),
|
domain=dict(required=True, type='str'),
|
||||||
limit_type=dict(required=True, type='str', choices=pam_types),
|
limit_type=dict(required=True, type='str', choices=pam_types),
|
||||||
@@ -201,6 +200,7 @@ def main():
|
|||||||
new_comment = module.params['comment']
|
new_comment = module.params['comment']
|
||||||
|
|
||||||
changed = False
|
changed = False
|
||||||
|
does_not_exist = False
|
||||||
|
|
||||||
if os.path.isfile(limits_conf):
|
if os.path.isfile(limits_conf):
|
||||||
if not os.access(limits_conf, os.W_OK):
|
if not os.access(limits_conf, os.W_OK):
|
||||||
@@ -208,7 +208,7 @@ def main():
|
|||||||
else:
|
else:
|
||||||
limits_conf_dir = os.path.dirname(limits_conf)
|
limits_conf_dir = os.path.dirname(limits_conf)
|
||||||
if os.path.isdir(limits_conf_dir) and os.access(limits_conf_dir, os.W_OK):
|
if os.path.isdir(limits_conf_dir) and os.access(limits_conf_dir, os.W_OK):
|
||||||
open(limits_conf, 'a').close()
|
does_not_exist = True
|
||||||
changed = True
|
changed = True
|
||||||
else:
|
else:
|
||||||
module.fail_json(msg="directory %s is not writable (check presence, access rights, use sudo)" % limits_conf_dir)
|
module.fail_json(msg="directory %s is not writable (check presence, access rights, use sudo)" % limits_conf_dir)
|
||||||
@@ -224,15 +224,20 @@ def main():
|
|||||||
|
|
||||||
space_pattern = re.compile(r'\s+')
|
space_pattern = re.compile(r'\s+')
|
||||||
|
|
||||||
|
if does_not_exist:
|
||||||
|
lines = []
|
||||||
|
else:
|
||||||
|
with open(limits_conf, 'rb') as f:
|
||||||
|
lines = list(f)
|
||||||
|
|
||||||
message = ''
|
message = ''
|
||||||
f = open(limits_conf, 'rb')
|
|
||||||
# Tempfile
|
# Tempfile
|
||||||
nf = tempfile.NamedTemporaryFile(mode='w+')
|
nf = tempfile.NamedTemporaryFile(mode='w+')
|
||||||
|
|
||||||
found = False
|
found = False
|
||||||
new_value = value
|
new_value = value
|
||||||
|
|
||||||
for line in f:
|
for line in lines:
|
||||||
line = to_native(line, errors='surrogate_or_strict')
|
line = to_native(line, errors='surrogate_or_strict')
|
||||||
if line.startswith('#'):
|
if line.startswith('#'):
|
||||||
nf.write(line)
|
nf.write(line)
|
||||||
@@ -323,18 +328,18 @@ def main():
|
|||||||
message = new_limit
|
message = new_limit
|
||||||
nf.write(new_limit)
|
nf.write(new_limit)
|
||||||
|
|
||||||
f.close()
|
|
||||||
nf.flush()
|
nf.flush()
|
||||||
|
|
||||||
with open(limits_conf, 'r') as content:
|
|
||||||
content_current = content.read()
|
|
||||||
|
|
||||||
with open(nf.name, 'r') as content:
|
with open(nf.name, 'r') as content:
|
||||||
content_new = content.read()
|
content_new = content.read()
|
||||||
|
|
||||||
if not module.check_mode:
|
if not module.check_mode:
|
||||||
# Copy tempfile to newfile
|
if does_not_exist:
|
||||||
module.atomic_move(nf.name, limits_conf)
|
with open(limits_conf, 'a'):
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Move tempfile to newfile
|
||||||
|
module.atomic_move(os.path.abspath(nf.name), os.path.abspath(limits_conf))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
nf.close()
|
nf.close()
|
||||||
@@ -344,7 +349,7 @@ def main():
|
|||||||
res_args = dict(
|
res_args = dict(
|
||||||
changed=changed,
|
changed=changed,
|
||||||
msg=message,
|
msg=message,
|
||||||
diff=dict(before=content_current, after=content_new),
|
diff=dict(before=b''.join(lines), after=content_new),
|
||||||
)
|
)
|
||||||
|
|
||||||
if backup:
|
if backup:
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ options:
|
|||||||
type: list
|
type: list
|
||||||
elements: path
|
elements: path
|
||||||
requirements:
|
requirements:
|
||||||
|
- pip >= 20.3b1 (necessary for the C(--format) option)
|
||||||
- The requested pip executables must be installed on the target.
|
- The requested pip executables must be installed on the target.
|
||||||
author:
|
author:
|
||||||
- Matthew Jones (@matburt)
|
- Matthew Jones (@matburt)
|
||||||
|
|||||||
@@ -174,6 +174,13 @@ def query_package(module, name):
|
|||||||
# '<' - installed but out of date
|
# '<' - installed but out of date
|
||||||
# '=' - installed and up to date
|
# '=' - installed and up to date
|
||||||
# '>' - installed but newer than the repository version
|
# '>' - installed but newer than the repository version
|
||||||
|
|
||||||
|
if (package in ('reading local summary...',
|
||||||
|
'processing local summary...',
|
||||||
|
'downloading pkg_summary.xz done.')) or \
|
||||||
|
(package.startswith('processing remote summary (')):
|
||||||
|
continue
|
||||||
|
|
||||||
pkgname_with_version, raw_state = package.split(splitchar)[0:2]
|
pkgname_with_version, raw_state = package.split(splitchar)[0:2]
|
||||||
|
|
||||||
# Search for package, stripping version
|
# Search for package, stripping version
|
||||||
@@ -317,7 +324,7 @@ def do_upgrade_packages(module, full=False):
|
|||||||
format_pkgin_command(module, cmd))
|
format_pkgin_command(module, cmd))
|
||||||
|
|
||||||
if rc == 0:
|
if rc == 0:
|
||||||
if re.search('^nothing to do.\n$', out):
|
if re.search('^(.*\n|)nothing to do.\n$', out):
|
||||||
module.exit_json(changed=False, msg="nothing left to upgrade")
|
module.exit_json(changed=False, msg="nothing left to upgrade")
|
||||||
else:
|
else:
|
||||||
module.fail_json(msg="could not %s packages" % cmd, stdout=out, stderr=err)
|
module.fail_json(msg="could not %s packages" % cmd, stdout=out, stderr=err)
|
||||||
|
|||||||
@@ -325,7 +325,7 @@ EXAMPLES = r'''
|
|||||||
api_host: node1
|
api_host: node1
|
||||||
password: 123456
|
password: 123456
|
||||||
hostname: example.org
|
hostname: example.org
|
||||||
ostemplate: local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
|
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
|
||||||
mounts: '{"mp0":"local:8,mp=/mnt/test/"}'
|
mounts: '{"mp0":"local:8,mp=/mnt/test/"}'
|
||||||
|
|
||||||
- name: Create new container with minimal options defining a cpu core limit
|
- name: Create new container with minimal options defining a cpu core limit
|
||||||
@@ -337,7 +337,7 @@ EXAMPLES = r'''
|
|||||||
api_host: node1
|
api_host: node1
|
||||||
password: 123456
|
password: 123456
|
||||||
hostname: example.org
|
hostname: example.org
|
||||||
ostemplate: local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
|
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
|
||||||
cores: 2
|
cores: 2
|
||||||
|
|
||||||
- name: Create new container with minimal options and same timezone as proxmox host
|
- name: Create new container with minimal options and same timezone as proxmox host
|
||||||
@@ -361,7 +361,7 @@ EXAMPLES = r'''
|
|||||||
api_host: node1
|
api_host: node1
|
||||||
password: 123456
|
password: 123456
|
||||||
hostname: example.org
|
hostname: example.org
|
||||||
ostemplate: local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
|
ostemplate: 'local:vztmpl/ubuntu-14.04-x86_64.tar.gz'
|
||||||
features:
|
features:
|
||||||
- nesting=1
|
- nesting=1
|
||||||
- mount=cifs,nfs
|
- mount=cifs,nfs
|
||||||
|
|||||||
@@ -1466,8 +1466,9 @@ def main():
|
|||||||
status = {}
|
status = {}
|
||||||
try:
|
try:
|
||||||
vm = proxmox.get_vm(vmid)
|
vm = proxmox.get_vm(vmid)
|
||||||
status['status'] = vm['status']
|
current = proxmox.proxmox_api.nodes(vm['node']).qemu(vmid).status.current.get()['status']
|
||||||
if vm['status'] == 'running':
|
status['status'] = current
|
||||||
|
if current == 'running':
|
||||||
module.exit_json(changed=False, vmid=vmid, msg="VM %s is already running" % vmid, **status)
|
module.exit_json(changed=False, vmid=vmid, msg="VM %s is already running" % vmid, **status)
|
||||||
|
|
||||||
if proxmox.start_vm(vm):
|
if proxmox.start_vm(vm):
|
||||||
@@ -1482,9 +1483,9 @@ def main():
|
|||||||
status = {}
|
status = {}
|
||||||
try:
|
try:
|
||||||
vm = proxmox.get_vm(vmid)
|
vm = proxmox.get_vm(vmid)
|
||||||
|
current = proxmox.proxmox_api.nodes(vm['node']).qemu(vmid).status.current.get()['status']
|
||||||
status['status'] = vm['status']
|
status['status'] = current
|
||||||
if vm['status'] == 'stopped':
|
if current == 'stopped':
|
||||||
module.exit_json(changed=False, vmid=vmid, msg="VM %s is already stopped" % vmid, **status)
|
module.exit_json(changed=False, vmid=vmid, msg="VM %s is already stopped" % vmid, **status)
|
||||||
|
|
||||||
if proxmox.stop_vm(vm, force=module.params['force'], timeout=module.params['timeout']):
|
if proxmox.stop_vm(vm, force=module.params['force'], timeout=module.params['timeout']):
|
||||||
@@ -1498,8 +1499,9 @@ def main():
|
|||||||
|
|
||||||
status = {}
|
status = {}
|
||||||
vm = proxmox.get_vm(vmid)
|
vm = proxmox.get_vm(vmid)
|
||||||
status['status'] = vm['status']
|
current = proxmox.proxmox_api.nodes(vm['node']).qemu(vmid).status.current.get()['status']
|
||||||
if vm['status'] == 'stopped':
|
status['status'] = current
|
||||||
|
if current == 'stopped':
|
||||||
module.exit_json(changed=False, vmid=vmid, msg="VM %s is not running" % vmid, **status)
|
module.exit_json(changed=False, vmid=vmid, msg="VM %s is not running" % vmid, **status)
|
||||||
|
|
||||||
if proxmox.restart_vm(vm, force=module.params['force']):
|
if proxmox.restart_vm(vm, force=module.params['force']):
|
||||||
@@ -1516,8 +1518,9 @@ def main():
|
|||||||
module.exit_json(changed=False, vmid=vmid)
|
module.exit_json(changed=False, vmid=vmid)
|
||||||
|
|
||||||
proxmox_node = proxmox.proxmox_api.nodes(vm['node'])
|
proxmox_node = proxmox.proxmox_api.nodes(vm['node'])
|
||||||
status['status'] = vm['status']
|
current = proxmox_node.qemu(vmid).status.current.get()['status']
|
||||||
if vm['status'] == 'running':
|
status['status'] = current
|
||||||
|
if current == 'running':
|
||||||
if module.params['force']:
|
if module.params['force']:
|
||||||
proxmox.stop_vm(vm, True, timeout=module.params['timeout'])
|
proxmox.stop_vm(vm, True, timeout=module.params['timeout'])
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -116,6 +116,15 @@ options:
|
|||||||
- Whether to print file changes details
|
- Whether to print file changes details
|
||||||
type: bool
|
type: bool
|
||||||
default: false
|
default: false
|
||||||
|
environment_lang:
|
||||||
|
description:
|
||||||
|
- The lang environment to use when running the puppet agent.
|
||||||
|
- The default value, V(C), is supported on every system, but can lead to encoding errors if UTF-8 is used in the output
|
||||||
|
- Use V(C.UTF-8) or V(en_US.UTF-8) or similar UTF-8 supporting locales in case of problems. You need to make sure
|
||||||
|
the selected locale is supported on the system the puppet agent runs on.
|
||||||
|
type: str
|
||||||
|
default: C
|
||||||
|
version_added: 8.6.0
|
||||||
requirements:
|
requirements:
|
||||||
- puppet
|
- puppet
|
||||||
author:
|
author:
|
||||||
@@ -208,6 +217,7 @@ def main():
|
|||||||
debug=dict(type='bool', default=False),
|
debug=dict(type='bool', default=False),
|
||||||
verbose=dict(type='bool', default=False),
|
verbose=dict(type='bool', default=False),
|
||||||
use_srv_records=dict(type='bool'),
|
use_srv_records=dict(type='bool'),
|
||||||
|
environment_lang=dict(type='str', default='C'),
|
||||||
),
|
),
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
mutually_exclusive=[
|
mutually_exclusive=[
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ from ansible.module_utils.urls import fetch_url
|
|||||||
|
|
||||||
|
|
||||||
def ring_check(module, riak_admin_bin):
|
def ring_check(module, riak_admin_bin):
|
||||||
cmd = '%s ringready' % riak_admin_bin
|
cmd = riak_admin_bin + ['ringready']
|
||||||
rc, out, err = module.run_command(cmd)
|
rc, out, err = module.run_command(cmd)
|
||||||
if rc == 0 and 'TRUE All nodes agree on the ring' in out:
|
if rc == 0 and 'TRUE All nodes agree on the ring' in out:
|
||||||
return True
|
return True
|
||||||
@@ -127,6 +127,7 @@ def main():
|
|||||||
# make sure riak commands are on the path
|
# make sure riak commands are on the path
|
||||||
riak_bin = module.get_bin_path('riak')
|
riak_bin = module.get_bin_path('riak')
|
||||||
riak_admin_bin = module.get_bin_path('riak-admin')
|
riak_admin_bin = module.get_bin_path('riak-admin')
|
||||||
|
riak_admin_bin = [riak_admin_bin] if riak_admin_bin is not None else [riak_bin, 'admin']
|
||||||
|
|
||||||
timeout = time.time() + 120
|
timeout = time.time() + 120
|
||||||
while True:
|
while True:
|
||||||
@@ -164,7 +165,7 @@ def main():
|
|||||||
module.fail_json(msg=out)
|
module.fail_json(msg=out)
|
||||||
|
|
||||||
elif command == 'kv_test':
|
elif command == 'kv_test':
|
||||||
cmd = '%s test' % riak_admin_bin
|
cmd = riak_admin_bin + ['test']
|
||||||
rc, out, err = module.run_command(cmd)
|
rc, out, err = module.run_command(cmd)
|
||||||
if rc == 0:
|
if rc == 0:
|
||||||
result['kv_test'] = out
|
result['kv_test'] = out
|
||||||
@@ -175,7 +176,7 @@ def main():
|
|||||||
if nodes.count(node_name) == 1 and len(nodes) > 1:
|
if nodes.count(node_name) == 1 and len(nodes) > 1:
|
||||||
result['join'] = 'Node is already in cluster or staged to be in cluster.'
|
result['join'] = 'Node is already in cluster or staged to be in cluster.'
|
||||||
else:
|
else:
|
||||||
cmd = '%s cluster join %s' % (riak_admin_bin, target_node)
|
cmd = riak_admin_bin + ['cluster', 'join', target_node]
|
||||||
rc, out, err = module.run_command(cmd)
|
rc, out, err = module.run_command(cmd)
|
||||||
if rc == 0:
|
if rc == 0:
|
||||||
result['join'] = out
|
result['join'] = out
|
||||||
@@ -184,7 +185,7 @@ def main():
|
|||||||
module.fail_json(msg=out)
|
module.fail_json(msg=out)
|
||||||
|
|
||||||
elif command == 'plan':
|
elif command == 'plan':
|
||||||
cmd = '%s cluster plan' % riak_admin_bin
|
cmd = riak_admin_bin + ['cluster', 'plan']
|
||||||
rc, out, err = module.run_command(cmd)
|
rc, out, err = module.run_command(cmd)
|
||||||
if rc == 0:
|
if rc == 0:
|
||||||
result['plan'] = out
|
result['plan'] = out
|
||||||
@@ -194,7 +195,7 @@ def main():
|
|||||||
module.fail_json(msg=out)
|
module.fail_json(msg=out)
|
||||||
|
|
||||||
elif command == 'commit':
|
elif command == 'commit':
|
||||||
cmd = '%s cluster commit' % riak_admin_bin
|
cmd = riak_admin_bin + ['cluster', 'commit']
|
||||||
rc, out, err = module.run_command(cmd)
|
rc, out, err = module.run_command(cmd)
|
||||||
if rc == 0:
|
if rc == 0:
|
||||||
result['commit'] = out
|
result['commit'] = out
|
||||||
@@ -206,7 +207,7 @@ def main():
|
|||||||
if wait_for_handoffs:
|
if wait_for_handoffs:
|
||||||
timeout = time.time() + wait_for_handoffs
|
timeout = time.time() + wait_for_handoffs
|
||||||
while True:
|
while True:
|
||||||
cmd = '%s transfers' % riak_admin_bin
|
cmd = riak_admin_bin + ['transfers']
|
||||||
rc, out, err = module.run_command(cmd)
|
rc, out, err = module.run_command(cmd)
|
||||||
if 'No transfers active' in out:
|
if 'No transfers active' in out:
|
||||||
result['handoffs'] = 'No transfers active.'
|
result['handoffs'] = 'No transfers active.'
|
||||||
@@ -216,7 +217,7 @@ def main():
|
|||||||
module.fail_json(msg='Timeout waiting for handoffs.')
|
module.fail_json(msg='Timeout waiting for handoffs.')
|
||||||
|
|
||||||
if wait_for_service:
|
if wait_for_service:
|
||||||
cmd = [riak_admin_bin, 'wait_for_service', 'riak_%s' % wait_for_service, node_name]
|
cmd = riak_admin_bin + ['wait_for_service', 'riak_%s' % wait_for_service, node_name]
|
||||||
rc, out, err = module.run_command(cmd)
|
rc, out, err = module.run_command(cmd)
|
||||||
result['service'] = out
|
result['service'] = out
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ options:
|
|||||||
aliases: [ rtc ]
|
aliases: [ rtc ]
|
||||||
choices: [ local, UTC ]
|
choices: [ local, UTC ]
|
||||||
notes:
|
notes:
|
||||||
- On SmartOS the C(sm-set-timezone) utility (part of the smtools package) is required to set the zone timezone
|
- On Ubuntu 24.04 the C(util-linux-extra) package is required to provide the C(hwclock) command.
|
||||||
|
- On SmartOS the C(sm-set-timezone) utility (part of the smtools package) is required to set the zone timezone.
|
||||||
- On AIX only Olson/tz database timezones are usable (POSIX is not supported).
|
- On AIX only Olson/tz database timezones are usable (POSIX is not supported).
|
||||||
- An OS reboot is also required on AIX for the new timezone setting to take effect.
|
- An OS reboot is also required on AIX for the new timezone setting to take effect.
|
||||||
author:
|
author:
|
||||||
|
|||||||
@@ -436,11 +436,16 @@ def is_attribute(tree, xpath, namespaces):
|
|||||||
""" Test if a given xpath matches and that match is an attribute
|
""" Test if a given xpath matches and that match is an attribute
|
||||||
|
|
||||||
An xpath attribute search will only match one item"""
|
An xpath attribute search will only match one item"""
|
||||||
|
|
||||||
|
# lxml 5.1.1 removed etree._ElementStringResult, so we can no longer simply assume it's there
|
||||||
|
# (https://github.com/lxml/lxml/commit/eba79343d0e7ad1ce40169f60460cdd4caa29eb3)
|
||||||
|
ElementStringResult = getattr(etree, '_ElementStringResult', None)
|
||||||
|
|
||||||
if xpath_matches(tree, xpath, namespaces):
|
if xpath_matches(tree, xpath, namespaces):
|
||||||
match = tree.xpath(xpath, namespaces=namespaces)
|
match = tree.xpath(xpath, namespaces=namespaces)
|
||||||
if isinstance(match[0], etree._ElementStringResult):
|
if isinstance(match[0], etree._ElementUnicodeResult):
|
||||||
return True
|
return True
|
||||||
elif isinstance(match[0], etree._ElementUnicodeResult):
|
elif ElementStringResult is not None and isinstance(match[0], ElementStringResult):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
41
plugins/plugin_utils/unsafe.py
Normal file
41
plugins/plugin_utils/unsafe.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# Copyright (c) 2023, Felix Fontein <felix@fontein.de>
|
||||||
|
# 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
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
from ansible.module_utils.six import binary_type, text_type
|
||||||
|
from ansible.module_utils.common._collections_compat import Mapping, Set
|
||||||
|
from ansible.module_utils.common.collections import is_sequence
|
||||||
|
from ansible.utils.unsafe_proxy import (
|
||||||
|
AnsibleUnsafe,
|
||||||
|
wrap_var as _make_unsafe,
|
||||||
|
)
|
||||||
|
|
||||||
|
_RE_TEMPLATE_CHARS = re.compile(u'[{}]')
|
||||||
|
_RE_TEMPLATE_CHARS_BYTES = re.compile(b'[{}]')
|
||||||
|
|
||||||
|
|
||||||
|
def make_unsafe(value):
|
||||||
|
if value is None or isinstance(value, AnsibleUnsafe):
|
||||||
|
return value
|
||||||
|
|
||||||
|
if isinstance(value, Mapping):
|
||||||
|
return dict((make_unsafe(key), make_unsafe(val)) for key, val in value.items())
|
||||||
|
elif isinstance(value, Set):
|
||||||
|
return set(make_unsafe(elt) for elt in value)
|
||||||
|
elif is_sequence(value):
|
||||||
|
return type(value)(make_unsafe(elt) for elt in value)
|
||||||
|
elif isinstance(value, binary_type):
|
||||||
|
if _RE_TEMPLATE_CHARS_BYTES.search(value):
|
||||||
|
value = _make_unsafe(value)
|
||||||
|
return value
|
||||||
|
elif isinstance(value, text_type):
|
||||||
|
if _RE_TEMPLATE_CHARS.search(value):
|
||||||
|
value = _make_unsafe(value)
|
||||||
|
return value
|
||||||
|
|
||||||
|
return value
|
||||||
13
tests/integration/targets/apk/aliases
Normal file
13
tests/integration/targets/apk/aliases
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
azp/posix/2
|
||||||
|
needs/root
|
||||||
|
destructive
|
||||||
|
skip/aix
|
||||||
|
skip/osx
|
||||||
|
skip/macos
|
||||||
|
skip/freebsd
|
||||||
|
skip/rhel
|
||||||
|
skip/ubuntu
|
||||||
160
tests/integration/targets/apk/tasks/main.yml
Normal file
160
tests/integration/targets/apk/tasks/main.yml
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
####################################################################
|
||||||
|
# WARNING: These are designed specifically for Ansible tests #
|
||||||
|
# and should not be used as examples of how to write Ansible roles #
|
||||||
|
####################################################################
|
||||||
|
|
||||||
|
# Copyright (c) 2024, Max Maxopoly <max@dermax.org>
|
||||||
|
# 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
|
||||||
|
- name: Run apk tests on Alpine
|
||||||
|
when: ansible_distribution in ['Alpine']
|
||||||
|
block:
|
||||||
|
- name: Ensure vim is not installed
|
||||||
|
community.general.apk:
|
||||||
|
name: vim
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Install vim
|
||||||
|
community.general.apk:
|
||||||
|
name: vim
|
||||||
|
state: present
|
||||||
|
register: results
|
||||||
|
|
||||||
|
- name: Ensure vim was installed
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- results is changed
|
||||||
|
- (results.packages | length) >= 1 # vim has dependencies, so depending on the base image this number may vary
|
||||||
|
|
||||||
|
- name: Install vim again
|
||||||
|
community.general.apk:
|
||||||
|
name: vim
|
||||||
|
state: present
|
||||||
|
register: results
|
||||||
|
|
||||||
|
- name: Ensure vim was not installed again
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- results is not changed
|
||||||
|
- (results.packages | default([]) | length) == 0
|
||||||
|
|
||||||
|
- name: Ensure vim is not installed
|
||||||
|
community.general.apk:
|
||||||
|
name: vim
|
||||||
|
state: absent
|
||||||
|
register: results
|
||||||
|
|
||||||
|
- name: Ensure vim was uninstalled
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- results is changed
|
||||||
|
- (results.packages | length) >= 1
|
||||||
|
|
||||||
|
- name: Install vim without cache
|
||||||
|
community.general.apk:
|
||||||
|
name: vim
|
||||||
|
state: present
|
||||||
|
no_cache: true
|
||||||
|
register: results
|
||||||
|
|
||||||
|
- name: Ensure vim was installed without cache
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- results is changed
|
||||||
|
|
||||||
|
- name: Install vim again without cache
|
||||||
|
community.general.apk:
|
||||||
|
name: vim
|
||||||
|
state: present
|
||||||
|
no_cache: true
|
||||||
|
register: results
|
||||||
|
|
||||||
|
- name: Ensure vim was not installed again without cache
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- results is not changed
|
||||||
|
- (results.packages | default([]) | length) == 0
|
||||||
|
|
||||||
|
- name: Ensure a bunch of packages aren't installed
|
||||||
|
community.general.apk:
|
||||||
|
name:
|
||||||
|
- less
|
||||||
|
- nano
|
||||||
|
- vim
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Install a bunch of packages
|
||||||
|
community.general.apk:
|
||||||
|
name:
|
||||||
|
- less
|
||||||
|
- nano
|
||||||
|
- vim
|
||||||
|
state: present
|
||||||
|
register: results
|
||||||
|
|
||||||
|
- name: Ensure a bunch of packages were installed
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- results is changed
|
||||||
|
- (results.packages | length) >= 3
|
||||||
|
|
||||||
|
- name: Install a bunch of packages again
|
||||||
|
community.general.apk:
|
||||||
|
name:
|
||||||
|
- less
|
||||||
|
- nano
|
||||||
|
- vim
|
||||||
|
state: present
|
||||||
|
register: results
|
||||||
|
|
||||||
|
- name: Ensure a bunch of packages were not installed again
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- results is not changed
|
||||||
|
- (results.packages | default([]) | length) == 0
|
||||||
|
|
||||||
|
- name: Ensure a bunch of packages are not installed
|
||||||
|
community.general.apk:
|
||||||
|
name:
|
||||||
|
- less
|
||||||
|
- nano
|
||||||
|
- vim
|
||||||
|
state: absent
|
||||||
|
register: results
|
||||||
|
|
||||||
|
- name: Ensure a bunch of packages were uninstalled
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- results is changed
|
||||||
|
- (results.packages | length) >= 3
|
||||||
|
|
||||||
|
- name: Install a bunch of packages without cache
|
||||||
|
community.general.apk:
|
||||||
|
name:
|
||||||
|
- less
|
||||||
|
- nano
|
||||||
|
- vim
|
||||||
|
state: present
|
||||||
|
no_cache: true
|
||||||
|
register: results
|
||||||
|
|
||||||
|
- name: Ensure a bunch of packages were installed without cache
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- results is changed
|
||||||
|
|
||||||
|
- name: Install a bunch of packages again without cache
|
||||||
|
community.general.apk:
|
||||||
|
name:
|
||||||
|
- less
|
||||||
|
- nano
|
||||||
|
- vim
|
||||||
|
state: present
|
||||||
|
no_cache: true
|
||||||
|
register: results
|
||||||
|
|
||||||
|
- name: Ensure a bunch of packages were not installed again without cache
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- results is not changed
|
||||||
|
- (results.packages | default([]) | length) == 0
|
||||||
@@ -8,6 +8,14 @@
|
|||||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# 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
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
- name: Help debugging
|
||||||
|
debug:
|
||||||
|
msg: >-
|
||||||
|
distribution={{ ansible_distribution }},
|
||||||
|
distribution major version={{ ansible_distribution_major_version }},
|
||||||
|
os_family={{ ansible_os_family }},
|
||||||
|
Python version={{ ansible_python.version.major }}
|
||||||
|
|
||||||
- name: test cloud-init
|
- name: test cloud-init
|
||||||
# TODO: check for a workaround
|
# TODO: check for a workaround
|
||||||
# install 'cloud-init'' failed: dpkg-divert: error: `diversion of /etc/init/ureadahead.conf
|
# install 'cloud-init'' failed: dpkg-divert: error: `diversion of /etc/init/ureadahead.conf
|
||||||
@@ -15,10 +23,11 @@
|
|||||||
# /etc/init/ureadahead.conf to /etc/init/ureadahead.conf.distrib
|
# /etc/init/ureadahead.conf to /etc/init/ureadahead.conf.distrib
|
||||||
# https://bugs.launchpad.net/ubuntu/+source/ureadahead/+bug/997838
|
# https://bugs.launchpad.net/ubuntu/+source/ureadahead/+bug/997838
|
||||||
# Will also have to skip on OpenSUSE when running on Python 2 on newer Leap versions
|
# Will also have to skip on OpenSUSE when running on Python 2 on newer Leap versions
|
||||||
# (!= 42 and >= 15) ascloud-init will install the Python 3 package, breaking our build on py2.
|
# (!= 42 and >= 15) as cloud-init will install the Python 3 package, breaking our build on py2.
|
||||||
when:
|
when:
|
||||||
- not (ansible_distribution == "Ubuntu" and ansible_distribution_major_version|int == 14)
|
- not (ansible_distribution == "Ubuntu" and ansible_distribution_major_version|int == 14)
|
||||||
- not (ansible_os_family == "Suse" and ansible_distribution_major_version|int != 42 and ansible_python.version.major != 3)
|
- not (ansible_os_family == "Suse" and ansible_distribution_major_version|int != 42 and ansible_python.version.major != 3)
|
||||||
|
- not (ansible_os_family == "Suse" and ansible_distribution_major_version|int == 15)
|
||||||
- not (ansible_distribution == "CentOS" and ansible_distribution_major_version|int == 8) # TODO: cannot start service
|
- not (ansible_distribution == "CentOS" and ansible_distribution_major_version|int == 8) # TODO: cannot start service
|
||||||
- not (ansible_distribution == 'Archlinux') # TODO: package seems to be broken, cannot be downloaded from mirrors?
|
- not (ansible_distribution == 'Archlinux') # TODO: package seems to be broken, cannot be downloaded from mirrors?
|
||||||
- not (ansible_distribution == 'Alpine') # TODO: not sure what's wrong here, the module doesn't return what the tests expect
|
- not (ansible_distribution == 'Alpine') # TODO: not sure what's wrong here, the module doesn't return what the tests expect
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
- name: bail out for non-supported platforms
|
- name: bail out for non-supported platforms
|
||||||
meta: end_play
|
meta: end_play
|
||||||
when:
|
when:
|
||||||
- (ansible_os_family != "RedHat" or ansible_distribution_major_version|int < 7)
|
- (ansible_os_family != "RedHat" or ansible_distribution_major_version|int < 8) # TODO: bump back to 7
|
||||||
|
- (ansible_distribution != 'CentOS' or ansible_distribution_major_version|int < 8) # TODO: remove
|
||||||
- ansible_os_family != "Debian"
|
- ansible_os_family != "Debian"
|
||||||
|
|
||||||
- name: install perl development package for Red Hat family
|
- name: install perl development package for Red Hat family
|
||||||
|
|||||||
@@ -43,6 +43,11 @@
|
|||||||
chdir: "{{ tmp_django_root.path }}/startproj"
|
chdir: "{{ tmp_django_root.path }}/startproj"
|
||||||
cmd: "{{ tmp_django_root.path }}/venv/bin/django-admin startapp app1"
|
cmd: "{{ tmp_django_root.path }}/venv/bin/django-admin startapp app1"
|
||||||
|
|
||||||
|
- name: Make manage.py executable
|
||||||
|
file:
|
||||||
|
path: "{{ tmp_django_root.path }}/startproj/test_django_manage_1/manage.py"
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
- name: Check
|
- name: Check
|
||||||
community.general.django_manage:
|
community.general.django_manage:
|
||||||
project_path: "{{ tmp_django_root.path }}/startproj/test_django_manage_1"
|
project_path: "{{ tmp_django_root.path }}/startproj/test_django_manage_1"
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user