Compare commits

..

51 Commits

Author SHA1 Message Date
157b783521 Merge pull request #6491 from jlaska/apt_repository_signing_fix
[apt_repository] Correct check_mode conditional logic
2014-03-14 11:23:41 -04:00
fc02883017 CHANGELOG and README updates for 1.5.3 2014-03-13 15:29:34 -05:00
2cf0dadb47 Revert "Rejoin args list into a string for run_command when using an unsafe shell"
This reverts commit 4273cb2d8e.
2014-03-13 14:51:08 -05:00
13692311e8 Fix typo in run_command when sending data that is not binary 2014-03-13 14:51:08 -05:00
824d42081c Update VERSION file for 1.5.3 release 2014-03-13 15:02:30 -04:00
c96c3c483c Rejoin args list into a string for run_command when using an unsafe shell
This allows the use of an args list with leading environment variables,
which otherwise would fail due to the way Popen works.
2014-03-13 13:53:25 -05:00
48a1c156ee [test_service] correct upstart service name and permissions
The 'service' utility was unable to find the 'ansible_test' service due to an
unexpected filename.  This patch corrects the filename and adjusts the
permissions to match other service scripts within /etc/init/.
2014-03-13 08:29:17 -04:00
f641cb1665 Correct ansible_distribution typo
Redhat != RedHat
2014-03-13 08:29:02 -04:00
3157dc5620 Use correct value of ansible_distribution in integration tests
This fixes integration tests when run on a RHEL system.  Oddly, the
ansible_distribution='RedHat' when run on RHEL.
2014-03-13 08:28:54 -04:00
f0a89d5bdf Correct test integration ec2 cleanup script 2014-03-13 07:50:11 -04:00
763235a83d Fix regression in dnsmadeeasy module caused by fetch_url change
Also:
* changed this module to use https for requests to the API
* fixed a bug in which a traceback was caused when the domain wasn't found

Fixes #6457
2014-03-13 07:50:11 -04:00
b489406507 Merge pull request #6461 from risaacson/modules_make_run_command_safer
Modules make run command safer
2014-03-13 07:50:11 -04:00
4c3781899e Fixes various typos introduced in a9017af2bb.
Fixes odd encoding problem with wait_for_service.
2014-03-12 21:57:29 -05:00
1728734d69 Fix test_fetch role 2014-03-12 18:51:11 -04:00
ac34b67bf4 Still more shell fixes. 2014-03-12 18:04:18 -04:00
053a5fb46f Fixup shell handling in monit module. 2014-03-12 18:04:18 -04:00
64d69a88f7 More shell fixes 2014-03-12 18:04:18 -04:00
c78a5681fc Close parens in portinstall 2014-03-12 18:04:18 -04:00
b5ce0526bc Remove files added by cherry-pick from devel 2014-03-12 18:04:18 -04:00
e6b05da55b More shell updates
Conflicts:

	library/system/debconf
2014-03-12 18:04:18 -04:00
6738737518 Fix missing colons in cpanm 2014-03-12 18:04:18 -04:00
1be68b4821 Fix typo in portinstall 2014-03-12 18:04:18 -04:00
d2036cedcc Some more run_command updates. 2014-03-12 18:04:18 -04:00
4392246b47 Fixes for run_command shell usage in remainder of packaging modules, save portinstall. 2014-03-12 18:04:18 -04:00
626f9629e2 Various commits to enable no-shell or safe-shell usage, more to come.
Conflicts:

	library/packaging/cpanm
2014-03-12 18:04:18 -04:00
80df6e4197 Only use cwd in run_command kwargs if the directory exists 2014-03-12 16:10:00 -05:00
a401f9579d git: Execute git commands in dest directory 2014-03-12 15:41:02 -05:00
fbf36040f4 Make sure the cwd exists in run_command before trying to use it 2014-03-12 15:40:55 -05:00
5c568bb00c Work around for cwd stat problems with run_command and sudo
This fixes issue #6443
2014-03-12 15:40:42 -05:00
baeabd9180 Compile ca certs into a temp file to reduce number of attempts
For those who may have a large number of certs found, this can reduce
the number of ssl connections attempted.
2014-03-12 16:11:15 -04:00
a28ff5f830 Remove validate_certs parameter from fetch_url calls 2014-03-12 16:11:04 -04:00
cb40013d15 Adding validate_certs to all modules that use fetch_url 2014-03-12 16:10:56 -04:00
f4a20feb4d Remove unused code from get_ca_certs() function 2014-03-12 16:10:48 -04:00
02b2e532db Rewriting ssl validation to try multiple certs found in paths
Previously, the function checked only for a single CA root cert, however
some distributions may have multiple certs in a directory. This will now
try any .crt or .pem file contained within several common paths for
each platform.

Fixes #6412
2014-03-12 16:10:39 -04:00
eef4096e8f Use same implementation as ssh.py for "is in host file" checks in module code, prevents git module from adding keys more than once. 2014-03-12 16:04:38 -04:00
453bedcf87 Don't process shell commands as arrays. 2014-03-12 16:03:59 -04:00
dbfcf0325e Expand environment variables and tildes passed to commands generically across the board. 2014-03-12 16:03:48 -04:00
72c7841c57 add module param to Network & sub-classes
add module param to Network and sub-classes of Network, so that ansible 1.5.1 changes to LinuxNetwork apply to all Network classes.
2014-03-12 16:03:12 -04:00
42ca3d8076 Check for hash availability during vault operations 2014-03-12 16:01:25 -04:00
b0771f3cd2 Wrap crypto.hash imports with try/except 2014-03-12 16:01:12 -04:00
521e135cb3 Fixed references to missing method in ec2 modules
Change-Id: I9b89d433b545269d111b3c290b6411aabf58dd24
2014-03-12 16:00:41 -04:00
d808604a51 Fixes #6411 Return None for ec2 api endpoints that return 404 2014-03-12 15:59:02 -04:00
e509191b76 Fix ec2_facts module by removing stray fail statement 2014-03-12 15:58:50 -04:00
de753fe99c Fix test_async by using env python 2014-03-12 15:58:04 -04:00
a9762357f9 module.run_command is intended to bypass the shell here, so can't do ">>" 2014-03-12 10:56:38 -04:00
8588ac5f60 Fix other reference to APT_ENV_VARS. 2014-03-11 10:48:52 -04:00
3bb3ce4467 Update apt module so that environment variables are set correctly since not going through shell. Very sorry folks, it will be addressed. 2014-03-11 10:48:42 -04:00
9d4589d574 version release bump for 1.5.2 2014-03-11 08:50:47 -04:00
1a470b1776 Merge branch 'release1.5.1' into release1.5.2 2014-03-11 08:43:37 -04:00
4ec3f3c1d5 Missing comma in argument spec. 2014-03-10 20:29:34 -05:00
7ad9598fe8 Missing comma in argument spec. 2014-03-10 19:39:01 -04:00
5772 changed files with 106859 additions and 374389 deletions

View File

@ -1,209 +0,0 @@
trigger:
batch: true
branches:
include:
- devel
- stable-*
pr:
autoCancel: true
branches:
include:
- devel
- stable-*
schedules:
- cron: 0 7 * * *
displayName: Nightly
always: true
branches:
include:
- devel
- stable-*
variables:
- name: checkoutPath
value: ansible
- name: coverageBranches
value: devel
- name: entryPoint
value: .azure-pipelines/commands/entry-point.sh
- name: fetchDepth
value: 500
- name: defaultContainer
value: quay.io/ansible/azure-pipelines-test-container:6.0.0
pool: Standard
stages:
- stage: Sanity
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Test {0}
testFormat: sanity/{0}
targets:
- test: 1
- test: 2
- stage: Units
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: units/{0}
targets:
- test: 3.7
- test: 3.8
- test: 3.9
- test: '3.10'
- test: 3.11
- test: 3.12
- stage: Windows
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Server {0}
testFormat: windows/{0}/1
targets:
- test: 2016
- test: 2019
- test: 2022
- stage: Remote
dependsOn: []
jobs:
- template: templates/matrix.yml # context/target
parameters:
targets:
- name: macOS 14.3
test: macos/14.3
- name: RHEL 9.3 py39
test: rhel/9.3@3.9
- name: RHEL 9.3 py311
test: rhel/9.3@3.11
- name: FreeBSD 13.3
test: freebsd/13.3
- name: FreeBSD 14.0
test: freebsd/14.0
groups:
- 1
- 2
- template: templates/matrix.yml # context/controller
parameters:
targets:
- name: macOS 14.3
test: macos/14.3
- name: RHEL 9.3
test: rhel/9.3
- name: FreeBSD 13.3
test: freebsd/13.3
- name: FreeBSD 14.0
test: freebsd/14.0
groups:
- 3
- 4
- 5
- template: templates/matrix.yml # context/controller (ansible-test container management)
parameters:
targets:
- name: Alpine 3.19
test: alpine/3.19
- name: Fedora 39
test: fedora/39
- name: RHEL 9.3
test: rhel/9.3
- name: Ubuntu 22.04
test: ubuntu/22.04
groups:
- 6
- stage: Docker
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: linux/{0}
targets:
- name: Alpine 3.19
test: alpine319
- name: Fedora 39
test: fedora39
- name: Ubuntu 20.04
test: ubuntu2004
- name: Ubuntu 22.04
test: ubuntu2204
groups:
- 1
- 2
- template: templates/matrix.yml
parameters:
testFormat: linux/{0}
targets:
- name: Alpine 3.19
test: alpine319
- name: Fedora 39
test: fedora39
- name: Ubuntu 22.04
test: ubuntu2204
groups:
- 3
- 4
- 5
- stage: Galaxy
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: galaxy/{0}/1
targets:
- test: '3.10'
- test: 3.11
- test: 3.12
- stage: Generic
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: generic/{0}/1
targets:
- test: '3.10'
- test: 3.11
- test: 3.12
- stage: Incidental_Windows
displayName: Incidental Windows
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Server {0}
testFormat: i/windows/{0}
targets:
- test: 2016
- test: 2019
- test: 2022
- stage: Incidental
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: i/{0}/1
targets:
- name: IOS Python
test: ios/csr1000v/
- stage: Summary
condition: succeededOrFailed()
dependsOn:
- Sanity
- Units
- Windows
- Remote
- Docker
- Galaxy
- Generic
- Incidental_Windows
- Incidental
jobs:
- template: templates/coverage.yml

View File

@ -1 +0,0 @@
remote.sh

View File

@ -1,34 +0,0 @@
#!/usr/bin/env bash
set -o pipefail -eux
declare -a args
IFS='/:' read -ra args <<< "$1"
cloud="${args[0]}"
python="${args[1]}"
group="${args[2]}"
target="shippable/${cloud}/group${group}/"
stage="${S:-prod}"
changed_all_target="shippable/${cloud}/smoketest/"
if ! ansible-test integration "${changed_all_target}" --list-targets > /dev/null 2>&1; then
# no smoketest tests are available for this cloud
changed_all_target="none"
fi
if [ "${group}" == "1" ]; then
# only run smoketest tests for group1
changed_all_mode="include"
else
# smoketest tests already covered by group1
changed_all_mode="exclude"
fi
# shellcheck disable=SC2086
ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \
--remote-terminate always --remote-stage "${stage}" \
--docker --python "${python}" --changed-all-target "${changed_all_target}" --changed-all-mode "${changed_all_mode}"

View File

@ -1,62 +0,0 @@
#!/usr/bin/env bash
set -o pipefail -eux
declare -a args
IFS='/:' read -ra args <<< "$1"
script="${args[0]}"
test="$1"
docker images
docker ps
for container in $(docker ps --format '{{.Image}} {{.ID}}' | grep -v -e '^quay.io/ansible/azure-pipelines-test-container:' | sed 's/^.* //'); do
docker rm -f "${container}" || true # ignore errors
done
docker ps
export PATH="${PWD}/bin:${PATH}"
export PYTHONIOENCODING='utf-8'
if [ -n "${COVERAGE:-}" ]; then
# on-demand coverage reporting triggered by setting the COVERAGE environment variable to a non-empty value
export COVERAGE="--coverage"
elif [[ "${COMMIT_MESSAGE}" =~ ci_coverage ]]; then
# on-demand coverage reporting triggered by having 'ci_coverage' in the latest commit message
export COVERAGE="--coverage"
else
# on-demand coverage reporting disabled (default behavior, always-on coverage reporting remains enabled)
export COVERAGE="--coverage-check"
fi
if [ -n "${COMPLETE:-}" ]; then
# disable change detection triggered by setting the COMPLETE environment variable to a non-empty value
export CHANGED=""
elif [[ "${COMMIT_MESSAGE}" =~ ci_complete ]]; then
# disable change detection triggered by having 'ci_complete' in the latest commit message
export CHANGED=""
else
# enable change detection (default behavior)
export CHANGED="--changed"
fi
if [ "${IS_PULL_REQUEST:-}" == "true" ]; then
# run unstable tests which are targeted by focused changes on PRs
export UNSTABLE="--allow-unstable-changed"
else
# do not run unstable tests outside PRs
export UNSTABLE=""
fi
if [[ "${COVERAGE:-}" == "--coverage" ]]; then
timeout=60
else
timeout=50
fi
ansible-test env --dump --show --timeout "${timeout}" --color -v
".azure-pipelines/commands/${script}.sh" "${test}"

View File

@ -1 +0,0 @@
remote.sh

View File

@ -1 +0,0 @@
remote.sh

View File

@ -1 +0,0 @@
cloud.sh

View File

@ -1,18 +0,0 @@
#!/usr/bin/env bash
set -o pipefail -eux
declare -a args
IFS='/:' read -ra args <<< "$1"
python="${args[1]}"
if [ "${#args[@]}" -gt 2 ]; then
target="shippable/generic/group${args[2]}/"
else
target="shippable/generic/"
fi
# shellcheck disable=SC2086
ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \
--docker default --python "${python}"

View File

@ -1,14 +0,0 @@
#!/usr/bin/env bash
# Temporary script to support side-by-side testing for incidental code coverage.
# Once collection migration has been completed the incidental tests can be combined with the regular tests.
set -o pipefail -eux
declare -a args
IFS='/:' read -ra args <<< "$1"
script="${args[1]}"
IFS='/' test="${args[*]:1}"
".azure-pipelines/commands/incidental/${script}.sh" "${test}"

View File

@ -1 +0,0 @@
network.sh

View File

@ -1,40 +0,0 @@
#!/usr/bin/env bash
set -o pipefail -eux
declare -a args
IFS='/:' read -ra args <<< "$1"
platform="${args[0]}"
version="${args[1]}"
python_version="${args[2]}"
target="shippable/${platform}/incidental/"
stage="${S:-prod}"
provider="${P:-default}"
# python versions to test in order
# all versions run full tests
IFS=' ' read -r -a python_versions <<< \
"$(PYTHONPATH="${PWD}/test/lib" python -c 'from ansible_test._internal import constants; print(" ".join(constants.CONTROLLER_PYTHON_VERSIONS))')"
if [ "${python_version}" ]; then
# limit tests to a single python version
python_versions=("${python_version}")
fi
for python_version in "${python_versions[@]}"; do
# terminate remote instances on the final python version tested
if [ "${python_version}" = "${python_versions[-1]}" ]; then
terminate="always"
else
terminate="never"
fi
# shellcheck disable=SC2086
ansible-test network-integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \
--platform "${platform}/${version}" \
--docker default --python "${python_version}" \
--remote-terminate "${terminate}" --remote-stage "${stage}" --remote-provider "${provider}"
done

View File

@ -1,52 +0,0 @@
#!/usr/bin/env bash
set -o pipefail -eux
declare -a args
IFS='/:' read -ra args <<< "$1"
version="${args[1]}"
target="shippable/windows/incidental/"
stage="${S:-prod}"
provider="${P:-default}"
# python version to run full tests on while other versions run minimal tests
python_default="$(PYTHONPATH="${PWD}/test/lib" python -c 'from ansible_test._internal import constants; print(constants.CONTROLLER_MIN_PYTHON_VERSION)')"
# version to test when only testing a single version
single_version=2022
# shellcheck disable=SC2086
ansible-test windows-integration --list-targets -v ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} > /tmp/explain.txt 2>&1 || { cat /tmp/explain.txt && false; }
{ grep ' windows-integration: .* (targeted)$' /tmp/explain.txt || true; } > /tmp/windows.txt
if [ -s /tmp/windows.txt ] || [ "${CHANGED:+$CHANGED}" == "" ]; then
echo "Detected changes requiring integration tests specific to Windows:"
cat /tmp/windows.txt
echo "Running Windows integration tests for multiple versions concurrently."
platforms=(
--windows "${version}"
)
else
echo "No changes requiring integration tests specific to Windows were detected."
echo "Running Windows integration tests for a single version only: ${single_version}"
if [ "${version}" != "${single_version}" ]; then
echo "Skipping this job since it is for: ${version}"
exit 0
fi
platforms=(
--windows "${version}"
)
fi
# shellcheck disable=SC2086
ansible-test windows-integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \
"${platforms[@]}" \
--docker default --python "${python_default}" \
--remote-terminate always --remote-stage "${stage}" --remote-provider "${provider}"

View File

@ -1,18 +0,0 @@
#!/usr/bin/env bash
set -o pipefail -eux
declare -a args
IFS='/:' read -ra args <<< "$1"
image="${args[1]}"
if [ "${#args[@]}" -gt 2 ]; then
target="shippable/posix/group${args[2]}/"
else
target="shippable/posix/"
fi
# shellcheck disable=SC2086
ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \
--docker "${image}"

View File

@ -1 +0,0 @@
remote.sh

View File

@ -1,32 +0,0 @@
#!/usr/bin/env bash
set -o pipefail -eux
declare -a args
IFS='/:' read -ra args <<< "$1"
platform="${args[0]}"
version="${args[1]}"
pyver=default
# check for explicit python version like 8.3@3.8
declare -a splitversion
IFS='@' read -ra splitversion <<< "$version"
if [ "${#splitversion[@]}" -gt 1 ]; then
version="${splitversion[0]}"
pyver="${splitversion[1]}"
fi
if [ "${#args[@]}" -gt 2 ]; then
target="shippable/posix/group${args[2]}/"
else
target="shippable/posix/"
fi
stage="${S:-prod}"
provider="${P:-default}"
# shellcheck disable=SC2086
ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \
--python "${pyver}" --remote "${platform}/${version}" --remote-terminate always --remote-stage "${stage}" --remote-provider "${provider}" \

View File

@ -1 +0,0 @@
remote.sh

View File

@ -1,41 +0,0 @@
#!/usr/bin/env bash
set -o pipefail -eux
declare -a args
IFS='/:' read -ra args <<< "$1"
group="${args[1]}"
group2_include=(
ansible-doc
changelog
package-data
pep8
pylint
validate-modules
)
group1_exclude=(
"${group2_include[@]}"
)
options=()
case "${group}" in
1)
for name in "${group1_exclude[@]}"; do
options+=(--skip-test "${name}")
done
;;
2)
for name in "${group2_include[@]}"; do
options+=(--test "${name}")
done
;;
esac
# shellcheck disable=SC2086
ansible-test sanity --color -v --junit ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} \
--docker \
"${options[@]}" --allow-disabled

View File

@ -1 +0,0 @@
remote.sh

View File

@ -1,11 +0,0 @@
#!/usr/bin/env bash
set -o pipefail -eux
declare -a args
IFS='/:' read -ra args <<< "$1"
version="${args[1]}"
# shellcheck disable=SC2086
ansible-test units --color -v --docker default --python "${version}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} \

View File

@ -1,94 +0,0 @@
#!/usr/bin/env bash
set -o pipefail -eux
declare -a args
IFS='/:' read -ra args <<< "$1"
version="${args[1]}"
group="${args[2]}"
target="shippable/windows/group${group}/"
stage="${S:-prod}"
provider="${P:-default}"
# python versions to test in order
IFS=' ' read -r -a python_versions <<< \
"$(PYTHONPATH="${PWD}/test/lib" python -c 'from ansible_test._internal import constants; print(" ".join(constants.CONTROLLER_PYTHON_VERSIONS))')"
# python version to run full tests on while other versions run minimal tests
python_default="$(PYTHONPATH="${PWD}/test/lib" python -c 'from ansible_test._internal import constants; print(constants.CONTROLLER_MIN_PYTHON_VERSION)')"
# version to test when only testing a single version
single_version=2022
# shellcheck disable=SC2086
ansible-test windows-integration --list-targets -v ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} > /tmp/explain.txt 2>&1 || { cat /tmp/explain.txt && false; }
{ grep ' windows-integration: .* (targeted)$' /tmp/explain.txt || true; } > /tmp/windows.txt
if [ -s /tmp/windows.txt ] || [ "${CHANGED:+$CHANGED}" == "" ]; then
echo "Detected changes requiring integration tests specific to Windows:"
cat /tmp/windows.txt
echo "Running Windows integration tests for multiple versions concurrently."
platforms=(
--windows "${version}"
)
else
echo "No changes requiring integration tests specific to Windows were detected."
echo "Running Windows integration tests for a single version only: ${single_version}"
if [ "${version}" != "${single_version}" ]; then
echo "Skipping this job since it is for: ${version}"
exit 0
fi
platforms=(
--windows "${version}"
)
fi
for version in "${python_versions[@]}"; do
changed_all_target="all"
changed_all_mode="default"
if [ "${version}" == "${python_default}" ]; then
# smoketest tests
if [ "${CHANGED}" ]; then
# with change detection enabled run tests for anything changed
# use the smoketest tests for any change that triggers all tests
ci="${target}"
changed_all_target="shippable/windows/smoketest/"
if [ "${target}" == "shippable/windows/group1/" ]; then
# only run smoketest tests for group1
changed_all_mode="include"
else
# smoketest tests already covered by group1
changed_all_mode="exclude"
fi
else
# without change detection enabled run entire test group
ci="${target}"
fi
else
# only run minimal tests for group1
if [ "${target}" != "shippable/windows/group1/" ]; then continue; fi
# minimal tests for other python versions
ci="shippable/windows/minimal/"
fi
# terminate remote instances on the final python version tested
if [ "${version}" = "${python_versions[-1]}" ]; then
terminate="always"
else
terminate="never"
fi
# shellcheck disable=SC2086
ansible-test windows-integration --color -v --retry-on-error "${ci}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \
"${platforms[@]}" --changed-all-target "${changed_all_target}" --changed-all-mode "${changed_all_mode}" \
--docker default --python "${version}" \
--remote-terminate "${terminate}" --remote-stage "${stage}" --remote-provider "${provider}"
done

View File

@ -1,20 +0,0 @@
#!/usr/bin/env bash
# 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 --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

View File

@ -1,59 +0,0 @@
#!/usr/bin/env python
"""
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 annotations
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()

View File

@ -1,24 +0,0 @@
#!/usr/bin/env bash
# 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

View File

@ -1,102 +0,0 @@
#!/usr/bin/env python
"""
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.
"""
from __future__ import annotations
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://ci-files.testing.ansible.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()

View File

@ -1,17 +0,0 @@
#!/usr/bin/env bash
# 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
# Generate stubs using docker (if supported) otherwise fall back to using a virtual environment instead.
# The use of docker is required when Powershell code is present, but Ansible 2.12 was the first version to support --docker with coverage.
ansible-test coverage xml --group-by command --stub --docker --color -v || ansible-test coverage xml --group-by command --stub --venv --color -v

View File

@ -1,34 +0,0 @@
#!/usr/bin/env bash
# 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"

View File

@ -1,24 +0,0 @@
#!/usr/bin/env python
"""Prepends a relative timestamp to each input line from stdin and writes it to stdout."""
from __future__ import annotations
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()

View File

@ -1,29 +0,0 @@
# 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: $[ variables.defaultContainer ]
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)
- bash: .azure-pipelines/scripts/publish-codecov.py "$(outputPath)"
displayName: Publish to codecov.io
condition: gt(variables.coverageFileCount, 0)
continueOnError: true

View File

@ -1,55 +0,0 @@
# 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) }}

View File

@ -1,45 +0,0 @@
# 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(replace(job.test, '/', '_'), '.', '_'), '-', '_'), '@', '_') }}
displayName: ${{ job.name }}
container: $[ variables.defaultContainer ]
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)"

View File

@ -1,5 +0,0 @@
team = "ansible"
repo = "ansible"
check_sha = "f31421576b00f0b167cdbe61217c31c21a41ac02" # the very first commit in repo
fix_commit_msg = false # Don't replace "#" with "GH-"
default_branch = "devel"

View File

@ -1,4 +0,0 @@
# .git-blame-ignore-revs
# Bulk PowerShell sanity fixes
6def4a3180fe03981ba64c6d8db28fed3bb39c0c
716631189cb5a3f66b3add98f39e64e98bc17bf7

1
.gitattributes vendored
View File

@ -1 +0,0 @@
.github/ export-ignore

View File

@ -1,3 +0,0 @@
# Community Code of Conduct
Please see the official [Ansible Community Code of Conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html).

View File

@ -1,70 +0,0 @@
# WELCOME TO ANSIBLE GITHUB
Hi! Nice to see you here!
## QUESTIONS ?
Please see the [Community Guide](https://docs.ansible.com/ansible/latest/community/index.html) for information on how to ask questions on the [mailing lists](https://docs.ansible.com/ansible/latest/community/communication.html#mailing-list-information) and IRC.
The GitHub issue tracker is not the best place for questions for various reasons, but both IRC and the mailing list are very helpful places for those things, as the community page explains best.
## CONTRIBUTING ?
By contributing to this project you agree to the [Developer Certificate of Origin (DCO)](#developer-certificate-of-origin-dco).
The Ansible project is licensed under the [GPL-3.0](COPYING) or later. Some portions of the code fall under other licenses as noted in individual files.
The Ansible project accepts contributions through GitHub pull requests. Please review the [Community Guide](https://docs.ansible.com/ansible/latest/community/index.html) for more information on contributing to Ansible.
## BUG TO REPORT ?
First and foremost, also check the [Community Guide](https://docs.ansible.com/ansible/latest/community/index.html).
You can report bugs or make enhancement requests at the [Ansible GitHub issue page](http://github.com/ansible/ansible/issues/new/choose) by filling out the issue template that will be presented.
Also please make sure you are testing on the latest released version of Ansible or the development branch; see the [Installation Guide](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) for details.
Thanks!
## DEVELOPER CERTIFICATE OF ORIGIN (DCO)
This document was created by the Linux Kernel community and is a simple statement that you, as a contributor, have the legal right to make the contribution.
```text
Developer Certificate of Origin
Version 1.1
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
1 Letterman Drive
Suite D4700
San Francisco, CA, 94129
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
```

View File

@ -1 +0,0 @@
Please raise issues via the [new interface](https://github.com/ansible/ansible/issues/new/choose)

View File

@ -1,265 +0,0 @@
---
name: 🐛 Bug report
description: Create a report to help us improve
body:
- type: markdown
attributes:
value: >
**Thank you for wanting to report a bug in ansible-core!**
⚠
Verify first that your issue is not [already reported on
GitHub][issue search] and keep in mind that we may have to keep
the current behavior because [every change breaks someone's
workflow][XKCD 1172].
We try to be mindful about this.
Also test if the latest release and devel branch are affected too.
**Tip:** If you are seeking community support, please consider
[starting a mailing list thread or chatting in IRC][ML||IRC].
[ML||IRC]:
https://docs.ansible.com/ansible-core/devel/community/communication.html?utm_medium=github&utm_source=issue_form--bug_report.yml#mailing-list-information
[issue search]: ../search?q=is%3Aissue&type=issues
[XKCD 1172]: https://xkcd.com/1172/
- type: textarea
attributes:
label: Summary
description: Explain the problem briefly below.
placeholder: >-
When I try to do X with ansible-core from the devel branch on GitHub, Y
breaks in a way Z under the env E. Here are all the details I know
about this problem...
validations:
required: true
- type: dropdown
attributes:
label: Issue Type
description: >
Please select the single available option in the drop-down.
<details>
<summary>
<em>Why?</em>
</summary>
We would do it by ourselves but unfortunatelly, the curent
edition of GitHub Issue Forms Alpha does not support this yet 🤷
_We will make it easier in the future, once GitHub
supports dropdown defaults. Promise!_
</details>
# FIXME: Once GitHub allows defining the default choice, update this
options:
- Bug Report
validations:
required: true
- type: input
attributes:
label: Component Name
description: >
Write the short name of the rst file, module, plugin, task or
feature below, *use your best guess if unsure*.
**Tip:** Cannot find it in this repository? Please be advised that
the source for some parts of the documentation are hosted outside
of this repository. If the page you are reporting describes
modules/plugins/etc that are not officially supported by the
Ansible Core Engineering team, there is a good chance that it is
coming from one of the [Ansible Collections maintained by the
community][collections org]. If this is the case, please make sure
to file an issue under the appropriate project there instead.
[collections org]: /ansible-collections
placeholder: dnf, apt, pip, user etc.
validations:
required: true
- type: textarea
attributes:
label: Ansible Version
description: >-
Paste verbatim output from `ansible --version` below, under
the prompt line. Please don't wrap it with triple backticks — your
whole input will be turned into a code snippet automatically.
render: console
value: |
$ ansible --version
placeholder: |
$ ansible --version
ansible [core 2.11.0b4.post0] (detached HEAD ref: refs/) last updated 2021/04/02 00:33:35 (GMT +200)
config file = None
configured module search path = ['~/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = ~/src/github/ansible/ansible/lib/ansible
ansible collection location = ~/.ansible/collections:/usr/share/ansible/collections
executable location = bin/ansible
python version = 3.9.0 (default, Oct 26 2020, 13:08:59) [GCC 10.2.0]
jinja version = 2.11.3
libyaml = True
validations:
required: true
- type: textarea
attributes:
label: Configuration
description: >-
Paste verbatim output from `ansible-config dump --only-changed -t all` below, under the prompt line.
(if using a version older than ansible-core 2.12 you should omit the '-t all')
Please don't wrap it with triple backticks — your
whole input will be turned into a code snippet automatically.
render: console
value: |
# if using a version older than ansible-core 2.12 you should omit the '-t all'
$ ansible-config dump --only-changed -t all
placeholder: |
# if using a version older than ansible-core 2.12 you should omit the '-t all'
$ ansible-config dump --only-changed -t all
DEFAULT_GATHERING(~/src/github/ansible/ansible/ansible.cfg) = smart
DEFAULT_HOST_LIST(~/src/github/ansible/ansible/ansible.cfg) = ['~/src/github/ansible/ansible/hosts']
DEFAULT_VAULT_PASSWORD_FILE(~/src/github/ansible/ansible/ansible.cfg) = ~/src/github/ansible/ansible/vault/print-password.sh
validations:
required: true
- type: textarea
attributes:
label: OS / Environment
description: >-
Provide all relevant information below, e.g. target OS versions,
network device firmware, etc.
placeholder: RHEL 8, CentOS Stream etc.
validations:
required: true
- type: textarea
attributes:
label: Steps to Reproduce
description: |
Describe exactly how to reproduce the problem, using a minimal test-case. It would *really* help us understand your problem if you could also pased any playbooks, configs and commands you used.
**HINT:** You can paste https://gist.github.com links for larger files.
value: |
<!--- Paste example playbooks or commands between quotes below -->
```yaml (paste below)
```
placeholder: |
1. Implement the following playbook:
```yaml
---
# ping.yml
- hosts: all
gather_facts: false
tasks:
- ping:
...
```
2. Then run `ANSIBLE_DEBUG=1 ansible-playbook ping.yml -vvvvv`
3. An error occurs.
validations:
required: true
- type: textarea
attributes:
label: Expected Results
description: >-
Describe what you expected to happen when running the steps above.
placeholder: >-
I expected X to happen because I assumed Y and was shocked
that it did not.
validations:
required: true
- type: textarea
attributes:
label: Actual Results
description: |
Describe what actually happened. If possible run with extra verbosity (`-vvvv`).
Paste verbatim command output and don't wrap it with triple backticks — your
whole input will be turned into a code snippet automatically.
render: console
placeholder: >-
Certificate did not match expected hostname: files.pythonhosted.org. Certificate: {'notAfter': 'Apr 28 19:20:25 2021 GMT', 'subjectAltName': ((u'DNS', 'r.ssl.fastly.net'), (u'DNS', '*.catchpoint.com'), (u'DNS', '*.cnn.io'), (u'DNS', '*.dollarshaveclub.com'), (u'DNS', '*.eater.com'), (u'DNS', '*.fastly.picmonkey.com'), (u'DNS', '*.files.saymedia-content.com'), (u'DNS', '*.ft.com'), (u'DNS', '*.meetupstatic.com'), (u'DNS', '*.nfl.com'), (u'DNS', '*.pagar.me'), (u'DNS', '*.picmonkey.com'), (u'DNS', '*.realself.com'), (u'DNS', '*.sbnation.com'), (u'DNS', '*.shakr.com'), (u'DNS', '*.streamable.com'), (u'DNS', '*.surfly.com'), (u'DNS', '*.theverge.com'), (u'DNS', '*.thrillist.com'), (u'DNS', '*.vox-cdn.com'), (u'DNS', '*.vox.com'), (u'DNS', '*.voxmedia.com'), (u'DNS', 'eater.com'), (u'DNS', 'ft.com'), (u'DNS', 'i.gse.io'), (u'DNS', 'picmonkey.com'), (u'DNS', 'realself.com'), (u'DNS', 'static.wixstatic.com'), (u'DNS', 'streamable.com'), (u'DNS', 'surfly.com'), (u'DNS', 'theverge.com'), (u'DNS', 'vox-cdn.com'), (u'DNS', 'vox.com'), (u'DNS', 'www.joyent.com')), 'subject': ((('countryName', u'US'),), (('stateOrProvinceName', u'California'),), (('localityName', u'San Francisco'),), (('organizationName', u'Fastly, Inc'),), (('commonName', u'r.ssl.fastly.net'),))}
Exception:
Traceback (most recent call last):
File "/usr/local/lib/python2.6/dist-packages/pip/basecommand.py", line 215, in main
status = self.run(options, args)
File "/usr/local/lib/python2.6/dist-packages/pip/commands/install.py", line 335, in run
wb.build(autobuilding=True)
File "/usr/local/lib/python2.6/dist-packages/pip/wheel.py", line 749, in build
self.requirement_set.prepare_files(self.finder)
File "/usr/local/lib/python2.6/dist-packages/pip/req/req_set.py", line 380, in prepare_files
ignore_dependencies=self.ignore_dependencies))
File "/usr/local/lib/python2.6/dist-packages/pip/req/req_set.py", line 620, in _prepare_file
session=self.session, hashes=hashes)
File "/usr/local/lib/python2.6/dist-packages/pip/download.py", line 821, in unpack_url
hashes=hashes
File "/usr/local/lib/python2.6/dist-packages/pip/download.py", line 659, in unpack_http_url
hashes)
File "/usr/local/lib/python2.6/dist-packages/pip/download.py", line 853, in _download_http_url
stream=True,
File "/usr/local/lib/python2.6/dist-packages/pip/_vendor/requests/sessions.py", line 521, in get
return self.request('GET', url, **kwargs)
File "/usr/local/lib/python2.6/dist-packages/pip/download.py", line 386, in request
return super(PipSession, self).request(method, url, *args, **kwargs)
File "/usr/local/lib/python2.6/dist-packages/pip/_vendor/requests/sessions.py", line 508, in request
resp = self.send(prep, **send_kwargs)
File "/usr/local/lib/python2.6/dist-packages/pip/_vendor/requests/sessions.py", line 618, in send
r = adapter.send(request, **kwargs)
File "/usr/local/lib/python2.6/dist-packages/pip/_vendor/cachecontrol/adapter.py", line 47, in send
resp = super(CacheControlAdapter, self).send(request, **kw)
File "/usr/local/lib/python2.6/dist-packages/pip/_vendor/requests/adapters.py", line 506, in send
raise SSLError(e, request=request)
SSLError: HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Max retries exceeded with url: /packages/ef/ab/aa12712415809bf698e719b307419f953e25344e8f42d557533d7a02b276/netapp_lib-2020.7.16-py2-none-any.whl (Caused by SSLError(CertificateError("hostname 'files.pythonhosted.org' doesn't match either of 'r.ssl.fastly.net', '*.catchpoint.com', '*.cnn.io', '*.dollarshaveclub.com', '*.eater.com', '*.fastly.picmonkey.com', '*.files.saymedia-content.com', '*.ft.com', '*.meetupstatic.com', '*.nfl.com', '*.pagar.me', '*.picmonkey.com', '*.realself.com', '*.sbnation.com', '*.shakr.com', '*.streamable.com', '*.surfly.com', '*.theverge.com', '*.thrillist.com', '*.vox-cdn.com', '*.vox.com', '*.voxmedia.com', 'eater.com', 'ft.com', 'i.gse.io', 'picmonkey.com', 'realself.com', 'static.wixstatic.com', 'streamable.com', 'surfly.com', 'theverge.com', 'vox-cdn.com', 'vox.com', 'www.joyent.com'",),))
ERROR: Command "/usr/bin/python2.6 /root/ansible/test/lib/ansible_test/_data/quiet_pip.py install --disable-pip-version-check -r /root/ansible/test/lib/ansible_test/_data/requirements/units.txt -r tests/unit/requirements.txt -c /root/ansible/test/lib/ansible_test/_data/requirements/constraints.txt" returned exit status 2.
ERROR: Command "docker exec d47eb360db4ce779c1f690db964655b76e68895c4360ff252c46fe7fe6f5c75a /usr/bin/env ANSIBLE_TEST_CONTENT_ROOT=/root/ansible_collections/netapp/ontap LC_ALL=en_US.UTF-8 /usr/bin/python3.6 /root/ansible/bin/ansible-test units --metadata tests/output/.tmp/metadata-9i2qfrcl.json --truncate 200 --redact --color yes --requirements --python default --requirements-mode only" returned exit status 1.
validations:
required: true
- type: markdown
attributes:
value: >
*One last thing...*
*Please, complete **all** sections as described, this form
is [processed automatically by a robot][ansibot help].*
Thank you for your collaboration!
[ansibot help]:
/ansible/ansibotmini#ansibotmini
- type: checkboxes
attributes:
label: Code of Conduct
description: |
Read the [Ansible Code of Conduct][CoC] first.
[CoC]: https://docs.ansible.com/ansible/latest/community/code_of_conduct.html?utm_medium=github&utm_source=issue_form--bug_report.yml
options:
- label: I agree to follow the Ansible Code of Conduct
required: true
...

View File

@ -1,26 +0,0 @@
# Ref: https://help.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository#configuring-the-template-chooser
blank_issues_enabled: false # default: true
contact_links:
- name: 🔐 Security bug report 🔥
url: https://docs.ansible.com/ansible/latest/community/reporting_bugs_and_features.html?utm_medium=github&utm_source=issue_template_chooser
about: |
Please learn how to report security vulnerabilities here.
For all security related bugs, email security@ansible.com
instead of using this issue tracker and you will receive
a prompt response.
For more information, see
https://docs.ansible.com/ansible/latest/community/reporting_bugs_and_features.html
- name: 📝 Ansible Code of Conduct
url: https://docs.ansible.com/ansible/latest/community/code_of_conduct.html?utm_medium=github&utm_source=issue_template_chooser
about: ❤ Be nice to other members of the community. ☮ Behave.
- name: 💬 Talks to the community
url: https://docs.ansible.com/ansible/latest/community/communication.html?utm_medium=github&utm_source=issue_template_chooser#mailing-list-information
about: Please ask and answer usage questions here
- name: ⚡ Working groups
url: https://github.com/ansible/community/wiki
about: Interested in improving a specific area? Become a part of a working group!
- name: 💼 For Enterprise
url: https://www.ansible.com/products/engine?utm_medium=github&utm_source=issue_template_chooser
about: Red Hat offers support for the Ansible Automation Platform

View File

@ -1,212 +0,0 @@
---
name: 📝 Documentation Report
description: Ask us about docs
body:
- type: markdown
attributes:
value: >
**Thank you for wanting to report a problem with ansible-core
documentation!**
Please fill out your suggestions below. If the problem seems
straightforward, feel free to go ahead and
[submit a pull request] instead!
⚠
Verify first that your issue is not [already reported on
GitHub][issue search].
Also test if the latest release and devel branch are affected too.
**Tip:** If you are seeking community support, please consider
[starting a mailing list thread or chatting in IRC][ML||IRC].
[ML||IRC]:
https://docs.ansible.com/ansible-core/devel/community/communication.html?utm_medium=github&utm_source=issue_form--documentation_report.yml#mailing-list-information
[issue search]: ../search?q=is%3Aissue&type=issues
[submit a pull request]:
https://docs.ansible.com/ansible-core/devel/community/documentation_contributions.html
- type: markdown
attributes:
value: >
**Check the repository for your issue.**
Source files for Ansible community documentation are
hosted in different repositories. Please make sure to file an
issue in the correct project.
Documentation for modules/plugins/etc that are officially
supported by the Ansible Core Engineering team is available
in this (`ansible/ansible`) repository.
The Installation Guide, Playbook Guide, Developer Guide,
and other documentation is available in the
[ansible/ansible-documentation] repository.
Documentation for other modules/plugins/etc is likely to be
available in one of the [Ansible Collections][collections index].
If available in the collection documentation, select the
**Issue Tracker** button to go directly to the GitHub issues.
[ansible/ansible-documentation]: /ansible/ansible-documentation
[collections index]:
https://docs.ansible.com/ansible/latest/collections/index.html
- type: textarea
attributes:
label: Summary
description: >
Explain the problem briefly below, add suggestions to wording
or structure.
**HINT:** Did you know the documentation has a `View on GitHub`
link on some pages? Feel free to use it to start a pull request
right from the GitHub UI!
placeholder: >-
I was reading the ansible-core documentation of version X and I'm having
problems understanding Y. It would be very helpful if that got
rephrased as Z.
validations:
required: true
- type: dropdown
attributes:
label: Issue Type
description: >
Please select the single available option in the drop-down.
<details>
<summary>
<em>Why?</em>
</summary>
_We will make it easier in the future, once GitHub
supports dropdown defaults. Promise!_
</details>
# FIXME: Once GitHub allows defining the default choice, update this
options:
- Documentation Report
validations:
required: true
- type: input
attributes:
label: Component Name
description: >
Write the short name of the rst file, module, plugin, task or
feature below, *use your best guess if unsure*.
placeholder: lib/ansible/modules/copy.py
validations:
required: true
- type: textarea
attributes:
label: Ansible Version
description: >-
Paste verbatim output from `ansible --version` below, under
the prompt line. Please don't wrap it with triple backticks — your
whole input will be turned into a code snippet automatically.
render: console
value: |
$ ansible --version
placeholder: |
$ ansible --version
ansible [core 2.11.0b4.post0] (detached HEAD ref: refs/) last updated 2021/04/02 00:33:35 (GMT +200)
config file = None
configured module search path = ['~/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = ~/src/github/ansible/ansible/lib/ansible
ansible collection location = ~/.ansible/collections:/usr/share/ansible/collections
executable location = bin/ansible
python version = 3.9.0 (default, Oct 26 2020, 13:08:59) [GCC 10.2.0]
jinja version = 2.11.3
libyaml = True
validations:
required: true
- type: textarea
attributes:
label: Configuration
description: >-
Paste verbatim output from `ansible-config dump --only-changed -t all` below, under the prompt line.
(if using a version older than ansible-core 2.12 you should omit the '-t all')
Please don't wrap it with triple backticks — your
whole input will be turned into a code snippet automatically.
render: console
value: |
# if using a version older than ansible-core 2.12 you should omit the '-t all'
$ ansible-config dump --only-changed -t all
placeholder: |
# if using a version older than ansible-core 2.12 you should omit the '-t all'
$ ansible-config dump --only-changed -t all
DEFAULT_GATHERING(~/src/github/ansible/ansible/ansible.cfg) = smart
DEFAULT_HOST_LIST(~/src/github/ansible/ansible/ansible.cfg) = ['~/src/github/ansible/ansible/hosts']
DEFAULT_VAULT_PASSWORD_FILE(~/src/github/ansible/ansible/ansible.cfg) = ~/src/github/ansible/ansible/vault/print-password.sh
validations:
required: true
- type: textarea
attributes:
label: OS / Environment
description: >-
Provide all relevant information below, e.g. OS version,
browser, etc.
placeholder: Fedora 33, Firefox etc.
validations:
required: true
- type: textarea
attributes:
label: Additional Information
description: |
Describe how this improves the documentation, e.g. before/after situation or screenshots.
**HINT:** You can paste https://gist.github.com links for larger files.
placeholder: >-
When the improvement is applied, it makes it more straightforward
to understand X.
validations:
required: true
- type: markdown
attributes:
value: >
*One last thing...*
*Please, complete **all** sections as described, this form
is [processed automatically by a robot][ansibot help].*
Thank you for your collaboration!
[ansibot help]:
/ansible/ansibotmini#ansibotmini
- type: checkboxes
attributes:
label: Code of Conduct
description: |
Read the [Ansible Code of Conduct][CoC] first.
[CoC]: https://docs.ansible.com/ansible/latest/community/code_of_conduct.html?utm_medium=github&utm_source=issue_form--documentation_report.yml
options:
- label: I agree to follow the Ansible Code of Conduct
required: true
...

View File

@ -1,192 +0,0 @@
---
name: ✨ Feature request
description: Suggest an idea for this project
body:
- type: markdown
attributes:
value: >
**Thank you for wanting to suggest a feature for ansible-core!**
💡
Before you go ahead with your request, please first consider if it
would be useful for majority of the ansible-core users. As a
general rule of thumb, any feature that is only of interest to a
small sub group should be [implemented in a third-party Ansible
Collection][contribute to collections] or maybe even just your
project alone. Be mindful of the fact that the essential
ansible-core features have a broad impact.
If unsure, consider filing a [new proposal] instead outlining your
use-cases, the research and implementation considerations. Then,
start a discussion on one of the public [IRC meetings] we have just
for this.
<details>
<summary>
❗ Every change breaks someone's workflow.
</summary>
[![❗ Every change breaks someone's workflow.
](https://imgs.xkcd.com/comics/workflow.png)
](https://xkcd.com/1172/)
</details>
⚠
Verify first that your idea is not [already requested on
GitHub][issue search].
Also test if the devel branch does not already implement this.
**Tip:** If you are seeking community support, please consider
[starting a mailing list thread or chatting in IRC][ML||IRC].
[contribute to collections]:
https://docs.ansible.com/ansible-core/devel/community/contributing_maintained_collections.html?utm_medium=github&utm_source=issue_form--feature_request.yml
[IRC meetings]:
https://docs.ansible.com/ansible-core/devel/community/communication.html?utm_medium=github&utm_source=issue_form--feature_request.yml#irc-meetings
[issue search]: ../search?q=is%3Aissue&type=issues
[ML||IRC]:
https://docs.ansible.com/ansible-core/devel/community/communication.html?utm_medium=github&utm_source=issue_form--feature_request.yml#mailing-list-information
[new proposal]: ../../proposals/issues/new
- type: textarea
attributes:
label: Summary
description: >
Describe the new feature/improvement you would like briefly below.
What's the problem this feature will solve?
What are you trying to do, that you are unable to achieve
with ansible-core as it currently stands?
* Provide examples of real-world use cases that this would enable
and how it solves the problem you described.
* How do you solve this now?
* Have you tried to work around the problem using other tools?
* Could there be a different approach to solving this issue?
*Know **exactly** what you want?* Consider filing a [new proposal]
instead outlining your research and implementation considerations.
[new proposal]: ../../proposals/issues/new
placeholder: >-
I am trying to do X with ansible-core from the devel branch on GitHub and
I think that implementing a feature Y would be very helpful for me and
every other user of ansible-core because of Z.
validations:
required: true
- type: dropdown
attributes:
label: Issue Type
description: >
Please select the single available option in the drop-down.
<details>
<summary>
<em>Why?</em>
</summary>
We would do it by ourselves but unfortunatelly, the curent
edition of GitHub Issue Forms Alpha does not support this yet 🤷
_We will make it easier in the future, once GitHub
supports dropdown defaults. Promise!_
</details>
# FIXME: Once GitHub allows defining the default choice, update this
options:
- Feature Idea
validations:
required: true
- type: input
attributes:
label: Component Name
description: >
Write the short name of the module, plugin, task or feature below,
*use your best guess if unsure*.
Be aware that a lot of content that used to reside in this repository
previously, is now hosted under [individual collection
projects][collections org].
If this is the case, please make sure to file an issue under the
appropriate project there instead.
[collections org]: /ansible-collections
placeholder: dnf, apt, pip, user etc.
validations:
required: true
- type: textarea
attributes:
label: Additional Information
description: |
Describe how the feature would be used, why it is needed and what it would solve.
**HINT:** You can paste https://gist.github.com links for larger files.
value: |
<!--- Paste example playbooks or commands between quotes below -->
```yaml (paste below)
```
placeholder: >-
I asked on https://stackoverflow.com/.... and the community
advised me to do X, Y and Z.
validations:
required: true
- type: markdown
attributes:
value: >
*One last thing...*
*Please, complete **all** sections as described, this form
is [processed automatically by a robot][ansibot help].*
Thank you for your collaboration!
[ansibot help]:
/ansible/ansibotmini#ansibotmini
- type: checkboxes
attributes:
label: Code of Conduct
description: |
Read the [Ansible Code of Conduct][CoC] first.
[CoC]: https://docs.ansible.com/ansible/latest/community/code_of_conduct.html?utm_medium=github&utm_source=issue_form--feature_request.yml
options:
- label: I agree to follow the Ansible Code of Conduct
required: true
...

View File

@ -1 +0,0 @@
PULL_REQUEST_TEMPLATE/Unclear purpose or motivation.md

View File

@ -1,20 +0,0 @@
##### SUMMARY
<!--- Describe the change below, including rationale and design decisions -->
<!--- HINT: Include "Fixes #nnn" if you are fixing an existing issue -->
##### ISSUE TYPE
- Bugfix Pull Request
##### ADDITIONAL INFORMATION
<!--- Include additional information to help people understand the change here -->
<!--- A step-by-step reproduction of the problem is helpful if there is no related issue -->
<!--- Paste verbatim command output below, e.g. before and after your change -->
```paste below
```

View File

@ -1,19 +0,0 @@
##### SUMMARY
<!--- Describe the change below, including rationale -->
<!--- HINT: Include "Closes #nnn" if you are fixing an existing issue -->
##### ISSUE TYPE
- Docs Pull Request
##### ADDITIONAL INFORMATION
<!--- Include additional information to help people understand the change here -->
<!--- Paste verbatim command output below, e.g. before and after your change -->
```paste below
```

View File

@ -1,19 +0,0 @@
##### SUMMARY
<!--- Describe the change below, including rationale and design decisions -->
<!--- HINT: Include "Resolves #nnn" if you are fixing an existing issue -->
##### ISSUE TYPE
- Feature Pull Request
##### ADDITIONAL INFORMATION
<!--- Include additional information to help people understand the change here -->
<!--- Paste verbatim command output below, e.g. before and after your change -->
```paste below
```

View File

@ -1 +0,0 @@
Unclear purpose or motivation.md

View File

@ -1,20 +0,0 @@
##### SUMMARY
<!--- Describe the change below, including rationale and design decisions -->
<!--- HINT: Include "Closes #nnn" if you are fixing an existing issue -->
##### ISSUE TYPE
- Test Pull Request
##### ADDITIONAL INFORMATION
<!--- Include additional information to help people understand the change here -->
<!--- A step-by-step reproduction of the problem is helpful if there is no related issue -->
<!--- Paste verbatim command output below, e.g. before and after your change -->
```paste below
```

View File

@ -1,25 +0,0 @@
##### SUMMARY
<!--- Describe the change below, including rationale and design decisions -->
<!--- HINT: Include "Fixes #nnn" if you are fixing an existing issue -->
##### ISSUE TYPE
<!--- Pick one below and delete the rest -->
- Bugfix Pull Request
- Docs Pull Request
- Feature Pull Request
- Test Pull Request
##### ADDITIONAL INFORMATION
<!--- Include additional information to help people understand the change here -->
<!--- A step-by-step reproduction of the problem is helpful if there is no related issue -->
<!--- Paste verbatim command output below, e.g. before and after your change -->
```paste below
```

View File

@ -1,18 +0,0 @@
2.17.0 Gallows Pole
2.16.0 All My Love
2.15.0 Ten Years Gone
2.14.0 C'mon Everybody
2.13.0 Nobody's Fault but Mine
2.12.0 Dazed and Confused
2.11.0 Hey Hey, What Can I Do
2.10.0 When the Levee Breaks
2.9.0 Immigrant Song
2.8.0 How Many More Times
2.7.0 In the Light
2.6.0 Heartbreaker
2.5.0 Kashmir
2.4.0 Dancing Days
2.3.0 Ramble On
2.2.0 The Battle of Evermore
2.1.0 The Song Remains the Same
2.0.0 Over the Hills and Far Away

15
.github/SECURITY.md vendored
View File

@ -1,15 +0,0 @@
# Security Policy
## Supported Versions
Ansible applies security fixes according to the 3-versions-back support
policy. Please find more information in [our docs](
https://docs.ansible.com/ansible/devel/reference_appendices/release_and_maintenance.html#release-status
).
## Reporting a Vulnerability
We encourage responsible disclosure practices for security
vulnerabilities. Please read our [policies for reporting bugs](
https://docs.ansible.com/ansible/devel/community/reporting_bugs_and_features.html#reporting-a-bug
) if you want to report a security issue that might affect Ansible.

107
.gitignore vendored
View File

@ -2,10 +2,9 @@
*.py[co]
build
AUTHORS.TXT
# Emacs backup and autosave files...
# Emacs backup files...
*~
.\#*
\#*
# RPM stuff...
MANIFEST
dist
@ -17,108 +16,26 @@ rpm-build
.idea
#IntelliJ IDEA stuff..
*.iml
#VSCode stuff..
.vscode/
# Mac OS X stuff...
.DS_Store
# manpage build stuff...
docs/man/man1/ansible*.1
docs/man/man1/ansible*.1.asciidoc.in
docs/man/man3/*
# Sublime stuff
*.sublime-project
*.sublime-workspace
# docsite stuff...
docs/docsite/_build
docs/docsite/*.html
docs/docsite/htmlout
docs/docsite/rst/conf.py
docs/docsite/rst/index.rst
docs/docsite/rst/cli/ansible-*.rst
docs/docsite/rst/cli/ansible.rst
docs/docsite/rst/dev_guide/collections_galaxy_meta.rst
docs/docsite/rst/dev_guide/testing/sanity/index.rst.new
docs/docsite/rst/dev_guide/index.rst
docs/docsite/rst/modules/*.rst
docs/docsite/rst/collections/*.rst
!docs/docsite/rst/collections/all_plugins.rst
docs/docsite/rst/collections/*/*.rst
docs/docsite/rst/playbooks_directives.rst
docs/docsite/rst/plugins_by_category.rst
docs/docsite/rst/plugins/*/*.rst
docs/docsite/rst/reference_appendices/config.rst
docs/docsite/rst/reference_appendices/playbooks_keywords.rst
docs/docsite/rst_warnings
docs/docsite/searchindex.js
docs/docsite/_static/*.gif
docs/docsite/_static/*.png
docs/docsite/_static/websupport.js
docsite/rst/modules_by_category.rst
docsite/rst/list_of_*.rst
docsite/rst/*_module.rst
docsite/*.html
docsite/_static/*.gif
docsite/_static/*.png
docsite/_static/websupport.js
docsite/searchindex.js
docsite/htmlout
# deb building stuff...
debian/
# Vim swap files
*.swp
*.swo
[._]*.un~
credentials.yml
# test output
*.retry
*.out
.pytest_cache/
.tox
.cache
.pytest_cache
results.xml
coverage.xml
/test/units/cover-html
/test/integration/inventory
/test/integration/targets/*/backup/
/test/cache/*
# Development
/test/develop
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
venv
env
Vagrantfile
.vagrant
# Backwards compatibility with `stable-2.9` and earlier branches.
# Also used in the `devel` branch during early Ansible 2.10 development.
/lib/ansible.egg-info/
# First used in the `devel` branch during Ansible 2.10 development.
/lib/ansible_base.egg-info/
# First used in the `devel` branch during Ansible 2.11 development.
/lib/ansible_core.egg-info/
# vendored lib dir
lib/ansible/_vendor/*
!lib/ansible/_vendor/__init__.py
# test stuff
/test/integration/cloud-config-*.*
!/test/integration/cloud-config-*.*.template
.python-version
# Release directory
packaging/release/ansible_release
/.cache/
/test/results/
/test/integration/cloud-config-aws.yml
/test/integration/inventory.networking
/test/integration/inventory.winrm
/test/integration/cloud-config-aws.yml
/test/integration/cloud-config-cs.ini
# python 'rope' stuff
.ropeproject
# local 'ack' config files
.ackrc
# default 'coverage html' results
htmlcov/
# default 'coverage' tool data
.coverage
# ansible-test coverage results
test/units/.coverage.*
/test/integration/cloud-config-azure.yml
/SYMLINK_CACHE.json
changelogs/.plugin-cache.yaml
.ansible-test-timeout.json

View File

@ -1,36 +0,0 @@
Michael DeHaan <michael.dehaan@gmail.com> <michael@ansibleworks.com>
Michael DeHaan <michael.dehaan@gmail.com> Michael DeHaan <michael@ansibleworks.com>
Michael DeHaan <michael.dehaan@gmail.com> <michael@ansible.com>
<bcoca@ansible.com> <brian.coca+git@gmail.com>
<bcoca@ansible.com> <briancoca+ansible@gmail.com>
<bcoca@ansible.com> <briancoca+dev@gmail.com>
<bcoca@ansible.com> <bcoca@tablethotels.com>
<a.badger@gmail.com> <toshio@fedoraproject.org>
James Tanner <tanner.jc@gmail.com>
<jimi@sngx.net> <jcammarata@ansibleworks.com>
Michael Scherer <misc@zarb.org> mscherer <misc@zarb.org>
<misc@zarb.org> <misc@ephaone.org>
<misc@zarb.org> <mscherer@users.noreply.github.com>
James Martin <jmartin@ansible.com> <jmartin@basho.com>
James Laska <jlaska@ansible.com> <jlaska@redhat.com>
James Laska <jlaska@ansible.com> <jlaska@ansibleworks.com>
James Laska <jlaska@ansible.com> <jlaska@James-Laskas-MacBook-Pro.local>
James Laska <jlaska@ansible.com> <jlaska@users.noreply.github.com>
Jason McKerr <mckerrj@gmail.com> <jmckerr@jmckerr-OSX.local>
Chris Houseknecht <chouseknecht@ansible.com>
Chris Houseknecht <chouseknecht@ansible.com> chouseknecht <chouse@ansible.com>
Chris Houseknecht <chouseknecht@ansible.com> Chris Houseknecht <chouse@ansibleworks.com>
Stephen Fromm <sfromm@gmail.com> Stephen Fromm <stephenf@nero.net>
Sandra Wills <docschick@ansible.com> Sandra Wills <swills@ansible.com>
Will Thames <will@thames.id.au> willthames <will@thames.id.au>
Will Thames <will@thames.id.au> Will Thames <willdthames@gmail.com>
Will Thames <will@thames.id.au> willthames <willdthames@gmail.com>
Will Thames <will@thames.id.au> willthames <will@musc.org.uk>
Will Thames <will@thames.id.au> u348095 <will.thames@suncorp.com.au>
Will Thames <will@thames.id.au> willthames <will.thames@suncorp.com.au>
Will Thames <will@thames.id.au> Will Thames <will.thames@xvt.com.au>
nitzmahone <mdavis@ansible.com> Matt Davis <nitzmahone@users.noreply.github.com>
Dag Wieers <dag@wieers.com> Dag Wieërs <dag@wieers.com>
Dag Wieers <dag@wieers.com> Dag Wieers <dag.wieers@gmail.com>
Rene Moser <mail@renemoser.net> René Moser <mail@renemoser.net>
Rene Moser <mail@renemoser.net> Rene Moser <rene.moser@swisstxt.ch>

1179
CHANGELOG.md Normal file

File diff suppressed because it is too large Load Diff

304
CODING_GUIDELINES.md Normal file
View File

@ -0,0 +1,304 @@
Coding Guidelines
=================
Hi! Thanks for interest in contributing to Ansible.
Here are some guidelines for contributing code. The purpose of this document are to establish what we're looking for in code contributions, and to make sure
new contributions know some of the conventions that we've been using.
We don't think much of this should be too strange to readers familiar with contributing to Python projects, though it helps if we all get on the same page.
Language
========
* While not all components of Ansible must be in Python, core contributions to the Ansible repo must be written in Python. This is to maximize the ability of everyone to contribute.
* If you want to write non-Python ansible modules or inventory scripts, that's fine, but they are not going to get merged in most likely. Sorry!!
PEP8 and basic style checks
===========================
* PEP8 is a great Python style guide, which you should read.
* PEP8 must not be strictly followed in all aspects, but most of it is good advice
* In particular, we don't really care about line lengths. Buy a bigger monitor!
* To run checks for things we care about, run "make pep8"
* Similarly, additional checks can be made with "make pyflakes"
* There is no need to submit code changes for pep8 and pyflake fixes, as these break attribution history. Project leadership will make these periodically.
* Do not submit pull requests that simply adjust whitespace in the code
Testing
=======
* Much of ansible's testing needs are in integration, not unit tests. Add module tests there.
* That being said, there are unit tests too!
* Code written must absolutely pass tests (i.e. "make tests")
* You should anticipate any error paths in your code and test down those error paths.
* Additions to tests for core code is welcome, but not always possible. Be sure things are at least well tested manually in that case.
Whitespace
==========
* Four space indent is strictly required
* Include meaningful whitespace between lines of code
Shebang Lines
=============
* /usr/bin/scripts should start with '/usr/bin/env python'
* module code should still use '/usr/bin/python' as this is replaced automatically by 'ansible_python_interpreter', see the FAQ in the docs for more info.
Comments
========
* Readability is one of the most important goals for this project
* Comment any non-trivial code where someone might not know why you are doing something in a particular way
* Though if something should be commented, that's often a sign someone should write a function
* All new functions must have a basic docstring comment
* Commenting above a line is preferable to commenting at the end of a line
Classes
=======
* With the exception of module code (where inline is better), it is desirable to see classes in their own files.
* Classes should generally not cause side effects as soon as they are instantiated, move meaningful behavior to methods rather than constructors.
Functions and Methods
=====================
* In general, functions should not be 'too long' and should describe a meaningful amount of work
* When code gets too nested, that's usually the sign the loop body could benefit from being a function
* Functions should have names that describe what they do, along with docstrings
* Functions should be named with_underscores
Variables
=========
* Use descriptive variable names instead of variables like 'x', unless x is a obvious loop index
* Ansible python code uses identifiers like 'ClassesLikeThis and variables_like_this
* Module parameters should also use_underscores and not runtogether
Misc Preferences
================
Use the dict constructor where possible when allocating dictionaries:
# not this:
foo = {
'a' : 12,
'b' : 34
}
# this:
foo = dict(
a = 12,
b = 34
)
Line up variables
# not this
a = 12
foosball = 34
xyz = 'dog'
# this
a = 12
foosball = 34
xyz = 'dog'
Don't use line continuations:
# no
if (this_is_a_very_long_line and foo and /
i_am_going_to_continue_it):
bar()
# better:
if (this_is_a_very_long_line and foo and i_am_going_to_continue_it):
bar()
Spacing:
# no
x=[1,2,3]
# no
x = [1,2,3]
# yes
x = [ 1, 2, 3 ]
Spacing continued:
# no
x=foo(12)
# no
x = foo( 12 )
# yes
x = foo(12)
Licenses
========
Every file should have a license header, including the copyright of the original author. Major additions to the module are allowed
to add an additional copyright line, and this is especially true of rewrites, but original authorship copyright messages should be preserved.
All contributions to the core repo should preserve original licenses and new contributions must include the GPLv3 header.
Module Documentation
====================
All module pull requests must include a DOCUMENTATION docstring (YAML format, see other modules for examples) as well as an EXAMPLES docstring, which
is free form.
When adding new modules, any new parameter must have a "version_added" attribute. When submitting a new module, the module should have a "version_added"
attribute in the pull request as well, set to the current development version.
Be sure to check grammar and spelling.
It's frequently the case that modules get submitted with YAML that isn't valid, so you can run "make webdocs" from the checkout to preview your module's documentation.
If it fails to build, take a look at your DOCUMENTATION string or you might have a Python syntax error in there too.
Python Imports
==============
To make it clear what a module is importing, imports should not be sprinkled throughout the code.
Python Imports should happen at the top of the file, exempting code from module_utils.
When a conditional runtime import is required, do so something like this instead:
HAS_FOO = False
try:
import foo
HAS_FOO = True
except ImportError:
pass
...
if not HAS_FOO:
raise Exception("the foo library is required")
This makes it clear what optional dependencies are but allows this to be deferred until runtime. In the case of module code, the raising of the Exception will be replaced
with a "module.exit_json" call.
Exceptions
==========
In the main body of the code, use typed exceptions where possible:
# not this
raise Exception("panic!")
# this
from ansible import errors
...
raise errors.AnsibleError("panic!")
Similarly, exception checking should be fine grained:
# not this
try:
foo()
except:
bar()
# but this
try:
foo()
except SomeTypedException:
bar()
List Comprehensions
===================
In general list comprehensions are always preferred to map() and filter() calls.
However, they can be abused. Optimize for readability, and avoid nesting them too deeply.
Regexes
=======
There is a time and place for them, but here's an illustrative joke.
"A developer had a problem, and used a regular expression to solve it. Now the developer had two problems".
Often regexes are difficult to maintain, and a trusty call to other string operations can be a great solution, faster,
and more readable.
File Conventions
================
If a piece of code looks for a named YAML file in a directory, it should assume it can take no extension, or an extension of '.yml' or '.yaml'.
This should be true against all code that loads files.
Any code that uses directories should consider the possibility that the directory may be symlink.
New Ansible language parameters
===============================
If adding a new parameter, like 'can_fizzbuzz: True/False' be sure the value of the parameter is templated somewhere in the Runner code, as if anything can be parameterized in Ansible,
there is a user that will try to parameterize it.
String Find
===========
Use 'in':
# not this:
if x.find('foo') != -1:
# this:
if 'foo' in x:
String checks
=============
To test if something is a string, consider that it may be unicode.
# no
if type(x) == str:
# yes
if isinstance(x, basestring):
Cleverness
==========
Ansible's code is intended to be read by as many people as possible, so we don't particularly encourage clever or heavily idiomatic code.
In particular, metaclasses are probably not appropriate, however entertaining they may be to add.
Git Practices
=============
Pull requests cannot be accepted that contain merge commits.
Always do "git pull --rebase" and "git rebase" vs "git pull" or "git merge".
Always create a new branch for each pull request to avoid intertwingling different features or fixes on the same branch.
Python Version Compliance
=========================
All code in Ansible core must support a minimum version of Python 2.6.
Module code must support a minimum of Python 2.4, with occasional exception for modules that require code that themselves require 2.6 and later.
A quick reminder is that list comprehensions in Python 2.4 are not as fully fleshed out, there are no 'dict' comprehensions, and there is no 'with' statement.
But otherwise it's pretty much all the same.
The End
=======
This was not meant to be a scary document, so we hope it wasn't, but we also hope this helps you write code that is easier to maintain by others in the future.
If you have questions about this document, please ask on the ansible-devel mailing list.
Thank you!

183
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,183 @@
Ansible Community Information
==============================
The purpose of the Ansible community is to unite developers, system administrators, operations, and
IT managers to share and build great automation solutions. This document contains all sorts of
information about how to contribute and interact with Ansible. Welcome!
Ways to Interact
================
There are a lot of ways to join and be a part of the Ansible community, such as:
Sharing Ansible with Others
---------------------------
You can help share Ansible with others by telling friends and colleagues, writing a blog post,
or presenting at user groups (like DevOps groups or the local LUG or BUG). You are also
welcome to share slides on speakerdeck, sign up for a free account and tag it “Ansible”. On Twitter,
you can also share things with #ansible and may wish
to follow [@Ansible](https://twitter.com/ansible).
Sharing Content and Tips
------------------------
Join the [Ansible project mailing list](https://groups.google.com/forum/#!forum/ansible-project) and you
can share playbooks you may have written and other interesting implementation stories. Put your Ansible
content up on places like github to share with others.
Sharing A Feature Idea
----------------------
If you have an idea for a new feature, you can open a new ticket at
[github.com/ansible/ansible](https://github.com/ansible/ansible), though in general we like to
talk about feature ideas first and bring in lots of people into the discussion. Consider stopping
by the
[Ansible project mailing list](https://groups.google.com/forum/#!forum/ansible-project) ([Subscribe](https://groups.google.com/forum/#!forum/ansible-project/join))
or #ansible on irc.freenode.net. There is an overview about more mailing lists
later in this document.
Helping with Documentation
--------------------------
Ansible documentation is a community project too! If you would like to help with the
documentation, whether correcting a typo or improving a section, or maybe even
documenting a new feature, submit a github pull request to the code that
lives in the “docsite/latest/rst” subdirectory of the project. Docs are in restructured text
format. If you aren’t comfortable with restructured text, you can also open a ticket on
github about any errors you spot or sections you would like to see added. For more information
on creating pull requests, please refer to the
[github help guide](https://help.github.com/articles/using-pull-requests).
Contributing Code (Features or Bugfixes)
----------------------------------------
The Ansible project keeps it’s source on github at
[github.com/ansible/ansible](http://github.com/ansible/ansible)
and takes contributions through
[github pull requests](https://help.github.com/articles/using-pull-requests).
It is usually a good idea to join the ansible-devel list to discuss any large features prior to submission, and this
especially helps in avoiding duplicate work or efforts where we decide, upon seeing a pull request for the first
time, that revisions are needed. (This is not usually needed for module development)
When submitting patches, be sure to run the unit tests first “make tests” and always use
“git rebase” vs “git merge” (aliasing git pull to git pull --rebase is a great idea) to
avoid merge commits in your submissions. We will require resubmission of pull requests that
contain merge commits.
We’ll then review your contributions and engage with you about questions and so on. Please be
advised we have a very large and active community, so it may take awhile to get your contributions
in! Patches should be made against the 'devel' branch.
Contributions can be for new features like modules, or to fix bugs you or others have found. If you
are interested in writing new modules to be included in the core Ansible distribution, please refer
to the [Module Developers documentation on our website](http://docs.ansible.com/developing_modules.html).
Ansible's aesthetic encourages simple, readable code and consistent, conservatively extending,
backwards-compatible improvements. Code developed for Ansible needs to support Python 2.6+,
while code in modules must run under Python 2.4 or higher. Please also use a 4-space indent
and no tabs.
Tip: To easily run from a checkout, source "./hacking/env-setup" and that's it -- no install
required. You're now live!
Reporting A Bug
---------------
Bugs should be reported to [github.com/ansible/ansible](http://github.com/ansible/ansible) after
signing up for a free github account. Before reporting a bug, please use the bug/issue search
to see if the issue has already been reported.
When filing a bug, please use the [issue template](https://raw2.github.com/ansible/ansible/devel/examples/issues/ISSUE_TEMPLATE.md) to provide all relevant information.
Do not use the issue tracker for "how do I do this" type questions. These are great candidates
for IRC or the mailing list instead where things are likely to be more of a discussion.
To be respectful of reviewers time and allow us to help everyone efficiently, please
provide minimal well-reduced and well-commented examples versus sharing your entire production
playbook. Include playbook snippets and output where possible.
Content in the GitHub bug tracker can be indented four spaces to preserve formatting.
For multiple-file content, we encourage use of gist.github.com. Online pastebin content can expire.
If you are not sure if something is a bug yet, you are welcome to ask about something on
the mailing list or IRC first. As we are a very high volume project, if you determine that
you do have a bug, please be sure to open the issue yourself to ensure we have a record of
it. Don’t rely on someone else in the community to file the bug report for you.
Online Resources
================
Documentation
-------------
The main ansible documentation can be found at [docs.ansible.com](http://docs.ansible.com).
As mentioned above this is an open source project, so we accept contributions to the documentation.
You can also find some best practices examples that we recommend reading at
[ansible-examples](http://github.com/ansible/ansible-examples).
Mailing lists
-------------
Ansible has several mailing lists. Your first post to the mailing list will be
moderated (to reduce spam), so please allow a day or less for your first post.
[ansible-announce](https://groups.google.com/forum/#!forum/ansible-announce) is for release
announcements and major news. It is a low traffic read-only list and you should only get a few
emails a month.
[ansible-project](https://groups.google.com/forum/#!forum/ansible-project) is the main list, and is
used for sharing cool projects you may have built, talking about Ansible ideas, and for users to ask
questions or to help other users.
[ansible-devel](https://groups.google.com/forum/#!forum/ansible-devel) is a technical list for
developers working on Ansible and Ansible modules. Join here to discuss how to build modules,
prospective feature implementations, or technical challenges.
To subscribe to a group from a non-google account, you can email the subscription address, for
example ansible-devel+subscribe@googlegroups.com.
IRC
---
Ansible has a general purpose IRC channel available at #ansible on irc.freenode.net.
Use this channel for all types of conversations, including sharing tips, coordinating
development work, or getting help from other users.
Miscellaneous Information
=========================
Staff
-----
Ansible, Inc is a company supporting Ansible and building additional solutions based on
Ansible. We also do services and support for those that are interested. Our most
important task however is enabling all the great things that happen in the Ansible
community, including organizing software releases of Ansible. For more information about
any of these things, contact info@ansible.com
On IRC, you can find us as mdehaan, jimi_c, Tybstar, and others. On the mailing list,
we post with an @ansible.com address.
Community Code of Conduct
-------------------------
Ansible’s community welcomes users of all types, backgrounds, and skill levels. Please
treat others as you expect to be treated, keep discussions positive, and avoid discrimination
or engaging in controversial debates (except vi vs emacs is cool). Posts to mailing lists
should remain focused around Ansible and IT automation. Abuse of these community guidelines
will not be tolerated and may result in banning from community resources.
Contributors License Agreement
------------------------------
By contributing you agree that these contributions are your own (or approved by your employer)
and you grant a full, complete, irrevocable
copyright license to all users and developers of the project, present and future, pursuant
to the license of the project.

View File

@ -1,7 +1,7 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found.
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
@ -664,11 +664,12 @@ might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

View File

@ -1,11 +1,8 @@
include COPYING
include bin/*
include changelogs/CHANGELOG*.rst
include changelogs/changelog.yaml
include licenses/*.txt
include requirements.txt
recursive-include packaging *.py *.j2
recursive-include test/integration *
recursive-include test/sanity *.in *.json *.py *.txt
recursive-include test/support *.py *.ps1 *.psm1 *.cs *.md
recursive-include test/units *
include README.md packaging/rpm/ansible.spec COPYING
include examples/hosts
include examples/ansible.cfg
graft examples/playbooks
include packaging/distutils/setup.py
recursive-include docs *
recursive-include library *
include Makefile

174
Makefile Normal file
View File

@ -0,0 +1,174 @@
#!/usr/bin/make
# WARN: gmake syntax
########################################################
# Makefile for Ansible
#
# useful targets:
# make sdist ---------------- produce a tarball
# make rpm ----------------- produce RPMs
# make deb ------------------ produce a DEB
# make docs ----------------- rebuild the manpages (results are checked in)
# make tests ---------------- run the tests
# make pyflakes, make pep8 -- source code checks
########################################################
# variable section
NAME = "ansible"
OS = $(shell uname -s)
# Manpages are currently built with asciidoc -- would like to move to markdown
# This doesn't evaluate until it's called. The -D argument is the
# directory of the target file ($@), kinda like `dirname`.
MANPAGES := docs/man/man1/ansible.1 docs/man/man1/ansible-playbook.1 docs/man/man1/ansible-pull.1 docs/man/man1/ansible-doc.1
ifneq ($(shell which a2x 2>/dev/null),)
ASCII2MAN = a2x -D $(dir $@) -d manpage -f manpage $<
ASCII2HTMLMAN = a2x -D docs/html/man/ -d manpage -f xhtml
else
ASCII2MAN = @echo "ERROR: AsciiDoc 'a2x' command is not installed but is required to build $(MANPAGES)" && exit 1
endif
PYTHON=python
SITELIB = $(shell $(PYTHON) -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")
# VERSION file provides one place to update the software version
VERSION := $(shell cat VERSION)
# Get the branch information from git
ifneq ($(shell which git),)
GIT_DATE := $(shell git log -n 1 --format="%ai")
endif
ifeq ($(shell echo $(OS) | egrep -c 'Darwin|FreeBSD|OpenBSD'),1)
DATE := $(shell date -j -r $(shell git log -n 1 --format="%at") +%Y%m%d%H%M)
else
DATE := $(shell date --utc --date="$(GIT_DATE)" +%Y%m%d%H%M)
endif
# RPM build parameters
RPMSPECDIR= packaging/rpm
RPMSPEC = $(RPMSPECDIR)/ansible.spec
RPMDIST = $(shell rpm --eval '%{?dist}')
RPMRELEASE = 1
ifeq ($(OFFICIAL),)
RPMRELEASE = 0.git$(DATE)
endif
RPMNVR = "$(NAME)-$(VERSION)-$(RPMRELEASE)$(RPMDIST)"
NOSETESTS ?= nosetests
########################################################
all: clean python
tests:
PYTHONPATH=./lib ANSIBLE_LIBRARY=./library $(NOSETESTS) -d -w test/units -v
authors:
sh hacking/authors.sh
# Regenerate %.1.asciidoc if %.1.asciidoc.in has been modified more
# recently than %.1.asciidoc.
%.1.asciidoc: %.1.asciidoc.in
sed "s/%VERSION%/$(VERSION)/" $< > $@
# Regenerate %.1 if %.1.asciidoc or VERSION has been modified more
# recently than %.1. (Implicitly runs the %.1.asciidoc recipe)
%.1: %.1.asciidoc VERSION
$(ASCII2MAN)
loc:
sloccount lib library bin
pep8:
@echo "#############################################"
@echo "# Running PEP8 Compliance Tests"
@echo "#############################################"
-pep8 -r --ignore=E501,E221,W291,W391,E302,E251,E203,W293,E231,E303,E201,E225,E261,E241 lib/ bin/
-pep8 -r --ignore=E501,E221,W291,W391,E302,E251,E203,W293,E231,E303,E201,E225,E261,E241 --filename "*" library/
pyflakes:
pyflakes lib/ansible/*.py lib/ansible/*/*.py bin/*
clean:
@echo "Cleaning up distutils stuff"
rm -rf build
rm -rf dist
@echo "Cleaning up byte compiled python stuff"
find . -type f -regex ".*\.py[co]$$" -delete
@echo "Cleaning up editor backup files"
find . -type f \( -name "*~" -or -name "#*" \) -delete
find . -type f \( -name "*.swp" \) -delete
@echo "Cleaning up manpage stuff"
find ./docs/man -type f -name "*.xml" -delete
find ./docs/man -type f -name "*.asciidoc" -delete
find ./docs/man/man3 -type f -name "*.3" -delete
@echo "Cleaning up output from test runs"
rm -rf test/test_data
@echo "Cleaning up RPM building stuff"
rm -rf MANIFEST rpm-build
@echo "Cleaning up Debian building stuff"
rm -rf debian
rm -rf deb-build
rm -rf docs/json
rm -rf docs/js
@echo "Cleaning up authors file"
rm -f AUTHORS.TXT
python:
$(PYTHON) setup.py build
install:
$(PYTHON) setup.py install
sdist: clean docs
$(PYTHON) setup.py sdist -t MANIFEST.in
rpmcommon: $(MANPAGES) sdist
@mkdir -p rpm-build
@cp dist/*.gz rpm-build/
@sed -e 's#^Version:.*#Version: $(VERSION)#' -e 's#^Release:.*#Release: $(RPMRELEASE)%{?dist}#' $(RPMSPEC) >rpm-build/$(NAME).spec
srpm: rpmcommon
@rpmbuild --define "_topdir %(pwd)/rpm-build" \
--define "_builddir %{_topdir}" \
--define "_rpmdir %{_topdir}" \
--define "_srcrpmdir %{_topdir}" \
--define "_specdir $(RPMSPECDIR)" \
--define "_sourcedir %{_topdir}" \
-bs rpm-build/$(NAME).spec
@rm -f rpm-build/$(NAME).spec
@echo "#############################################"
@echo "Ansible SRPM is built:"
@echo " rpm-build/$(RPMNVR).src.rpm"
@echo "#############################################"
rpm: rpmcommon
@rpmbuild --define "_topdir %(pwd)/rpm-build" \
--define "_builddir %{_topdir}" \
--define "_rpmdir %{_topdir}" \
--define "_srcrpmdir %{_topdir}" \
--define "_specdir $(RPMSPECDIR)" \
--define "_sourcedir %{_topdir}" \
--define "_rpmfilename %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm" \
--define "__python `which $(PYTHON)`" \
-ba rpm-build/$(NAME).spec
@rm -f rpm-build/$(NAME).spec
@echo "#############################################"
@echo "Ansible RPM is built:"
@echo " rpm-build/$(RPMNVR).noarch.rpm"
@echo "#############################################"
debian: sdist
deb: debian
cp -r packaging/debian ./
chmod 755 debian/rules
fakeroot debian/rules clean
fakeroot dh_install
fakeroot debian/rules binary
# for arch or gentoo, read instructions in the appropriate 'packaging' subdirectory directory
webdocs: $(MANPAGES)
(cd docsite/; make docs)

110
README.md
View File

@ -1,89 +1,47 @@
[![PyPI version](https://img.shields.io/pypi/v/ansible-core.svg)](https://pypi.org/project/ansible-core)
[![Docs badge](https://img.shields.io/badge/docs-latest-brightgreen.svg)](https://docs.ansible.com/ansible/latest/)
[![Chat badge](https://img.shields.io/badge/chat-IRC-brightgreen.svg)](https://docs.ansible.com/ansible/latest/community/communication.html)
[![Build Status](https://dev.azure.com/ansible/ansible/_apis/build/status/CI?branchName=devel)](https://dev.azure.com/ansible/ansible/_build/latest?definitionId=20&branchName=devel)
[![Ansible Code of Conduct](https://img.shields.io/badge/code%20of%20conduct-Ansible-silver.svg)](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html)
[![Ansible mailing lists](https://img.shields.io/badge/mailing%20lists-Ansible-orange.svg)](https://docs.ansible.com/ansible/latest/community/communication.html#mailing-list-information)
[![Repository License](https://img.shields.io/badge/license-GPL%20v3.0-brightgreen.svg)](COPYING)
[![Ansible CII Best Practices certification](https://bestpractices.coreinfrastructure.org/projects/2372/badge)](https://bestpractices.coreinfrastructure.org/projects/2372)
[![PyPI version](https://badge.fury.io/py/ansible.png)](http://badge.fury.io/py/ansible)
# Ansible
Ansible
=======
Ansible is a radically simple IT automation system. It handles
configuration management, application deployment, cloud provisioning,
ad-hoc task execution, network automation, and multi-node orchestration. Ansible makes complex
changes like zero-downtime rolling updates with load balancers easy. More information on the Ansible [website](https://ansible.com/).
Ansible is a radically simple configuration-management, application deployment, task-execution, and multinode orchestration engine.
## Design Principles
Read the documentation and more at http://ansible.com/
* Have an extremely simple setup process with a minimal learning curve.
* Manage machines quickly and in parallel.
* Avoid custom-agents and additional open ports, be agentless by
leveraging the existing SSH daemon.
* Describe infrastructure in a language that is both machine and human
friendly.
* Focus on security and easy auditability/review/rewriting of content.
* Manage new remote machines instantly, without bootstrapping any
software.
* Allow module development in any dynamic language, not just Python.
* Be usable as non-root.
* Be the easiest IT automation system to use, ever.
Many users run straight from the development branch (it's generally fine to do so), but you might also wish to consume a release. You can find
instructions [here](http://docs.ansible.com/intro_getting_started.html) for a variety of platforms. If you want a tarball of the last release, go to [releases.ansible.com](http://releases.ansible.com/ansible) and you can also install with pip.
## Use Ansible
Design Principles
=================
You can install a released version of Ansible with `pip` or a package manager. See our
[installation guide](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) for details on installing Ansible
on a variety of platforms.
* Have a dead simple setup process and a minimal learning curve
* Be super fast & parallel by default
* Require no server or client daemons; use existing SSHd
* Use a language that is both machine and human friendly
* Focus on security and easy auditability/review/rewriting of content
* Manage remote machines instantly, without bootstrapping
* Allow module development in any dynamic language, not just Python
* Be usable as non-root
* Be the easiest IT automation system to use, ever.
Get Involved
============
Power users and developers can run the `devel` branch, which has the latest
features and fixes, directly. Although it is reasonably stable, you are more likely to encounter
breaking changes when running the `devel` branch. We recommend getting involved
in the Ansible community if you want to run the `devel` branch.
* Read [Contributing.md](https://github.com/ansible/ansible/blob/devel/CONTRIBUTING.md) for all kinds of ways to contribute to and interact with the project, including mailing list information and how to submit bug reports and code to Ansible.
* All code submissions are done through pull requests. Take care to make sure no merge commits are in the submission, and use "git rebase" vs "git merge" for this reason. If submitting a large code change (other than modules), it's probably a good idea to join ansible-devel and talk about what you would like to do or add first and to avoid duplicate efforts. This not only helps everyone know what's going on, it also helps save time and effort if we decide some changes are needed.
* irc.freenode.net: #ansible
## Get Involved
Branch Info
===========
* Read [Community Information](https://docs.ansible.com/ansible/latest/community) for all
kinds of ways to contribute to and interact with the project,
including mailing list information and how to submit bug reports and
code to Ansible.
* Join a [Working Group](https://docs.ansible.com/ansible/devel/community/communication.html#working-groups),
an organized community devoted to a specific technology domain or platform.
* Submit a proposed code update through a pull request to the `devel` branch.
* Talk to us before making larger changes
to avoid duplicate efforts. This not only helps everyone
know what is going on, but it also helps save time and effort if we decide
some changes are needed.
* For a list of email lists, IRC channels and Working Groups, see the
[Communication page](https://docs.ansible.com/ansible/devel/community/communication.html)
* Releases are named after Van Halen songs.
* The devel branch corresponds to the release actively under development.
* Various release-X.Y branches exist for previous releases
* We'd love to have your contributions, read "CONTRIBUTING.md" for process notes.
## Coding Guidelines
Author
======
We document our Coding Guidelines in the [Developer Guide](https://docs.ansible.com/ansible/devel/dev_guide/). We particularly suggest you review:
Michael DeHaan -- michael@ansible.com
* [Contributing your module to Ansible](https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_checklist.html)
* [Conventions, tips, and pitfalls](https://docs.ansible.com/ansible/devel/dev_guide/developing_modules_best_practices.html)
[Ansible, Inc](http://ansible.com)
## Branch Info
* The `devel` branch corresponds to the release actively under development.
* The `stable-2.X` branches correspond to stable releases.
* Create a branch based on `devel` and set up a [dev environment](https://docs.ansible.com/ansible/latest/dev_guide/developing_modules_general.html#common-environment-setup) if you want to open a PR.
* See the [Ansible release and maintenance](https://docs.ansible.com/ansible/devel/reference_appendices/release_and_maintenance.html) page for information about active branches.
## Roadmap
Based on team and community feedback, an initial roadmap will be published for a major or minor version (ex: 2.7, 2.8).
The [Ansible Roadmap page](https://docs.ansible.com/ansible/devel/roadmap/) details what is planned and how to influence the roadmap.
## Authors
Ansible was created by [Michael DeHaan](https://github.com/mpdehaan)
and has contributions from over 5000 users (and growing). Thanks everyone!
[Ansible](https://www.ansible.com) is sponsored by [Red Hat, Inc.](https://www.redhat.com)
## License
GNU General Public License v3.0 or later
See [COPYING](COPYING) to see the full text.

36
RELEASES.txt Normal file
View File

@ -0,0 +1,36 @@
Ansible Releases at a Glance
============================
1.6 "The Cradle Will Rock" - NEXT
1.5.3 "Love Walks In" -------- 03-13-2014
1.5.2 "Love Walks In" -------- 03-11-2014
1.5.1 "Love Walks In" -------- 03-10-2014
1.5 "Love Walks In" -------- 02-28-2014
1.4.5 "Could This Be Magic?" - 02-12-2014
1.4.4 "Could This Be Magic?" - 01-06-2014
1.4.3 "Could This Be Magic?" - 12-20-2013
1.4.2 "Could This Be Magic?" - 12-18-2013
1.4.1 "Could This Be Magic?" - 11-27-2013
1.4 "Could This Be Magic?" - 11-21-2013
1.3.4 "Top of the World" ----- 10-29-2013
1.3.3 "Top of the World" ----- 10-09-2013
1.3.2 "Top of the World" ----- 09-19-2013
1.3.1 "Top of the World" ----- 09-16-2013
1.3 "Top of the World" ----- 09-13-2013
1.2.3 "Hear About It Later" -- 08-21-2013
1.2.2 "Hear About It Later" -- 07-05-2013
1.2.1 "Hear About It Later" -- 07-04-2013
1.2 "Right Now" ------------ 06-10-2013
1.1 "Mean Street" ---------- 04-02-2013
1.0 "Eruption" ------------- 02-01-2013
0.9 "Dreams" --------------- 11-30-2012
0.8 "Cathedral" ------------ 10-19-2012
0.7 "Panama" --------------- 09-06-2012
0.6 "Cabo" ----------------- 08-06-2012
0.5 "Amsterdam" ------------ 07-04-2012
0.4 "Unchained" ------------ 05-23-2012
0.3 "Baluchitherium" ------- 04-23-2012
0.0.2 Untitled
0.0.1 Untitled

1
VERSION Normal file
View File

@ -0,0 +1 @@
1.5.3

View File

@ -1 +0,0 @@
../lib/ansible/cli/adhoc.py

236
bin/ansible Executable file
View File

@ -0,0 +1,236 @@
#!/usr/bin/env python
# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
########################################################
import os
import sys
from ansible.runner import Runner
import ansible.constants as C
from ansible import utils
from ansible import errors
from ansible import callbacks
from ansible import inventory
########################################################
class Cli(object):
''' code behind bin/ansible '''
# ----------------------------------------------
def __init__(self):
self.stats = callbacks.AggregateStats()
self.callbacks = callbacks.CliRunnerCallbacks()
# ----------------------------------------------
def parse(self):
''' create an options parser for bin/ansible '''
parser = utils.base_parser(
constants=C,
runas_opts=True,
subset_opts=True,
async_opts=True,
output_opts=True,
connect_opts=True,
check_opts=True,
diff_opts=False,
usage='%prog <host-pattern> [options]'
)
parser.add_option('-a', '--args', dest='module_args',
help="module arguments", default=C.DEFAULT_MODULE_ARGS)
parser.add_option('-m', '--module-name', dest='module_name',
help="module name to execute (default=%s)" % C.DEFAULT_MODULE_NAME,
default=C.DEFAULT_MODULE_NAME)
options, args = parser.parse_args()
self.callbacks.options = options
if len(args) == 0 or len(args) > 1:
parser.print_help()
sys.exit(1)
# su and sudo command line arguments need to be mutually exclusive
if (options.su or options.su_user or options.ask_su_pass) and \
(options.sudo or options.sudo_user or options.ask_sudo_pass):
parser.error("Sudo arguments ('--sudo', '--sudo-user', and '--ask-sudo-pass') "
"and su arguments ('-su', '--su-user', and '--ask-su-pass') are "
"mutually exclusive")
if (options.ask_vault_pass and options.vault_password_file):
parser.error("--ask-vault-pass and --vault-password-file are mutually exclusive")
return (options, args)
# ----------------------------------------------
def run(self, options, args):
''' use Runner lib to do SSH things '''
pattern = args[0]
"""
inventory_manager = inventory.Inventory(options.inventory)
if options.subset:
inventory_manager.subset(options.subset)
hosts = inventory_manager.list_hosts(pattern)
if len(hosts) == 0:
callbacks.display("No hosts matched")
sys.exit(0)
if options.listhosts:
for host in hosts:
callbacks.display(' %s' % host)
sys.exit(0)
if ((options.module_name == 'command' or options.module_name == 'shell')
and not options.module_args):
callbacks.display("No argument passed to %s module" % options.module_name, color='red', stderr=True)
sys.exit(1)
"""
sshpass = None
sudopass = None
su_pass = None
vault_pass = None
options.ask_pass = options.ask_pass or C.DEFAULT_ASK_PASS
# Never ask for an SSH password when we run with local connection
if options.connection == "local":
options.ask_pass = False
options.ask_sudo_pass = options.ask_sudo_pass or C.DEFAULT_ASK_SUDO_PASS
options.ask_su_pass = options.ask_su_pass or C.DEFAULT_ASK_SU_PASS
options.ask_vault_pass = options.ask_vault_pass or C.DEFAULT_ASK_VAULT_PASS
(sshpass, sudopass, su_pass, vault_pass) = utils.ask_passwords(ask_pass=options.ask_pass, ask_sudo_pass=options.ask_sudo_pass, ask_su_pass=options.ask_su_pass, ask_vault_pass=options.ask_vault_pass)
# read vault_pass from a file
if options.vault_password_file:
this_path = os.path.expanduser(options.vault_password_file)
try:
f = open(this_path, "rb")
tmp_vault_pass=f.read()
f.close()
except (OSError, IOError), e:
raise errors.AnsibleError("Could not read %s: %s" % (this_path, e))
# get rid of newline chars
tmp_vault_pass = tmp_vault_pass.strip()
if not options.ask_vault_pass:
vault_pass = tmp_vault_pass
inventory_manager = inventory.Inventory(options.inventory)
if options.subset:
inventory_manager.subset(options.subset)
hosts = inventory_manager.list_hosts(pattern)
if len(hosts) == 0:
callbacks.display("No hosts matched")
sys.exit(0)
if options.listhosts:
for host in hosts:
callbacks.display(' %s' % host)
sys.exit(0)
if ((options.module_name == 'command' or options.module_name == 'shell')
and not options.module_args):
callbacks.display("No argument passed to %s module" % options.module_name, color='red', stderr=True)
sys.exit(1)
if options.su_user or options.ask_su_pass:
options.su = True
elif options.sudo_user or options.ask_sudo_pass:
options.sudo = True
options.sudo_user = options.sudo_user or C.DEFAULT_SUDO_USER
options.su_user = options.su_user or C.DEFAULT_SU_USER
if options.tree:
utils.prepare_writeable_dir(options.tree)
runner = Runner(
module_name=options.module_name,
module_path=options.module_path,
module_args=options.module_args,
remote_user=options.remote_user,
remote_pass=sshpass,
inventory=inventory_manager,
timeout=options.timeout,
private_key_file=options.private_key_file,
forks=options.forks,
pattern=pattern,
callbacks=self.callbacks,
sudo=options.sudo,
sudo_pass=sudopass,
sudo_user=options.sudo_user,
transport=options.connection,
subset=options.subset,
check=options.check,
diff=options.check,
su=options.su,
su_pass=su_pass,
su_user=options.su_user,
vault_pass=vault_pass
)
if options.seconds:
callbacks.display("background launch...\n\n", color='cyan')
results, poller = runner.run_async(options.seconds)
results = self.poll_while_needed(poller, options)
else:
results = runner.run()
return (runner, results)
# ----------------------------------------------
def poll_while_needed(self, poller, options):
''' summarize results from Runner '''
# BACKGROUND POLL LOGIC when -B and -P are specified
if options.seconds and options.poll_interval > 0:
poller.wait(options.seconds, options.poll_interval)
return poller.results
########################################################
if __name__ == '__main__':
callbacks.display("", log_only=True)
callbacks.display(" ".join(sys.argv), log_only=True)
callbacks.display("", log_only=True)
cli = Cli()
(options, args) = cli.parse()
try:
(runner, results) = cli.run(options, args)
for result in results['contacted'].values():
if 'failed' in result or result.get('rc', 0) != 0:
sys.exit(2)
if results['dark']:
sys.exit(3)
except errors.AnsibleError, e:
# Generic handler for ansible specific errors
callbacks.display("ERROR: %s" % str(e), stderr=True, color='red')
sys.exit(1)

View File

@ -1 +0,0 @@
../lib/ansible/cli/config.py

View File

@ -1 +0,0 @@
../lib/ansible/cli/scripts/ansible_connection_cli_stub.py

View File

@ -1 +0,0 @@
../lib/ansible/cli/console.py

View File

@ -1 +0,0 @@
../lib/ansible/cli/doc.py

286
bin/ansible-doc Executable file
View File

@ -0,0 +1,286 @@
#!/usr/bin/env python
# (c) 2012, Jan-Piet Mens <jpmens () gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
import os
import sys
import textwrap
import re
import optparse
import datetime
import subprocess
from ansible import utils
from ansible.utils import module_docs
import ansible.constants as C
from ansible.utils import version
import traceback
MODULEDIR = C.DEFAULT_MODULE_PATH
BLACKLIST_EXTS = ('.swp', '.bak', '~', '.rpm')
_ITALIC = re.compile(r"I\(([^)]+)\)")
_BOLD = re.compile(r"B\(([^)]+)\)")
_MODULE = re.compile(r"M\(([^)]+)\)")
_URL = re.compile(r"U\(([^)]+)\)")
_CONST = re.compile(r"C\(([^)]+)\)")
PAGER = 'less'
LESS_OPTS = 'FRSX' # -F (quit-if-one-screen) -R (allow raw ansi control chars)
# -S (chop long lines) -X (disable termcap init and de-init)
def pager_print(text):
''' just print text '''
print text
def pager_pipe(text, cmd):
''' pipe text through a pager '''
if 'LESS' not in os.environ:
os.environ['LESS'] = LESS_OPTS
try:
cmd = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=sys.stdout)
cmd.communicate(input=text)
except IOError:
pass
except KeyboardInterrupt:
pass
def pager(text):
''' find reasonable way to display text '''
# this is a much simpler form of what is in pydoc.py
if not sys.stdout.isatty():
pager_print(text)
elif 'PAGER' in os.environ:
if sys.platform == 'win32':
pager_print(text)
else:
pager_pipe(text, os.environ['PAGER'])
elif hasattr(os, 'system') and os.system('(less) 2> /dev/null') == 0:
pager_pipe(text, 'less')
else:
pager_print(text)
def tty_ify(text):
t = _ITALIC.sub("`" + r"\1" + "'", text) # I(word) => `word'
t = _BOLD.sub("*" + r"\1" + "*", t) # B(word) => *word*
t = _MODULE.sub("[" + r"\1" + "]", t) # M(word) => [word]
t = _URL.sub(r"\1", t) # U(word) => word
t = _CONST.sub("`" + r"\1" + "'", t) # C(word) => `word'
return t
def get_man_text(doc):
opt_indent=" "
text = []
text.append("> %s\n" % doc['module'].upper())
desc = "".join(doc['description'])
text.append("%s\n" % textwrap.fill(tty_ify(desc), initial_indent=" ", subsequent_indent=" "))
if 'option_keys' in doc and len(doc['option_keys']) > 0:
text.append("Options (= is mandatory):\n")
for o in doc['option_keys']:
opt = doc['options'][o]
if opt.get('required', False):
opt_leadin = "="
else:
opt_leadin = "-"
text.append("%s %s" % (opt_leadin, o))
desc = "".join(opt['description'])
if 'choices' in opt:
choices = ", ".join(str(i) for i in opt['choices'])
desc = desc + " (Choices: " + choices + ")"
text.append("%s\n" % textwrap.fill(tty_ify(desc), initial_indent=opt_indent,
subsequent_indent=opt_indent))
if 'notes' in doc and len(doc['notes']) > 0:
notes = "".join(doc['notes'])
text.append("Notes:%s\n" % textwrap.fill(tty_ify(notes), initial_indent=" ",
subsequent_indent=opt_indent))
if 'requirements' in doc and doc['requirements'] is not None and len(doc['requirements']) > 0:
req = ", ".join(doc['requirements'])
text.append("Requirements:%s\n" % textwrap.fill(tty_ify(req), initial_indent=" ",
subsequent_indent=opt_indent))
if 'examples' in doc and len(doc['examples']) > 0:
text.append("Example%s:\n" % ('' if len(doc['examples']) < 2 else 's'))
for ex in doc['examples']:
text.append("%s\n" % (ex['code']))
if 'plainexamples' in doc and doc['plainexamples'] is not None:
text.append(doc['plainexamples'])
text.append('')
return "\n".join(text)
def get_snippet_text(doc):
text = []
desc = tty_ify("".join(doc['short_description']))
text.append("- name: %s" % (desc))
text.append(" action: %s" % (doc['module']))
for o in doc['options']:
opt = doc['options'][o]
desc = tty_ify("".join(opt['description']))
s = o + "="
text.append(" %-20s # %s" % (s, desc))
text.append('')
return "\n".join(text)
def get_module_list_text(module_list):
text = []
for module in sorted(set(module_list)):
if module in module_docs.BLACKLIST_MODULES:
continue
filename = utils.plugins.module_finder.find_plugin(module)
if filename is None:
continue
if os.path.isdir(filename):
continue
try:
doc, plainexamples = module_docs.get_docstring(filename)
desc = tty_ify(doc.get('short_description', '?'))
if len(desc) > 55:
desc = desc + '...'
text.append("%-20s %-60.60s" % (module, desc))
except:
traceback.print_exc()
sys.stderr.write("ERROR: module %s has a documentation error formatting or is missing documentation\n" % module)
pass
return "\n".join(text)
def main():
p = optparse.OptionParser(
version=version("%prog"),
usage='usage: %prog [options] [module...]',
description='Show Ansible module documentation',
)
p.add_option("-M", "--module-path",
action="store",
dest="module_path",
default=MODULEDIR,
help="Ansible modules/ directory")
p.add_option("-l", "--list",
action="store_true",
default=False,
dest='list_dir',
help='List available modules')
p.add_option("-s", "--snippet",
action="store_true",
default=False,
dest='show_snippet',
help='Show playbook snippet for specified module(s)')
p.add_option('-v', action='version', help='Show version number and exit')
(options, args) = p.parse_args()
if options.module_path is not None:
for i in options.module_path.split(os.pathsep):
utils.plugins.module_finder.add_directory(i)
if options.list_dir:
# list all modules
paths = utils.plugins.module_finder._get_paths()
module_list = []
for path in paths:
# os.system("ls -C %s" % (path))
if os.path.isdir(path):
for module in os.listdir(path):
if any(module.endswith(x) for x in BLACKLIST_EXTS):
continue
module_list.append(module)
pager(get_module_list_text(module_list))
sys.exit()
if len(args) == 0:
p.print_help()
def print_paths(finder):
''' Returns a string suitable for printing of the search path '''
# Uses a list to get the order right
ret = []
for i in finder._get_paths():
if i not in ret:
ret.append(i)
return os.pathsep.join(ret)
text = ''
for module in args:
filename = utils.plugins.module_finder.find_plugin(module)
if filename is None:
sys.stderr.write("module %s not found in %s\n" % (module,
print_paths(utils.plugins.module_finder)))
continue
if any(filename.endswith(x) for x in BLACKLIST_EXTS):
continue
try:
doc, plainexamples = module_docs.get_docstring(filename)
except:
traceback.print_exc()
sys.stderr.write("ERROR: module %s has a documentation error formatting or is missing documentation\n" % module)
continue
if doc is not None:
all_keys = []
for (k,v) in doc['options'].iteritems():
all_keys.append(k)
all_keys = sorted(all_keys)
doc['option_keys'] = all_keys
doc['filename'] = filename
doc['docuri'] = doc['module'].replace('_', '-')
doc['now_date'] = datetime.date.today().strftime('%Y-%m-%d')
doc['plainexamples'] = plainexamples
if options.show_snippet:
text += get_snippet_text(doc)
else:
text += get_man_text(doc)
else:
# this typically means we couldn't even parse the docstring, not just that the YAML is busted,
# probably a quoting issue.
sys.stderr.write("ERROR: module %s missing documentation (or could not parse documentation)\n" % module)
pager(text)
if __name__ == '__main__':
main()

View File

@ -1 +0,0 @@
../lib/ansible/cli/galaxy.py

814
bin/ansible-galaxy Executable file
View File

@ -0,0 +1,814 @@
#!/usr/bin/env python
########################################################################
#
# (C) 2013, James Cammarata <jcammarata@ansible.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
########################################################################
import datetime
import json
import os
import os.path
import shutil
import sys
import tarfile
import tempfile
import urllib
import urllib2
import yaml
from collections import defaultdict
from distutils.version import LooseVersion
from jinja2 import Environment
from optparse import OptionParser
import ansible.constants as C
default_meta_template = """---
galaxy_info:
author: {{ author }}
description: {{description}}
company: {{ company }}
# Some suggested licenses:
# - BSD (default)
# - MIT
# - GPLv2
# - GPLv3
# - Apache
# - CC-BY
license: {{ license }}
min_ansible_version: {{ min_ansible_version }}
#
# Below are all platforms currently available. Just uncomment
# the ones that apply to your role. If you don't see your
# platform on this list, let us know and we'll get it added!
#
#platforms:
{%- for platform,versions in platforms.iteritems() %}
#- name: {{ platform }}
# versions:
# - all
{%- for version in versions %}
# - {{ version }}
{%- endfor %}
{%- endfor %}
#
# Below are all categories currently available. Just as with
# the platforms above, uncomment those that apply to your role.
#
#categories:
{%- for category in categories %}
#- {{ category.name }}
{%- endfor %}
dependencies: []
# List your role dependencies here, one per line. Only
# dependencies available via galaxy should be listed here.
# Be sure to remove the '[]' above if you add dependencies
# to this list.
{% for dependency in dependencies %}
#- {{ dependency }}
{% endfor %}
"""
default_readme_template = """Role Name
========
A brief description of the role goes here.
Requirements
------------
Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
Role Variables
--------------
A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well.
Dependencies
------------
A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles.
Example Playbook
-------------------------
Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too:
- hosts: servers
roles:
- { role: username.rolename, x: 42 }
License
-------
BSD
Author Information
------------------
An optional section for the role authors to include contact information, or a website (HTML is not allowed).
"""
#-------------------------------------------------------------------------------------
# Utility functions for parsing actions/options
#-------------------------------------------------------------------------------------
VALID_ACTIONS = ("init", "info", "install", "list", "remove")
def get_action(args):
"""
Get the action the user wants to execute from the
sys argv list.
"""
for i in range(0,len(args)):
arg = args[i]
if arg in VALID_ACTIONS:
del args[i]
return arg
return None
def build_option_parser(action):
"""
Builds an option parser object based on the action
the user wants to execute.
"""
usage = "usage: %%prog [%s] [--help] [options] ..." % "|".join(VALID_ACTIONS)
epilog = "\nSee '%s <command> --help' for more information on a specific command.\n\n" % os.path.basename(sys.argv[0])
OptionParser.format_epilog = lambda self, formatter: self.epilog
parser = OptionParser(usage=usage, epilog=epilog)
if not action:
parser.print_help()
sys.exit()
# options for all actions
# - none yet
# options specific to actions
if action == "info":
parser.set_usage("usage: %prog info [options] role_name[,version]")
elif action == "init":
parser.set_usage("usage: %prog init [options] role_name")
parser.add_option(
'-p', '--init-path', dest='init_path', default="./",
help='The path in which the skeleton role will be created.'
'The default is the current working directory.')
elif action == "install":
parser.set_usage("usage: %prog install [options] [-r FILE | role_name(s)[,version] | tar_file(s)]")
parser.add_option(
'-i', '--ignore-errors', dest='ignore_errors', action='store_true', default=False,
help='Ignore errors and continue with the next specified role.')
parser.add_option(
'-n', '--no-deps', dest='no_deps', action='store_true', default=False,
help='Don\'t download roles listed as dependencies')
parser.add_option(
'-r', '--role-file', dest='role_file',
help='A file containing a list of roles to be imported')
elif action == "remove":
parser.set_usage("usage: %prog remove role1 role2 ...")
elif action == "list":
parser.set_usage("usage: %prog list [role_name]")
# options that apply to more than one action
if action != "init":
parser.add_option(
'-p', '--roles-path', dest='roles_path', default=C.DEFAULT_ROLES_PATH,
help='The path to the directory containing your roles.'
'The default is the roles_path configured in your '
'ansible.cfg file (/etc/ansible/roles if not configured)')
if action in ("info","init","install"):
parser.add_option(
'-s', '--server', dest='api_server', default="galaxy.ansible.com",
help='The API server destination')
if action in ("init","install"):
parser.add_option(
'-f', '--force', dest='force', action='store_true', default=False,
help='Force overwriting an existing role')
# done, return the parser
return parser
def get_opt(options, k, defval=""):
"""
Returns an option from an Optparse values instance.
"""
try:
data = getattr(options, k)
except:
return defval
if k == "roles_path":
if os.pathsep in data:
data = data.split(os.pathsep)[0]
return data
def exit_without_ignore(options, rc=1):
"""
Exits with the specified return code unless the
option --ignore-errors was specified
"""
if not get_opt(options, "ignore_errors", False):
print 'You can use --ignore-errors to skip failed roles.'
sys.exit(rc)
#-------------------------------------------------------------------------------------
# Galaxy API functions
#-------------------------------------------------------------------------------------
def api_get_config(api_server):
"""
Fetches the Galaxy API current version to ensure
the API server is up and reachable.
"""
try:
url = 'https://%s/api/' % api_server
data = json.load(urllib2.urlopen(url))
if not data.get("current_version",None):
return None
else:
return data
except:
return None
def api_lookup_role_by_name(api_server, role_name):
"""
Uses the Galaxy API to do a lookup on the role owner/name.
"""
role_name = urllib.quote(role_name)
try:
parts = role_name.split(".")
user_name = ".".join(parts[0:-1])
role_name = parts[-1]
print " downloading role '%s', owned by %s" % (role_name, user_name)
except:
parser.print_help()
print "Invalid role name (%s). You must specify username.rolename" % role_name
sys.exit(1)
url = 'https://%s/api/v1/roles/?owner__username=%s&name=%s' % (api_server,user_name,role_name)
try:
data = json.load(urllib2.urlopen(url))
if len(data["results"]) == 0:
return None
else:
return data["results"][0]
except:
return None
def api_fetch_role_related(api_server, related, role_id):
"""
Uses the Galaxy API to fetch the list of related items for
the given role. The url comes from the 'related' field of
the role.
"""
try:
url = 'https://%s/api/v1/roles/%d/%s/?page_size=50' % (api_server, int(role_id), related)
data = json.load(urllib2.urlopen(url))
results = data['results']
done = (data.get('next', None) == None)
while not done:
url = 'https://%s%s' % (api_server, data['next'])
print url
data = json.load(urllib2.urlopen(url))
results += data['results']
done = (data.get('next', None) == None)
return results
except:
return None
def api_get_list(api_server, what):
"""
Uses the Galaxy API to fetch the list of items specified.
"""
try:
url = 'https://%s/api/v1/%s/?page_size' % (api_server, what)
data = json.load(urllib2.urlopen(url))
if "results" in data:
results = data['results']
else:
results = data
done = True
if "next" in data:
done = (data.get('next', None) == None)
while not done:
url = 'https://%s%s' % (api_server, data['next'])
print url
data = json.load(urllib2.urlopen(url))
results += data['results']
done = (data.get('next', None) == None)
return results
except:
print " - failed to download the %s list" % what
return None
#-------------------------------------------------------------------------------------
# Role utility functions
#-------------------------------------------------------------------------------------
def get_role_path(role_name, options):
"""
Returns the role path based on the roles_path option
and the role name.
"""
roles_path = get_opt(options,'roles_path')
roles_path = os.path.join(roles_path, role_name)
roles_path = os.path.expanduser(roles_path)
return roles_path
def get_role_metadata(role_name, options):
"""
Returns the metadata as YAML, if the file 'meta/main.yml'
exists in the specified role_path
"""
role_path = os.path.join(get_role_path(role_name, options), 'meta/main.yml')
try:
if os.path.isfile(role_path):
f = open(role_path, 'r')
meta_data = yaml.safe_load(f)
f.close()
return meta_data
else:
return None
except:
return None
def get_galaxy_install_info(role_name, options):
"""
Returns the YAML data contained in 'meta/.galaxy_install_info',
if it exists.
"""
try:
info_path = os.path.join(get_role_path(role_name, options), 'meta/.galaxy_install_info')
if os.path.isfile(info_path):
f = open(info_path, 'r')
info_data = yaml.safe_load(f)
f.close()
return info_data
else:
return None
except:
return None
def write_galaxy_install_info(role_name, role_version, options):
"""
Writes a YAML-formatted file to the role's meta/ directory
(named .galaxy_install_info) which contains some information
we can use later for commands like 'list' and 'info'.
"""
info = dict(
version = role_version,
install_date = datetime.datetime.utcnow().strftime("%c"),
)
try:
info_path = os.path.join(get_role_path(role_name, options), 'meta/.galaxy_install_info')
f = open(info_path, 'w+')
info_data = yaml.safe_dump(info, f)
f.close()
except:
return False
return True
def remove_role(role_name, options):
"""
Removes the specified role from the roles path. There is a
sanity check to make sure there's a meta/main.yml file at this
path so the user doesn't blow away random directories
"""
if get_role_metadata(role_name, options):
role_path = get_role_path(role_name, options)
shutil.rmtree(role_path)
return True
else:
return False
def fetch_role(role_name, target, role_data, options):
"""
Downloads the archived role from github to a temp location, extracts
it, and then copies the extracted role to the role library path.
"""
# first grab the file and save it to a temp location
archive_url = 'https://github.com/%s/%s/archive/%s.tar.gz' % (role_data["github_user"], role_data["github_repo"], target)
print " - downloading role from %s" % archive_url
try:
url_file = urllib2.urlopen(archive_url)
temp_file = tempfile.NamedTemporaryFile(delete=False)
data = url_file.read()
while data:
temp_file.write(data)
data = url_file.read()
temp_file.close()
return temp_file.name
except Exception, e:
# TODO: better urllib2 error handling for error
# messages that are more exact
print "Error: failed to download the file."
return False
def install_role(role_name, role_version, role_filename, options):
# the file is a tar, so open it that way and extract it
# to the specified (or default) roles directory
if not tarfile.is_tarfile(role_filename):
print "Error: the file downloaded was not a tar.gz"
return False
else:
role_tar_file = tarfile.open(role_filename, "r:gz")
# verify the role's meta file
meta_file = None
members = role_tar_file.getmembers()
for member in members:
if "/meta/main.yml" in member.name:
meta_file = member
break
if not meta_file:
print "Error: this role does not appear to have a meta/main.yml file."
return False
else:
try:
meta_file_data = yaml.safe_load(role_tar_file.extractfile(meta_file))
except:
print "Error: this role does not appear to have a valid meta/main.yml file."
return False
# we strip off the top-level directory for all of the files contained within
# the tar file here, since the default is 'github_repo-target', and change it
# to the specified role's name
role_path = os.path.join(get_opt(options, 'roles_path', '/etc/ansible/roles'), role_name)
role_path = os.path.expanduser(role_path)
print " - extracting %s to %s" % (role_name, role_path)
try:
if os.path.exists(role_path):
if not os.path.isdir(role_path):
print "Error: the specified roles path exists and is not a directory."
return False
elif not get_opt(options, "force", False):
print "Error: the specified role %s appears to already exist. Use --force to replace it." % role_name
return False
else:
# using --force, remove the old path
if not remove_role(role_name, options):
print "Error: %s doesn't appear to contain a role." % role_path
print "Please remove this directory manually if you really want to put the role here."
return False
else:
os.makedirs(role_path)
# now we do the actual extraction to the role_path
for member in members:
# we only extract files
if member.isreg():
member.name = "/".join(member.name.split("/")[1:])
role_tar_file.extract(member, role_path)
# write out the install info file for later use
write_galaxy_install_info(role_name, role_version, options)
except OSError, e:
print "Error: you do not have permission to modify files in %s" % role_path
return False
# return the parsed yaml metadata
print "%s was installed successfully" % role_name
return meta_file_data
#-------------------------------------------------------------------------------------
# Action functions
#-------------------------------------------------------------------------------------
def execute_init(args, options, parser):
"""
Executes the init action, which creates the skeleton framework
of a role that complies with the galaxy metadata format.
"""
init_path = get_opt(options, 'init_path', './')
api_server = get_opt(options, "api_server", "galaxy.ansible.com")
force = get_opt(options, 'force', False)
api_config = api_get_config(api_server)
if not api_config:
print "The API server (%s) is not responding, please try again later." % api_server
sys.exit(1)
try:
role_name = args.pop(0).strip()
if role_name == "":
raise Exception("")
role_path = os.path.join(init_path, role_name)
if os.path.exists(role_path):
if os.path.isfile(role_path):
print "The path %s already exists, but is a file - aborting" % role_path
sys.exit(1)
elif not force:
print "The directory %s already exists." % role_path
print ""
print "You can use --force to re-initialize this directory,\n" + \
"however it will reset any main.yml files that may have\n" + \
"been modified there already."
sys.exit(1)
except Exception, e:
parser.print_help()
print "No role name specified for init"
sys.exit(1)
ROLE_DIRS = ('defaults','files','handlers','meta','tasks','templates','vars')
# create the default README.md
if not os.path.exists(role_path):
os.makedirs(role_path)
readme_path = os.path.join(role_path, "README.md")
f = open(readme_path, "wb")
f.write(default_readme_template)
f.close
for dir in ROLE_DIRS:
dir_path = os.path.join(init_path, role_name, dir)
main_yml_path = os.path.join(dir_path, 'main.yml')
# create the directory if it doesn't exist already
if not os.path.exists(dir_path):
os.makedirs(dir_path)
# now create the main.yml file for that directory
if dir == "meta":
# create a skeleton meta/main.yml with a valid galaxy_info
# datastructure in place, plus with all of the available
# tags/platforms included (but commented out) and the
# dependencies section
platforms = api_get_list(api_server, "platforms")
if not platforms:
platforms = []
categories = api_get_list(api_server, "categories")
if not categories:
categories = []
# group the list of platforms from the api based
# on their names, with the release field being
# appended to a list of versions
platform_groups = defaultdict(list)
for platform in platforms:
platform_groups[platform['name']].append(platform['release'])
platform_groups[platform['name']].sort()
inject = dict(
author = 'your name',
company = 'your company (optional)',
license = 'license (GPLv2, CC-BY, etc)',
min_ansible_version = '1.2',
platforms = platform_groups,
categories = categories,
)
rendered_meta = Environment().from_string(default_meta_template).render(inject)
f = open(main_yml_path, 'w')
f.write(rendered_meta)
f.close()
pass
elif dir not in ('files','templates'):
# just write a (mostly) empty YAML file for main.yml
f = open(main_yml_path, 'w')
f.write('---\n# %s file for %s\n' % (dir,role_name))
f.close()
print "%s was created successfully" % role_name
def execute_info(args, options, parser):
"""
Executes the info action. This action prints out detailed
information about an installed role as well as info available
from the galaxy API.
"""
pass
def execute_install(args, options, parser):
"""
Executes the installation action. The args list contains the
roles to be installed, unless -f was specified. The list of roles
can be a name (which will be downloaded via the galaxy API and github),
or it can be a local .tar.gz file.
"""
role_file = get_opt(options, "role_file", None)
api_server = get_opt(options, "api_server", "galaxy.ansible.com")
no_deps = get_opt(options, "no_deps", False)
if len(args) == 0 and not role_file:
# the user needs to specify one of either --role-file
# or specify a single user/role name
parser.print_help()
print "You must specify a user/role name or a roles file"
sys.exit()
elif len(args) == 1 and role_file:
# using a role file is mutually exclusive of specifying
# the role name on the command line
parser.print_help()
print "Please specify a user/role name, or a roles file, but not both"
sys.exit(1)
api_config = api_get_config(api_server)
if not api_config:
print "The API server (%s) is not responding, please try again later." % api_server
sys.exit(1)
roles_done = []
if role_file:
# roles listed in a file, one per line
# so we'll go through and grab them all
f = open(role_file, 'r')
roles_left = f.readlines()
f.close()
else:
# roles were specified directly, so we'll just go out grab them
# (and their dependencies, unless the user doesn't want us to).
roles_left = args
while len(roles_left) > 0:
# query the galaxy API for the role data
role_name = roles_left.pop(0).strip()
role_version = None
if role_name == "" or role_name.startswith("#"):
continue
elif role_name.find(',') != -1:
role_name,role_version = role_name.split(',',1)
role_name = role_name.strip()
role_version = role_version.strip()
if os.path.isfile(role_name):
# installing a local tar.gz
tar_file = role_name
role_name = os.path.basename(role_name).replace('.tar.gz','')
if tarfile.is_tarfile(tar_file):
print " - installing %s as %s" % (tar_file, role_name)
if not install_role(role_name, role_version, tar_file, options):
exit_without_ignore(options)
else:
print "%s (%s) was NOT installed successfully." % (role_name,tar_file)
exit_without_ignore(options)
else:
# installing remotely
role_data = api_lookup_role_by_name(api_server, role_name)
if not role_data:
print "Sorry, %s was not found on %s." % (role_name, api_server)
continue
role_versions = api_fetch_role_related(api_server, 'versions', role_data['id'])
if not role_version:
# convert the version names to LooseVersion objects
# and sort them to get the latest version. If there
# are no versions in the list, we'll grab the head
# of the master branch
if len(role_versions) > 0:
loose_versions = [LooseVersion(a.get('name',None)) for a in role_versions]
loose_versions.sort()
role_version = str(loose_versions[-1])
else:
role_version = 'master'
print " no version specified, installing %s" % role_version
else:
if role_versions and role_version not in [a.get('name',None) for a in role_versions]:
print "The specified version (%s) was not found in the list of available versions." % role_version
exit_without_ignore(options)
continue
# download the role. if --no-deps was specified, we stop here,
# otherwise we recursively grab roles and all of their deps.
tmp_file = fetch_role(role_name, role_version, role_data, options)
if tmp_file and install_role(role_name, role_version, tmp_file, options):
# we're done with the temp file, clean it up
os.unlink(tmp_file)
# install dependencies, if we want them
if not no_deps:
role_dependencies = role_data['summary_fields']['dependencies'] # api_fetch_role_related(api_server, 'dependencies', role_data['id'])
for dep_name in role_dependencies:
#dep_name = "%s.%s" % (dep['owner'], dep['name'])
if not get_role_metadata(dep_name, options):
print ' adding dependency: %s' % dep_name
roles_left.append(dep_name)
else:
print ' dependency %s is already installed, skipping.' % dep_name
else:
if tmp_file:
os.unlink(tmp_file)
print "%s was NOT installed successfully." % role_name
exit_without_ignore(options)
sys.exit(0)
def execute_remove(args, options, parser):
"""
Executes the remove action. The args list contains the list
of roles to be removed. This list can contain more than one role.
"""
if len(args) == 0:
parser.print_help()
print 'You must specify at least one role to remove.'
sys.exit()
for role in args:
if get_role_metadata(role, options):
if remove_role(role, options):
print 'successfully removed %s' % role
else:
print "failed to remove role: %s" % role
else:
print '%s is not installed, skipping.' % role
sys.exit(0)
def execute_list(args, options, parser):
"""
Executes the list action. The args list can contain zero
or one role. If one is specified, only that role will be
shown, otherwise all roles in the specified directory will
be shown.
"""
if len(args) > 1:
print "Please specify only one role to list, or specify no roles to see a full list"
sys.exit(1)
if len(args) == 1:
# show only the request role, if it exists
role_name = args[0]
metadata = get_role_metadata(role_name, options)
if metadata:
install_info = get_galaxy_install_info(role_name, options)
version = None
if install_info:
version = install_info.get("version", None)
if not version:
version = "(unknown version)"
# show some more info about single roles here
print " %s, %s" % (role_name, version)
else:
print "The role %s was not found" % role_name
else:
# show all valid roles in the roles_path directory
roles_path = get_opt(options, 'roles_path')
roles_path = os.path.expanduser(roles_path)
if not os.path.exists(roles_path):
parser.print_help()
print "The path %s does not exist. Please specify a valid path with --roles-path" % roles_path
sys.exit(1)
elif not os.path.isdir(roles_path):
print "%s exists, but it is not a directory. Please specify a valid path with --roles-path" % roles_path
parser.print_help()
sys.exit(1)
path_files = os.listdir(roles_path)
for path_file in path_files:
if get_role_metadata(path_file, options):
install_info = get_galaxy_install_info(path_file, options)
version = None
if install_info:
version = install_info.get("version", None)
if not version:
version = "(unknown version)"
print " %s, %s" % (path_file, version)
sys.exit(0)
#-------------------------------------------------------------------------------------
# The main entry point
#-------------------------------------------------------------------------------------
def main():
# parse the CLI options
action = get_action(sys.argv)
parser = build_option_parser(action)
(options, args) = parser.parse_args()
# execute the desired action
if 1: #try:
fn = globals()["execute_%s" % action]
fn(args, options, parser)
#except KeyError, e:
# print "Error: %s is not a valid action. Valid actions are: %s" % (action, ", ".join(VALID_ACTIONS))
# sys.exit(1)
if __name__ == "__main__":
main()

View File

@ -1 +0,0 @@
../lib/ansible/cli/inventory.py

View File

@ -1 +0,0 @@
../lib/ansible/cli/playbook.py

314
bin/ansible-playbook Executable file
View File

@ -0,0 +1,314 @@
#!/usr/bin/env python
# (C) 2012, Michael DeHaan, <michael.dehaan@gmail.com>
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#######################################################
import sys
import os
import stat
import ansible.playbook
import ansible.constants as C
import ansible.utils.template
from ansible import errors
from ansible import callbacks
from ansible import utils
from ansible.color import ANSIBLE_COLOR, stringc
from ansible.callbacks import display
def colorize(lead, num, color):
""" Print 'lead' = 'num' in 'color' """
if num != 0 and ANSIBLE_COLOR and color is not None:
return "%s%s%-15s" % (stringc(lead, color), stringc("=", color), stringc(str(num), color))
else:
return "%s=%-4s" % (lead, str(num))
def hostcolor(host, stats, color=True):
if ANSIBLE_COLOR and color:
if stats['failures'] != 0 or stats['unreachable'] != 0:
return "%-37s" % stringc(host, 'red')
elif stats['changed'] != 0:
return "%-37s" % stringc(host, 'yellow')
else:
return "%-37s" % stringc(host, 'green')
return "%-26s" % host
def main(args):
''' run ansible-playbook operations '''
# create parser for CLI options
parser = utils.base_parser(
constants=C,
usage = "%prog playbook.yml",
connect_opts=True,
runas_opts=True,
subset_opts=True,
check_opts=True,
diff_opts=True
)
#parser.add_option('--vault-password', dest="vault_password",
# help="password for vault encrypted files")
parser.add_option('-e', '--extra-vars', dest="extra_vars", action="append",
help="set additional variables as key=value or YAML/JSON", default=[])
parser.add_option('-t', '--tags', dest='tags', default='all',
help="only run plays and tasks tagged with these values")
parser.add_option('--skip-tags', dest='skip_tags',
help="only run plays and tasks whose tags do not match these values")
parser.add_option('--syntax-check', dest='syntax', action='store_true',
help="perform a syntax check on the playbook, but do not execute it")
parser.add_option('--list-tasks', dest='listtasks', action='store_true',
help="list all tasks that would be executed")
parser.add_option('--step', dest='step', action='store_true',
help="one-step-at-a-time: confirm each task before running")
parser.add_option('--start-at-task', dest='start_at',
help="start the playbook at the task matching this name")
options, args = parser.parse_args(args)
if len(args) == 0:
parser.print_help(file=sys.stderr)
return 1
# su and sudo command line arguments need to be mutually exclusive
if (options.su or options.su_user or options.ask_su_pass) and \
(options.sudo or options.sudo_user or options.ask_sudo_pass):
parser.error("Sudo arguments ('--sudo', '--sudo-user', and '--ask-sudo-pass') "
"and su arguments ('-su', '--su-user', and '--ask-su-pass') are "
"mutually exclusive")
if (options.ask_vault_pass and options.vault_password_file):
parser.error("--ask-vault-pass and --vault-password-file are mutually exclusive")
inventory = ansible.inventory.Inventory(options.inventory)
inventory.subset(options.subset)
if len(inventory.list_hosts()) == 0:
raise errors.AnsibleError("provided hosts list is empty")
sshpass = None
sudopass = None
su_pass = None
vault_pass = None
if not options.listhosts and not options.syntax and not options.listtasks:
options.ask_pass = options.ask_pass or C.DEFAULT_ASK_PASS
options.ask_vault_pass = options.ask_vault_pass or C.DEFAULT_ASK_VAULT_PASS
# Never ask for an SSH password when we run with local connection
if options.connection == "local":
options.ask_pass = False
options.ask_sudo_pass = options.ask_sudo_pass or C.DEFAULT_ASK_SUDO_PASS
options.ask_su_pass = options.ask_su_pass or C.DEFAULT_ASK_SU_PASS
options.ask_vault_pass = options.ask_vault_pass or C.DEFAULT_ASK_VAULT_PASS
(sshpass, sudopass, su_pass, vault_pass) = utils.ask_passwords(ask_pass=options.ask_pass, ask_sudo_pass=options.ask_sudo_pass, ask_su_pass=options.ask_su_pass, ask_vault_pass=options.ask_vault_pass)
options.sudo_user = options.sudo_user or C.DEFAULT_SUDO_USER
options.su_user = options.su_user or C.DEFAULT_SU_USER
if options.vault_password_file:
this_path = os.path.expanduser(options.vault_password_file)
try:
f = open(this_path, "rb")
tmp_vault_pass=f.read()
f.close()
except (OSError, IOError), e:
raise errors.AnsibleError("Could not read %s: %s" % (this_path, e))
# get rid of newline chars
tmp_vault_pass = tmp_vault_pass.strip()
if not options.ask_vault_pass:
vault_pass = tmp_vault_pass
extra_vars = {}
for extra_vars_opt in options.extra_vars:
if extra_vars_opt.startswith("@"):
# Argument is a YAML file (JSON is a subset of YAML)
extra_vars = utils.combine_vars(extra_vars, utils.parse_yaml_from_file(extra_vars_opt[1:]))
elif extra_vars_opt and extra_vars_opt[0] in '[{':
# Arguments as YAML
extra_vars = utils.combine_vars(extra_vars, utils.parse_yaml(extra_vars_opt))
else:
# Arguments as Key-value
extra_vars = utils.combine_vars(extra_vars, utils.parse_kv(extra_vars_opt))
only_tags = options.tags.split(",")
skip_tags = options.skip_tags
if options.skip_tags is not None:
skip_tags = options.skip_tags.split(",")
for playbook in args:
if not os.path.exists(playbook):
raise errors.AnsibleError("the playbook: %s could not be found" % playbook)
if not (os.path.isfile(playbook) or stat.S_ISFIFO(os.stat(playbook).st_mode)):
raise errors.AnsibleError("the playbook: %s does not appear to be a file" % playbook)
# run all playbooks specified on the command line
for playbook in args:
# let inventory know which playbooks are using so it can know the basedirs
inventory.set_playbook_basedir(os.path.dirname(playbook))
stats = callbacks.AggregateStats()
playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY)
if options.step:
playbook_cb.step = options.step
if options.start_at:
playbook_cb.start_at = options.start_at
runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=utils.VERBOSITY)
pb = ansible.playbook.PlayBook(
playbook=playbook,
module_path=options.module_path,
inventory=inventory,
forks=options.forks,
remote_user=options.remote_user,
remote_pass=sshpass,
callbacks=playbook_cb,
runner_callbacks=runner_cb,
stats=stats,
timeout=options.timeout,
transport=options.connection,
sudo=options.sudo,
sudo_user=options.sudo_user,
sudo_pass=sudopass,
extra_vars=extra_vars,
private_key_file=options.private_key_file,
only_tags=only_tags,
skip_tags=skip_tags,
check=options.check,
diff=options.diff,
su=options.su,
su_pass=su_pass,
su_user=options.su_user,
vault_password=vault_pass
)
if options.listhosts or options.listtasks or options.syntax:
print ''
print 'playbook: %s' % playbook
print ''
playnum = 0
for (play_ds, play_basedir) in zip(pb.playbook, pb.play_basedirs):
playnum += 1
play = ansible.playbook.Play(pb, play_ds, play_basedir)
label = play.name
if options.listhosts:
hosts = pb.inventory.list_hosts(play.hosts)
print ' play #%d (%s): host count=%d' % (playnum, label, len(hosts))
for host in hosts:
print ' %s' % host
if options.listtasks:
matched_tags, unmatched_tags = play.compare_tags(pb.only_tags)
# Remove skipped tasks
matched_tags = matched_tags - set(pb.skip_tags)
unmatched_tags.discard('all')
unknown_tags = ((set(pb.only_tags) | set(pb.skip_tags)) -
(matched_tags | unmatched_tags))
if unknown_tags:
continue
print ' play #%d (%s):' % (playnum, label)
for task in play.tasks():
if (set(task.tags).intersection(pb.only_tags) and not
set(task.tags).intersection(pb.skip_tags)):
if getattr(task, 'name', None) is not None:
# meta tasks have no names
print ' %s' % task.name
print ''
continue
if options.syntax:
# if we've not exited by now then we are fine.
print 'Playbook Syntax is fine'
return 0
failed_hosts = []
unreachable_hosts = []
try:
pb.run()
hosts = sorted(pb.stats.processed.keys())
display(callbacks.banner("PLAY RECAP"))
playbook_cb.on_stats(pb.stats)
for h in hosts:
t = pb.stats.summarize(h)
if t['failures'] > 0:
failed_hosts.append(h)
if t['unreachable'] > 0:
unreachable_hosts.append(h)
retries = failed_hosts + unreachable_hosts
if len(retries) > 0:
filename = pb.generate_retry_inventory(retries)
if filename:
display(" to retry, use: --limit @%s\n" % filename)
for h in hosts:
t = pb.stats.summarize(h)
display("%s : %s %s %s %s" % (
hostcolor(h, t),
colorize('ok', t['ok'], 'green'),
colorize('changed', t['changed'], 'yellow'),
colorize('unreachable', t['unreachable'], 'red'),
colorize('failed', t['failures'], 'red')),
screen_only=True
)
display("%s : %s %s %s %s" % (
hostcolor(h, t, False),
colorize('ok', t['ok'], None),
colorize('changed', t['changed'], None),
colorize('unreachable', t['unreachable'], None),
colorize('failed', t['failures'], None)),
log_only=True
)
print ""
if len(failed_hosts) > 0:
return 2
if len(unreachable_hosts) > 0:
return 3
except errors.AnsibleError, e:
display("ERROR: %s" % e, color='red')
return 1
return 0
if __name__ == "__main__":
display(" ", log_only=True)
display(" ".join(sys.argv), log_only=True)
display(" ", log_only=True)
try:
sys.exit(main(sys.argv[1:]))
except errors.AnsibleError, e:
display("ERROR: %s" % e, color='red', stderr=True)
sys.exit(1)
except KeyboardInterrupt, ke:
display("ERROR: interrupted", color='red', stderr=True)
sys.exit(1)

View File

@ -1 +0,0 @@
../lib/ansible/cli/pull.py

207
bin/ansible-pull Executable file
View File

@ -0,0 +1,207 @@
#!/usr/bin/env python
# (c) 2012, Stephen Fromm <sfromm@gmail.com>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
# ansible-pull is a script that runs ansible in local mode
# after checking out a playbooks directory from source repo. There is an
# example playbook to bootstrap this script in the examples/ dir which
# installs ansible and sets it up to run on cron.
# usage:
# ansible-pull -d /var/lib/ansible \
# -U http://example.net/content.git [-C production] \
# [path/playbook.yml]
#
# the -d and -U arguments are required; the -C argument is optional.
#
# ansible-pull accepts an optional argument to specify a playbook
# location underneath the workdir and then searches the source repo
# for playbooks in the following order, stopping at the first match:
#
# 1. $workdir/path/playbook.yml, if specified
# 2. $workdir/$fqdn.yml
# 3. $workdir/$hostname.yml
# 4. $workdir/local.yml
#
# the source repo must contain at least one of these playbooks.
import os
import shutil
import subprocess
import sys
import datetime
import socket
from ansible import utils
from ansible.utils import cmd_functions
from ansible import errors
DEFAULT_REPO_TYPE = 'git'
DEFAULT_PLAYBOOK = 'local.yml'
PLAYBOOK_ERRORS = {1: 'File does not exist',
2: 'File is not readable'}
VERBOSITY=0
def increment_debug(option, opt, value, parser):
global VERBOSITY
VERBOSITY += 1
def try_playbook(path):
if not os.path.exists(path):
return 1
if not os.access(path, os.R_OK):
return 2
return 0
def select_playbook(path, args):
playbook = None
if len(args) > 0 and args[0] is not None:
playbook = "%s/%s" % (path, args[0])
rc = try_playbook(playbook)
if rc != 0:
print >>sys.stderr, "%s: %s" % (playbook, PLAYBOOK_ERRORS[rc])
return None
return playbook
else:
fqdn = socket.getfqdn()
hostpb = "%s/%s.yml" % (path, fqdn)
shorthostpb = "%s/%s.yml" % (path, fqdn.split('.')[0])
localpb = "%s/%s" % (path, DEFAULT_PLAYBOOK)
errors = []
for pb in [hostpb, shorthostpb, localpb]:
rc = try_playbook(pb)
if rc == 0:
playbook = pb
break
else:
errors.append("%s: %s" % (pb, PLAYBOOK_ERRORS[rc]))
if playbook is None:
print >>sys.stderr, "\n".join(errors)
return playbook
def main(args):
""" Set up and run a local playbook """
usage = "%prog [options] [playbook.yml]"
parser = utils.SortedOptParser(usage=usage)
parser.add_option('--purge', default=False, action='store_true',
help='purge checkout after playbook run')
parser.add_option('-o', '--only-if-changed', dest='ifchanged', default=False, action='store_true',
help='only run the playbook if the repository has been updated')
parser.add_option('-f', '--force', dest='force', default=False,
action='store_true',
help='run the playbook even if the repository could '
'not be updated')
parser.add_option('-d', '--directory', dest='dest', default=None,
help='directory to checkout repository to')
#parser.add_option('-l', '--live', default=True, action='store_live',
# help='Print the ansible-playbook output while running')
parser.add_option('-U', '--url', dest='url', default=None,
help='URL of the playbook repository')
parser.add_option('-C', '--checkout', dest='checkout',
help='branch/tag/commit to checkout. '
'Defaults to behavior of repository module.')
parser.add_option('-i', '--inventory-file', dest='inventory',
help="location of the inventory host file")
parser.add_option('-v', '--verbose', default=False, action="callback",
callback=increment_debug,
help='Pass -vvvv to ansible-playbook')
parser.add_option('-m', '--module-name', dest='module_name',
default=DEFAULT_REPO_TYPE,
help='Module name used to check out repository. '
'Default is %s.' % DEFAULT_REPO_TYPE)
parser.add_option('--vault-password-file', dest='vault_password_file',
help="vault password file")
options, args = parser.parse_args(args)
hostname = socket.getfqdn()
if not options.dest:
# use a hostname dependent directory, in case of $HOME on nfs
options.dest = utils.prepare_writeable_dir('~/.ansible/pull/%s' % hostname)
options.dest = os.path.abspath(options.dest)
if not options.url:
parser.error("URL for repository not specified, use -h for help")
return 1
now = datetime.datetime.now()
print >>sys.stderr, now.strftime("Starting ansible-pull at %F %T")
inv_opts = 'localhost,'
limit_opts = 'localhost:%s:127.0.0.1' % hostname
repo_opts = "name=%s dest=%s" % (options.url, options.dest)
if VERBOSITY == 0:
base_opts = '-c local --limit "%s"' % limit_opts
elif VERBOSITY > 0:
debug_level = ''.join([ "v" for x in range(0, VERBOSITY) ])
base_opts = '-%s -c local --limit "%s"' % (debug_level, limit_opts)
if options.checkout:
repo_opts += ' version=%s' % options.checkout
path = utils.plugins.module_finder.find_plugin(options.module_name)
if path is None:
sys.stderr.write("module '%s' not found.\n" % options.module_name)
return 1
cmd = 'ansible all -i "%s" %s -m %s -a "%s"' % (
inv_opts, base_opts, options.module_name, repo_opts
)
# RUN THE CHECKOUT COMMAND
rc, out, err = cmd_functions.run_cmd(cmd, live=True)
if rc != 0:
if options.force:
print "Unable to update repository. Continuing with (forced) run of playbook."
else:
return rc
elif options.ifchanged and '"changed": true' not in out:
print "Repository has not changed, quitting."
return 0
playbook = select_playbook(options.dest, args)
if playbook is None:
print >>sys.stderr, "Could not find a playbook to run."
return 1
cmd = 'ansible-playbook %s %s' % (base_opts, playbook)
if options.vault_password_file:
cmd += " --vault-password-file=%s" % options.vault_password_file
if options.inventory:
cmd += ' -i "%s"' % options.inventory
os.chdir(options.dest)
# RUN THE PLAYBOOK COMMAND
rc, out, err = cmd_functions.run_cmd(cmd, live=True)
if options.purge:
os.chdir('/')
try:
shutil.rmtree(options.dest)
except Exception, e:
print >>sys.stderr, "Failed to remove %s: %s" % (options.dest, str(e))
return rc
if __name__ == '__main__':
try:
sys.exit(main(sys.argv[1:]))
except KeyboardInterrupt, e:
print >>sys.stderr, "Exit on user request.\n"
sys.exit(1)

View File

@ -1 +0,0 @@
../test/lib/ansible_test/_util/target/cli/ansible_test_cli_stub.py

View File

@ -1 +0,0 @@
../lib/ansible/cli/vault.py

220
bin/ansible-vault Executable file
View File

@ -0,0 +1,220 @@
#!/usr/bin/env python
# (c) 2014, James Tanner <tanner.jc@gmail.com>
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
# ansible-pull is a script that runs ansible in local mode
# after checking out a playbooks directory from source repo. There is an
# example playbook to bootstrap this script in the examples/ dir which
# installs ansible and sets it up to run on cron.
import os
import sys
import traceback
from ansible import utils
from ansible import errors
from ansible.utils.vault import VaultEditor
from optparse import OptionParser
#-------------------------------------------------------------------------------------
# Utility functions for parsing actions/options
#-------------------------------------------------------------------------------------
VALID_ACTIONS = ("create", "decrypt", "edit", "encrypt", "rekey")
def build_option_parser(action):
"""
Builds an option parser object based on the action
the user wants to execute.
"""
usage = "usage: %%prog [%s] [--help] [options] file_name" % "|".join(VALID_ACTIONS)
epilog = "\nSee '%s <command> --help' for more information on a specific command.\n\n" % os.path.basename(sys.argv[0])
OptionParser.format_epilog = lambda self, formatter: self.epilog
parser = OptionParser(usage=usage, epilog=epilog)
if not action:
parser.print_help()
sys.exit()
# options for all actions
#parser.add_option('-c', '--cipher', dest='cipher', default="AES256", help="cipher to use")
parser.add_option('--debug', dest='debug', action="store_true", help="debug")
parser.add_option('--vault-password-file', dest='password_file',
help="vault password file")
# options specific to actions
if action == "create":
parser.set_usage("usage: %prog create [options] file_name")
elif action == "decrypt":
parser.set_usage("usage: %prog decrypt [options] file_name")
elif action == "edit":
parser.set_usage("usage: %prog edit [options] file_name")
elif action == "encrypt":
parser.set_usage("usage: %prog encrypt [options] file_name")
elif action == "rekey":
parser.set_usage("usage: %prog rekey [options] file_name")
# done, return the parser
return parser
def get_action(args):
"""
Get the action the user wants to execute from the
sys argv list.
"""
for i in range(0,len(args)):
arg = args[i]
if arg in VALID_ACTIONS:
del args[i]
return arg
return None
def get_opt(options, k, defval=""):
"""
Returns an option from an Optparse values instance.
"""
try:
data = getattr(options, k)
except:
return defval
if k == "roles_path":
if os.pathsep in data:
data = data.split(os.pathsep)[0]
return data
#-------------------------------------------------------------------------------------
# Command functions
#-------------------------------------------------------------------------------------
def _read_password(filename):
f = open(filename, "rb")
data = f.read()
f.close
# get rid of newline chars
data = data.strip()
return data
def execute_create(args, options, parser):
if len(args) > 1:
raise errors.AnsibleError("'create' does not accept more than one filename")
if not options.password_file:
password, new_password = utils.ask_vault_passwords(ask_vault_pass=True, confirm_vault=True)
else:
password = _read_password(options.password_file)
cipher = 'AES256'
if hasattr(options, 'cipher'):
cipher = options.cipher
this_editor = VaultEditor(cipher, password, args[0])
this_editor.create_file()
def execute_decrypt(args, options, parser):
if not options.password_file:
password, new_password = utils.ask_vault_passwords(ask_vault_pass=True)
else:
password = _read_password(options.password_file)
cipher = 'AES256'
if hasattr(options, 'cipher'):
cipher = options.cipher
for f in args:
this_editor = VaultEditor(cipher, password, f)
this_editor.decrypt_file()
print "Decryption successful"
def execute_edit(args, options, parser):
if len(args) > 1:
raise errors.AnsibleError("create does not accept more than one filename")
if not options.password_file:
password, new_password = utils.ask_vault_passwords(ask_vault_pass=True)
else:
password = _read_password(options.password_file)
cipher = None
for f in args:
this_editor = VaultEditor(cipher, password, f)
this_editor.edit_file()
def execute_encrypt(args, options, parser):
if len(args) > 1:
raise errors.AnsibleError("'create' does not accept more than one filename")
if not options.password_file:
password, new_password = utils.ask_vault_passwords(ask_vault_pass=True, confirm_vault=True)
else:
password = _read_password(options.password_file)
cipher = 'AES256'
if hasattr(options, 'cipher'):
cipher = options.cipher
for f in args:
this_editor = VaultEditor(cipher, password, f)
this_editor.encrypt_file()
print "Encryption successful"
def execute_rekey(args, options, parser):
if not options.password_file:
password, __ = utils.ask_vault_passwords(ask_vault_pass=True)
else:
password = _read_password(options.password_file)
__, new_password = utils.ask_vault_passwords(ask_vault_pass=False, ask_new_vault_pass=True, confirm_new=True)
cipher = None
for f in args:
this_editor = VaultEditor(cipher, password, f)
this_editor.rekey_file(new_password)
print "Rekey successful"
#-------------------------------------------------------------------------------------
# MAIN
#-------------------------------------------------------------------------------------
def main():
action = get_action(sys.argv)
parser = build_option_parser(action)
(options, args) = parser.parse_args()
# execute the desired action
try:
fn = globals()["execute_%s" % action]
fn(args, options, parser)
except Exception, err:
if options.debug:
print traceback.format_exc()
print "ERROR:",err
sys.exit(1)
if __name__ == "__main__":
main()

View File

@ -1,369 +0,0 @@
==============================================
ansible-core 2.17 "Gallows Pole" Release Notes
==============================================
.. contents:: Topics
v2.17.4
=======
Release Summary
---------------
| Release Date: 2024-09-09
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__
Bugfixes
--------
- Fix ``SemanticVersion.parse()`` to store the version string so that ``__repr__`` reports it instead of ``None`` (https://github.com/ansible/ansible/pull/83831).
- Fix an issue where registered variable was not available for templating in ``loop_control.label`` on skipped looped tasks (https://github.com/ansible/ansible/issues/83619)
- Fix for ``meta`` tasks breaking host/fork affinity with ``host_pinned`` strategy (https://github.com/ansible/ansible/issues/83294)
- Fix using the current task's directory for looking up relative paths within roles (https://github.com/ansible/ansible/issues/82695).
- atomic_move - fix using the setgid bit on the parent directory when creating files (https://github.com/ansible/ansible/issues/46742, https://github.com/ansible/ansible/issues/67177).
- connection plugins using the 'extras' option feature would need variables to match the plugin's loaded name, sometimes requiring fqcn, which is not the same as the documented/declared/expected variables. Now we fall back to the 'basename' of the fqcn, but plugin authors can still set the expected value directly.
- csvfile lookup - give an error when no search term is provided using modern config syntax (https://github.com/ansible/ansible/issues/83689).
- include_tasks - Display location when attempting to load a task list where ``include_*`` did not specify any value - https://github.com/ansible/ansible/issues/83874
- powershell - Improve CLIXML decoding to decode all control characters and unicode characters that are encoded as surrogate pairs.
- psrp - Fix bug when attempting to fetch a file path that contains special glob characters like ``[]``
- runtime-metadata sanity test - do not crash on deprecations if ``galaxy.yml`` contains an empty ``version`` field (https://github.com/ansible/ansible/pull/83831).
- ssh - Fix bug when attempting to fetch a file path with characters that should be quoted when using the ``piped`` transfer method
v2.17.3
=======
Release Summary
---------------
| Release Date: 2024-08-12
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__
Minor Changes
-------------
- ansible-test - Improve the error message shown when an unknown ``--remote`` or ``--docker`` option is given.
- ansible-test - Removed the ``vyos/1.1.8`` network remote as it is no longer functional.
Bugfixes
--------
- Warning now includes filename and line number of variable when specifying a list of dictionaries for vars (https://github.com/ansible/ansible/issues/82528).
- config, restored the ability to set module compression via a variable
- debconf - fix normalization of value representation for boolean vtypes in new packages (https://github.com/ansible/ansible/issues/83594)
- linear strategy: fix handlers included via ``include_tasks`` handler to be executed in lockstep (https://github.com/ansible/ansible/issues/83019)
v2.17.2
=======
Release Summary
---------------
| Release Date: 2024-07-15
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__
Bugfixes
--------
- Fix a traceback when an environment variable contains certain special characters (https://github.com/ansible/ansible/issues/83498)
- dnf - reverted incomplete fix from 2.17.2rc1 (https://github.com/ansible/ansible/pull/83504)
- dnf, dnf5 - fix for installing a set of packages by specifying them using a wildcard character (https://github.com/ansible/ansible/issues/83373)
- linear strategy now provides a properly templated task name to the v2_runner_on_started callback event.
- package_facts - ignore warnings sent by apk on stderr (https://github.com/ansible/ansible/issues/83501).
- replace - Updated before/after example (https://github.com/ansible/ansible/issues/83390).
- templating hostvars under native jinja will not cause serialization errors anymore.
v2.17.1
=======
Release Summary
---------------
| Release Date: 2024-06-17
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__
Minor Changes
-------------
- ansible-test - Update ``pypi-test-container`` to version 3.1.0.
Bugfixes
--------
- Fix rapid memory usage growth when notifying handlers using the ``listen`` keyword (https://github.com/ansible/ansible/issues/83392)
- Fix the task attribute ``resolved_action`` to show the FQCN instead of ``None`` when ``action`` or ``local_action`` is used in the playbook.
- Fix using ``module_defaults`` with ``local_action``/``action`` (https://github.com/ansible/ansible/issues/81905).
- fixed unit test test_borken_cowsay to address mock not been properly applied when existing unix system already have cowsay installed.
- powershell - Implement more robust deletion mechanism for C# code compilation temporary files. This should avoid scenarios where the underlying temporary directory may be temporarily locked by antivirus tools or other IO problems. A failure to delete one of these temporary directories will result in a warning rather than an outright failure.
- shell plugin - properly quote all needed components of shell commands (https://github.com/ansible/ansible/issues/82535)
v2.17.0
=======
Release Summary
---------------
| Release Date: 2024-05-20
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__
Major Changes
-------------
- urls.py - Removed support for Python 2
Minor Changes
-------------
- Add ``dump`` and ``passno`` mount information to facts component (https://github.com/ansible/ansible/issues/80478)
- Added MIRACLE LINUX 9.2 in RedHat OS Family.
- Interpreter Discovery - Remove hardcoded references to specific python interpreters to use for certain distro versions, and modify logic for python3 to become the default.
- Use Python's built-in ``functools.update_wrapper`` instead an inline copy from Python 3.7.
- User can now set ansible.log to record higher verbosity than what is specified for display via new configuration item LOG_VERBOSITY.
- ``DEFAULT_PRIVATE_ROLE_VARS`` is now overridden by explicit setting of ``public`` for ``include_roles`` and ``import_roles``.
- ``ansible-galaxy role|collection init`` - accept ``--extra-vars`` to supplement/override the variables ``ansible-galaxy`` injects for templating ``.j2`` files in the skeleton.
- ``import_role`` action now also gets a ``public`` option that controls variable exports, default depending on ``DEFAULT_PRIVATE_ROLE_VARS`` (if using defaults equates to ``public=True``).
- added configuration item ``TARGET_LOG_INFO`` that allows the user/author to add an information string to the log output on targets.
- ansible-doc - treat double newlines in documentation strings as paragraph breaks. This is useful to create multi-paragraph notes in module/plugin documentation (https://github.com/ansible/ansible/pull/82465).
- ansible-doc output has been revamped to make it more visually pleasing when going to a terminal, also more concise, use -v to show extra information.
- ansible-galaxy - Started normalizing build directory with a trailing separator when building collections, internally. (https://github.com/ansible/ansible/pull/81619).
- ansible-galaxy dependency resolution messages have changed the unexplained 'virtual' collection for the specific type ('scm', 'dir', etc) that is more user friendly
- ansible-test - Add Alpine 3.19 container.
- ansible-test - Add Alpine 3.19 to remotes.
- ansible-test - Add Fedora 39 container.
- ansible-test - Add Fedora 39 remote.
- ansible-test - Add a work-around for permission denied errors when using ``pytest >= 8`` on multi-user systems with an installed version of ``ansible-test``.
- ansible-test - Add support for RHEL 9.3 remotes.
- ansible-test - Added a macOS 14.3 remote VM.
- ansible-test - Bump the ``nios-test-container`` from version 2.0.0 to version 3.0.0.
- ansible-test - Containers and remotes managed by ansible-test will have their Python ``EXTERNALLY-MANAGED`` marker (PEP668) removed. This provides backwards compatibility for existing tests running in newer environments which mark their Python as externally managed. A future version of ansible-test may change this behavior, requiring tests to be adapted to such environments.
- ansible-test - Make Python 3.12 the default version used in the ``base`` and ``default`` containers.
- ansible-test - Remove Alpine 3(.18) container.
- ansible-test - Remove Alpine 3.18 from remotes.
- ansible-test - Remove Fedora 38 remote support.
- ansible-test - Remove Fedora 38 test container.
- ansible-test - Remove rhel/9.2 test remote
- ansible-test - Remove the FreeBSD 13.2 remote.
- ansible-test - Removed fallback to ``virtualenv`` when ``-m venv`` is non-functional.
- ansible-test - Removed test remotes: macos/13.2
- ansible-test - Removed the ``no-basestring`` sanity test. The test is no longer necessary now that Python 3 is required.
- ansible-test - Removed the ``no-dict-iteritems``, ``no-dict-iterkeys`` and ``no-dict-itervalues`` sanity tests. The tests are no longer necessary since Python 3 is required.
- ansible-test - Removed the ``no-main-display`` sanity test. The unwanted pattern is unlikely to occur, since the test has existed since Ansible 2.8.
- ansible-test - Removed the ``no-unicode-literals`` sanity test. The test is unnecessary now that Python 3 is required and the ``unicode_literals`` feature has no effect.
- ansible-test - Special handling for installation of ``cryptography`` has been removed, as it is no longer necessary.
- ansible-test - The ``shellcheck`` sanity test no longer disables the ``SC2164`` check. In most cases, seeing this error means the script is missing ``set -e``.
- ansible-test - The ``unidiomatic-typecheck`` rule has been enabled in the ``pylint`` sanity test.
- ansible-test - The ``unidiomatic-typecheck`` rule has been removed from the ``validate-modules`` sanity test.
- ansible-test - Update the base and default containers to use Ubuntu 22.04 for the base image. This also updates PowerShell to version 7.4.0 with .NET 8.0.0 and ShellCheck to version 0.8.0.
- ansible-test - Updated the CloudStack test container to version 1.7.0.
- ansible-test - Updated the distro test containers to version 6.3.0 to include coverage 7.3.2 for Python 3.8+. The alpine3 container is now based on 3.18 instead of 3.17 and includes Python 3.11 instead of Python 3.10.
- ansible-test - Updated the distro test containers to version 7.1.0.
- ansible-test - When ansible-test installs requirements, it now instructs pip to allow installs on externally managed environments as defined by PEP 668. This only occurs in ephemeral environments managed by ansible-test, such as containers, or when the `--requirements` option is used.
- ansible-test - When invoking ``sleep`` in containers during container setup, the ``env`` command is used to avoid invoking the shell builtin, if present.
- ansible-test - document block name now included in error message for YAML parsing errors (https://github.com/ansible/ansible/issues/82353).
- ansible-test - sanity test allows ``EXAMPLES`` to be multi-document YAML (https://github.com/ansible/ansible/issues/82353).
- ansible-test now has FreeBSD 13.3 and 14.0 support
- ansible.builtin.user - Remove user not found warning (https://github.com/ansible/ansible/issues/80267)
- apt_repository.py - use api.launchpad.net endpoint instead of launchpad.net/api
- async tasks can now also support check mode at the same time.
- async_status now supports check mode.
- constructed inventory plugin - Adding a note that only group_vars of explicit groups are loaded (https://github.com/ansible/ansible/pull/82580).
- csvfile - add a keycol parameter to specify in which column to search.
- dnf - add the ``best`` option
- dnf5 - add the ``best`` option
- filter plugin - Add the count and mandatory_count parameters in the regex_replace filter
- find - add a encoding parameter to specify which encoding of the files to be searched.
- git module - gpg_allowlist name was added in 2.17 and we will eventually deprecate the gpg_whitelist alias.
- import_role - allow subdirectories with ``_from`` options for parity with ``include_role`` (https://github.com/ansible/ansible/issues/82584).
- module argument spec - Allow module authors to include arbitrary additional context in the argument spec, by making use of a new top level key called ``context``. This key should be a dict type. This allows for users to customize what they place in the argument spec, without having to ignore sanity tests that validate the schema.
- modules - Add the ability for an action plugin to call ``self._execute_module(*, ignore_unknown_opts=True)`` to execute a module with options that may not be supported for the version being called. This tells the module basic wrapper to ignore validating the options provided match the arg spec.
- package action now has a configuration that overrides the detected package manager, it is still overridden itself by the use option.
- py3compat - Remove ``ansible.utils.py3compat`` as it is no longer necessary
- removed the unused argument ``create_new_password`` from ``CLI.build_vault_ids`` (https://github.com/ansible/ansible/pull/82066).
- urls - Add support for TLS 1.3 post handshake certificate authentication - https://github.com/ansible/ansible/issues/81782
- urls - reduce complexity of ``Request.open``
- user - accept yescrypt hash as user password
- validate-modules tests now correctly handles ``choices`` in dictionary format.
Breaking Changes / Porting Guide
--------------------------------
- assert - Nested templating may result in an inability for the conditional to be evaluated. See the porting guide for more information.
Deprecated Features
-------------------
- Old style vars plugins which use the entrypoints `get_host_vars` or `get_group_vars` are deprecated. The plugin should be updated to inherit from `BaseVarsPlugin` and define a `get_vars` method as the entrypoint.
- The 'required' parameter in 'ansible.module_utils.common.process.get_bin_path' API is deprecated (https://github.com/ansible/ansible/issues/82464).
- ``module_utils`` - importing the following convenience helpers from ``ansible.module_utils.basic`` has been deprecated: ``get_exception``, ``literal_eval``, ``_literal_eval``, ``datetime``, ``signal``, ``types``, ``chain``, ``repeat``, ``PY2``, ``PY3``, ``b``, ``binary_type``, ``integer_types``, ``iteritems``, ``string_types``, ``test_type``, ``map`` and ``shlex_quote``.
- ansible-doc - role entrypoint attributes are deprecated and eventually will no longer be shown in ansible-doc from ansible-core 2.20 on (https://github.com/ansible/ansible/issues/82639, https://github.com/ansible/ansible/pull/82678).
- paramiko connection plugin, configuration items in the global scope are being deprecated and will be removed in favor or the existing same options in the plugin itself. Users should not need to change anything (how to configure them are the same) but plugin authors using the global constants should move to using the plugin's get_option().
Removed Features (previously deprecated)
----------------------------------------
- Remove deprecated APIs from ansible-docs (https://github.com/ansible/ansible/issues/81716).
- Remove deprecated JINJA2_NATIVE_WARNING environment variable (https://github.com/ansible/ansible/issues/81714)
- Remove deprecated ``scp_if_ssh`` from ssh connection plugin (https://github.com/ansible/ansible/issues/81715).
- Remove deprecated crypt support from ansible.utils.encrypt (https://github.com/ansible/ansible/issues/81717)
- Removed Python 2.7 and Python 3.6 as a supported remote version. Python 3.7+ is now required for target execution.
- With the removal of Python 2 support, the yum module and yum action plugin are removed and redirected to ``dnf``.
Security Fixes
--------------
- ANSIBLE_NO_LOG - Address issue where ANSIBLE_NO_LOG was ignored (CVE-2024-0690)
- ansible-galaxy - Prevent roles from using symlinks to overwrite files outside of the installation directory (CVE-2023-5115)
- templating - Address issues where internal templating can cause unsafe variables to lose their unsafe designation (CVE-2023-5764)
Bugfixes
--------
- Add a version ceiling constraint for pypsrp to avoid potential breaking changes in the 1.0.0 release.
- All core lookups now use set_option(s) even when doing their own custom parsing. This ensures that the options are always the proper type.
- Allow for searching handler subdir for included task via include_role (https://github.com/ansible/ansible/issues/81722)
- AnsibleModule.atomic_move - fix preserving extended ACLs of the destination when it exists (https://github.com/ansible/ansible/issues/72929).
- Cache host_group_vars after instantiating it once and limit the amount of repetitive work it needs to do every time it runs.
- Call PluginLoader.all() once for vars plugins, and load vars plugins that run automatically or are enabled specifically by name subsequently.
- Consolidate systemd detection logic into one place (https://github.com/ansible/ansible/issues/80975).
- Consolidated the list of internal static vars, centralized them as constant and completed from some missing entries.
- Do not print undefined error message twice (https://github.com/ansible/ansible/issues/78703).
- Enable file cache for vaulted files during vars lookup to fix a strong performance penalty in huge and complex playbboks.
- Fix NEVRA parsing of package names that include digit(s) in them (https://github.com/ansible/ansible/issues/76463, https://github.com/ansible/ansible/issues/81018)
- Fix ``force_handlers`` not working with ``any_errors_fatal`` (https://github.com/ansible/ansible/issues/36308)
- Fix ``run_once`` being incorrectly interpreted on handlers (https://github.com/ansible/ansible/issues/81666)
- Fix an issue when setting a plugin name from an unsafe source resulted in ``ValueError: unmarshallable object`` (https://github.com/ansible/ansible/issues/82708)
- Fix check for missing _sub_plugin attribute in older connection plugins (https://github.com/ansible/ansible/pull/82954)
- Fix condition for unquoting configuration strings from ini files (https://github.com/ansible/ansible/issues/82387).
- Fix for when ``any_errors_fatal`` was ignored if error occurred in a block with always (https://github.com/ansible/ansible/issues/31543)
- Fix handlers not being executed in lockstep using the linear strategy in some cases (https://github.com/ansible/ansible/issues/82307)
- Fix handling missing urls in ansible.module_utils.urls.fetch_file for Python 3.
- Fix issue where an ``include_tasks`` handler in a role was not able to locate a file in ``tasks/`` when ``tasks_from`` was used as a role entry point and ``main.yml`` was not present (https://github.com/ansible/ansible/issues/82241)
- Fix issues when tasks withing nested blocks wouldn't run when ``force_handlers`` is set (https://github.com/ansible/ansible/issues/81533)
- Fix loading vars_plugins in roles (https://github.com/ansible/ansible/issues/82239).
- Fix notifying role handlers by listen keyword topics with the "role_name : " prefix (https://github.com/ansible/ansible/issues/82849).
- Fix setting proper locale for git executable when running on non english systems, ensuring git output can always be parsed.
- Fix tasks in always section not being executed for nested blocks with ``any_errors_fatal`` (https://github.com/ansible/ansible/issues/73246)
- Fixes permission for cache json file from 600 to 644 (https://github.com/ansible/ansible/issues/82683).
- Give the tombstone error for ``include`` pre-fork like other tombstoned action/module plugins.
- Harden python templates for respawn and ansiballz around str literal quoting
- Include the task location when a module or action plugin is deprecated (https://github.com/ansible/ansible/issues/82450).
- Interpreter discovery - Add ``Amzn`` to ``OS_FAMILY_MAP`` for correct family fallback for interpreter discovery (https://github.com/ansible/ansible/issues/80882).
- Mirror the behavior of dnf on the command line when handling NEVRAs with omitted epoch (https://github.com/ansible/ansible/issues/71808)
- Plugin loader does not dedupe nor cache filter/test plugins by file basename, but full path name.
- Properly template tags in parent blocks (https://github.com/ansible/ansible/issues/81053)
- Provide additional information about the alternative plugin in the deprecation message (https://github.com/ansible/ansible/issues/80561).
- Remove the galaxy_info field ``platforms`` from the role templates (https://github.com/ansible/ansible/issues/82453).
- Restoring the ability of filters/tests can have same file base name but different tests/filters defined inside.
- Reword the error message when the module fails to parse parameters in JSON format (https://github.com/ansible/ansible/issues/81188).
- Reword warning if the reserved keyword _ansible_ used as a module parameter (https://github.com/ansible/ansible/issues/82514).
- Run all handlers with the same ``listen`` topic, even when notified from another handler (https://github.com/ansible/ansible/issues/82363).
- Slight optimization to hostvars (instantiate template only once per host, vs per call to var).
- Stopped misleadingly advertising ``async`` mode support in the ``reboot`` module (https://github.com/ansible/ansible/issues/71517).
- ``ansible-galaxy role import`` - fix using the ``role_name`` in a standalone role's ``galaxy_info`` metadata by disabling automatic removal of the ``ansible-role-`` prefix. This matches the behavior of the Galaxy UI which also no longer implicitly removes the ``ansible-role-`` prefix. Use the ``--role-name`` option or add a ``role_name`` to the ``galaxy_info`` dictionary in the role's ``meta/main.yml`` to use an alternate role name.
- ``ansible-test sanity --test runtime-metadata`` - add ``action_plugin`` as a valid field for modules in the schema (https://github.com/ansible/ansible/pull/82562).
- ``ansible.module_utils.service`` - ensure binary data transmission in ``daemonize()``
- ``any_errors_fatal`` should fail all hosts and rescue all of them when a ``rescue`` section is specified (https://github.com/ansible/ansible/issues/80981)
- ``include_role`` - properly execute ``v2_playbook_on_include`` and ``v2_runner_on_failed`` callbacks as well as increase ``ok`` and ``failed`` stats in the play recap, when appropriate (https://github.com/ansible/ansible/issues/77336)
- allow_duplicates - fix evaluating if the current role allows duplicates instead of using the initial value from the duplicate's cached role.
- ansible-config init will now dedupe ini entries from plugins.
- ansible-config will now properly template defaults before dumping them.
- ansible-doc - fixed "inicates" typo in output
- ansible-doc - format top-level descriptions with multiple paragraphs as multiple paragraphs, instead of concatenating them (https://github.com/ansible/ansible/pull/83155).
- ansible-galaxy - Deprecate use of the Galaxy v2 API (https://github.com/ansible/ansible/issues/81781)
- ansible-galaxy - Provide a better error message when using a requirements file with an invalid format - https://github.com/ansible/ansible/issues/81901
- ansible-galaxy - Resolve issue with the dataclass used for galaxy.yml manifest caused by using future annotations
- ansible-galaxy - ensure path to ansible collection when installing or downloading doesn't have a backslash (https://github.com/ansible/ansible/pull/79705).
- ansible-galaxy - started allowing the use of pre-releases for collections that do not have any stable versions published. (https://github.com/ansible/ansible/pull/81606)
- ansible-galaxy - started allowing the use of pre-releases for dependencies on any level of the dependency tree that specifically demand exact pre-release versions of collections and not version ranges. (https://github.com/ansible/ansible/pull/81606)
- ansible-galaxy error on dependency resolution will not error itself due to 'virtual' collections not having a name/namespace.
- ansible-galaxy info - fix reporting no role found when lookup_role_by_name returns None.
- ansible-galaxy role import - exit with 1 when the import fails (https://github.com/ansible/ansible/issues/82175).
- ansible-galaxy role install - fix installing roles from Galaxy that have version ``None`` (https://github.com/ansible/ansible/issues/81832).
- ansible-galaxy role install - fix symlinks (https://github.com/ansible/ansible/issues/82702, https://github.com/ansible/ansible/issues/81965).
- ansible-galaxy role install - normalize tarfile paths and symlinks using ``ansible.utils.path.unfrackpath`` and consider them valid as long as the realpath is in the tarfile's role directory (https://github.com/ansible/ansible/issues/81965).
- ansible-inventory - index available_hosts for major performance boost when dumping large inventories
- ansible-pull now will expand relative paths for the ``-d|--directory`` option is now expanded before use.
- ansible-pull will now correctly handle become and connection password file options for ansible-playbook.
- ansible-test - Add a ``pylint`` plugin to work around a known issue on Python 3.12.
- ansible-test - Explicitly supply ``ControlPath=none`` when setting up port forwarding over SSH to address the scenario where the local ssh configuration uses ``ControlPath`` for all hosts, and would prevent ports to be forwarded after the initial connection to the host.
- ansible-test - Fix parsing of cgroup entries which contain a ``:`` in the path (https://github.com/ansible/ansible/issues/81977).
- ansible-test - Include missing ``pylint`` requirements for Python 3.10.
- ansible-test - Properly detect docker host when using ``ssh://`` protocol for connecting to the docker daemon.
- ansible-test - The ``libexpat`` package is automatically upgraded during remote bootstrapping to maintain compatibility with newer Python packages.
- ansible-test - The ``validate-modules`` sanity test no longer attempts to process files with unrecognized extensions as Python (resolves https://github.com/ansible/ansible/issues/82604).
- ansible-test - Update ``pylint`` to version 3.0.1.
- ansible-test ansible-doc sanity test - do not remove underscores from plugin names in collections before calling ``ansible-doc`` (https://github.com/ansible/ansible/pull/82574).
- ansible-test validate-modules sanity test - do not treat leading underscores for plugin names in collections as an attempted deprecation (https://github.com/ansible/ansible/pull/82575).
- ansible-test — Python 3.8–3.12 will use ``coverage`` v7.3.2.
- ansible.builtin.apt - calling clean = true does not properly clean certain cache files such as /var/cache/apt/pkgcache.bin and /var/cache/apt/pkgcache.bin (https://github.com/ansible/ansible/issues/82611)
- ansible.builtin.uri - the module was ignoring the ``force`` parameter and always requesting a cached copy (via the ``If-Modified-Since`` header) when downloading to an existing local file. Disable caching when ``force`` is ``true``, as documented (https://github.com/ansible/ansible/issues/82166).
- ansible_managed restored it's 'templatability' by ensuring the possible injection routes are cut off earlier in the process.
- apt - honor install_recommends and dpkg_options while installing python3-apt library (https://github.com/ansible/ansible/issues/40608).
- apt - install recommended packages when installing package via deb file (https://github.com/ansible/ansible/issues/29726).
- apt_repository - do not modify repo files if the file is a symlink (https://github.com/ansible/ansible/issues/49809).
- apt_repository - update PPA URL to point to https URL (https://github.com/ansible/ansible/issues/82463).
- assemble - fixed missing parameter 'content' in _get_diff_data API (https://github.com/ansible/ansible/issues/82359).
- async - Fix bug that stopped running async task in ``--check`` when ``check_mode: False`` was set as a task attribute - https://github.com/ansible/ansible/issues/82811
- blockinfile - when ``create=true`` is used with a filename without path, the module crashed (https://github.com/ansible/ansible/pull/81638).
- check if there are attributes to set before attempting to set them (https://github.com/ansible/ansible/issues/76727)
- copy action now also generates temprary files as hidden ('.' prefixed) to avoid accidental pickup by running services that glob by extension.
- copy action now ensures that tempfiles use the same suffix as destination, to allow for ``validate`` to work with utilities that check extensions.
- deb822_repository - handle idempotency if the order of parameters is changed (https://github.com/ansible/ansible/issues/82454).
- debconf - allow user to specify a list for value when vtype is multiselect (https://github.com/ansible/ansible/issues/81345).
- delegate_to when set to an empty or undefined variable will now give a proper error.
- distribution.py - Recognize ALP-Dolomite as part of the SUSE OS family in Ansible, fixing its previous misidentification (https://github.com/ansible/ansible/pull/82496).
- distro - bump bundled distro version from 1.6.0 to 1.8.0 (https://github.com/ansible/ansible/issues/81713).
- dnf - fix an issue when cached RPMs were left in the cache directory even when the keepcache setting was unset (https://github.com/ansible/ansible/issues/81954)
- dnf - fix an issue when installing a package by specifying a file it provides could result in installing a different package providing the same file than the package already installed resulting in resolution failure (https://github.com/ansible/ansible/issues/82461)
- dnf - properly set gpg check options on enabled repositories according to the ``disable_gpg_check`` option (https://github.com/ansible/ansible/issues/80110)
- dnf - properly skip unavailable packages when ``skip_broken`` is enabled (https://github.com/ansible/ansible/issues/80590)
- dnf - the ``nobest`` option only overrides the distribution default when explicitly used, and is used for all supported operations (https://github.com/ansible/ansible/issues/82616)
- dnf5 - replace removed API calls
- dnf5 - respect ``allow_downgrade`` when installing packages directly from rpm files
- dnf5 - the ``nobest`` option only overrides the distribution default when used
- dwim functions for lookups should be better at detectging role context even in abscense of tasks/main.
- ensure we have logger before we log when we have increased verbosity.
- expect - fix argument spec error using timeout=null (https://github.com/ansible/ansible/issues/80982).
- fact gathering on linux now handles thread count by using rounding vs dropping decimals, it should give slightly more accurate numbers.
- facts - add a generic detection for VMware in product name.
- facts - detect VMware ESXi 8.0 virtualization by product name VMware20,1
- fetch - Do not calculate the file size for Windows fetch targets to improve performance.
- fetch - add error message when using ``dest`` with a trailing slash that becomes a local directory - https://github.com/ansible/ansible/issues/82878
- find - do not fail on Permission errors (https://github.com/ansible/ansible/issues/82027).
- first_found lookup now always returns a full (absolute) and normalized path
- first_found lookup now always takes into account k=v options
- flush_handlers - properly handle a handler failure in a nested block when ``force_handlers`` is set (http://github.com/ansible/ansible/issues/81532)
- galaxy - skip verification for unwanted Python compiled bytecode files (https://github.com/ansible/ansible/issues/81628).
- handle exception raised while validating with elements='int' and value is not within choices (https://github.com/ansible/ansible/issues/82776).
- include_tasks - include `ansible_loop_var` and `ansible_index_var` in a loop (https://github.com/ansible/ansible/issues/82655).
- include_vars - fix calculating ``depth`` relative to the root and ensure all files are included (https://github.com/ansible/ansible/issues/80987).
- interpreter_discovery - handle AnsibleError exception raised while interpreter discovery (https://github.com/ansible/ansible/issues/78264).
- iptables - add option choices 'src,src' and 'dst,dst' in match_set_flags (https://github.com/ansible/ansible/issues/81281).
- iptables - set jump to DSCP when set_dscp_mark or set_dscp_mark_class is set (https://github.com/ansible/ansible/issues/77077).
- known_hosts - Fix issue with `@cert-authority` entries in known_hosts incorrectly being removed.
- module no_log will no longer affect top level booleans, for example ``no_log_module_parameter='a'`` will no longer hide ``changed=False`` as a 'no log value' (matches 'a').
- moved assemble, raw, copy, fetch, reboot, script and wait_for_connection to query task instead of play_context ensuring they get the lastest and most correct data.
- reboot action now handles connections with 'timeout' vs only 'connection_timeout' settings.
- role params now have higher precedence than host facts again, matching documentation, this had unintentionally changed in 2.15.
- roles, code cleanup and performance optimization of dependencies, now cached, and ``public`` setting is now determined once, at role instantiation.
- roles, the ``static`` property is now correctly set, this will fix issues with ``public`` and ``DEFAULT_PRIVATE_ROLE_VARS`` controls on exporting vars.
- set_option method for plugins to update config now properly passes through type casting and validation.
- ssh - add tests for the SSH connection plugin.
- support url-encoded credentials in URLs like http://x%40:%40@example.com (https://github.com/ansible/ansible/pull/82552)
- syslog - Handle ValueError exception raised when sending Null Characters to syslog with Python 3.12.
- systemd_services - update documentation regarding required_one_of and required_by parameters (https://github.com/ansible/ansible/issues/82914).
- template - Fix error when templating an unsafe string which corresponds to an invalid type in Python (https://github.com/ansible/ansible/issues/82600).
- template action will also inherit the behavior from copy (as it uses it internally).
- templating - ensure syntax errors originating from a template being compiled into Python code object result in a failure (https://github.com/ansible/ansible/issues/82606)
- unarchive - add support for 8 character permission strings for zip archives (https://github.com/ansible/ansible/pull/81705).
- unarchive - force unarchive if symlink target changes (https://github.com/ansible/ansible/issues/30420).
- unarchive modules now uses zipinfo options without relying on implementation defaults, making it more compatible with all OS/distributions.
- unsafe data - Address an incompatibility when iterating or getting a single index from ``AnsibleUnsafeBytes``
- unsafe data - Address an incompatibility with ``AnsibleUnsafeText`` and ``AnsibleUnsafeBytes`` when pickling with ``protocol=0``
- unsafe data - Enable directly using ``AnsibleUnsafeText`` with Python ``pathlib`` (https://github.com/ansible/ansible/issues/82414)
- uri - update the documentation for follow_redirects.
- uri action plugin now skipped during check mode (not supported) instead of even trying to execute the module, which already skipped, this does not really change the result, but returns much faster.
- vars - handle exception while combining VarsWithSources and dict (https://github.com/ansible/ansible/issues/81659).
- wait_for should not handle 'non mmapable files' again.
- winrm - Better handle send input failures when communicating with hosts under load
- winrm - Do not raise another exception during cleanup when a task is timed out - https://github.com/ansible/ansible/issues/81095
- winrm - does not hang when attempting to get process output when stdin write failed

View File

@ -1,8 +0,0 @@
Changelogs
==========
As part of the release process a version-specific `CHANGELOG-vX.Y.rst` will be generated from fragments in
the `fragments` directory.
On release branches once a release has been created, consult the branch's version-specific file for changes that have
occurred in that branch. The `devel` branch does not have a generated changelog, only changelog fragments.

View File

@ -1,887 +0,0 @@
ancestor: 2.16.0
releases:
2.17.0:
changes:
release_summary: '| Release Date: 2024-05-20
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__
'
codename: Gallows Pole
fragments:
- 2.17.0_summary.yaml
release_date: '2024-05-20'
2.17.0b1:
changes:
breaking_changes:
- assert - Nested templating may result in an inability for the conditional
to be evaluated. See the porting guide for more information.
bugfixes:
- All core lookups now use set_option(s) even when doing their own custom parsing.
This ensures that the options are always the proper type.
- Allow for searching handler subdir for included task via include_role (https://github.com/ansible/ansible/issues/81722)
- AnsibleModule.atomic_move - fix preserving extended ACLs of the destination
when it exists (https://github.com/ansible/ansible/issues/72929).
- Cache host_group_vars after instantiating it once and limit the amount of
repetitive work it needs to do every time it runs.
- Call PluginLoader.all() once for vars plugins, and load vars plugins that
run automatically or are enabled specifically by name subsequently.
- Consolidate systemd detection logic into one place (https://github.com/ansible/ansible/issues/80975).
- Consolidated the list of internal static vars, centralized them as constant
and completed from some missing entries.
- Do not print undefined error message twice (https://github.com/ansible/ansible/issues/78703).
- Enable file cache for vaulted files during vars lookup to fix a strong performance
penalty in huge and complex playbboks.
- Fix NEVRA parsing of package names that include digit(s) in them (https://github.com/ansible/ansible/issues/76463,
https://github.com/ansible/ansible/issues/81018)
- Fix ``force_handlers`` not working with ``any_errors_fatal`` (https://github.com/ansible/ansible/issues/36308)
- Fix ``run_once`` being incorrectly interpreted on handlers (https://github.com/ansible/ansible/issues/81666)
- 'Fix an issue when setting a plugin name from an unsafe source resulted in
``ValueError: unmarshallable object`` (https://github.com/ansible/ansible/issues/82708)'
- Fix check for missing _sub_plugin attribute in older connection plugins (https://github.com/ansible/ansible/pull/82954)
- Fix condition for unquoting configuration strings from ini files (https://github.com/ansible/ansible/issues/82387).
- Fix for when ``any_errors_fatal`` was ignored if error occurred in a block
with always (https://github.com/ansible/ansible/issues/31543)
- Fix handling missing urls in ansible.module_utils.urls.fetch_file for Python
3.
- Fix issue where an ``include_tasks`` handler in a role was not able to locate
a file in ``tasks/`` when ``tasks_from`` was used as a role entry point and
``main.yml`` was not present (https://github.com/ansible/ansible/issues/82241)
- Fix issues when tasks withing nested blocks wouldn't run when ``force_handlers``
is set (https://github.com/ansible/ansible/issues/81533)
- Fix loading vars_plugins in roles (https://github.com/ansible/ansible/issues/82239).
- 'Fix notifying role handlers by listen keyword topics with the "role_name
: " prefix (https://github.com/ansible/ansible/issues/82849).'
- Fix setting proper locale for git executable when running on non english systems,
ensuring git output can always be parsed.
- Fix tasks in always section not being executed for nested blocks with ``any_errors_fatal``
(https://github.com/ansible/ansible/issues/73246)
- Fixes permission for cache json file from 600 to 644 (https://github.com/ansible/ansible/issues/82683).
- Give the tombstone error for ``include`` pre-fork like other tombstoned action/module
plugins.
- Harden python templates for respawn and ansiballz around str literal quoting
- Include the task location when a module or action plugin is deprecated (https://github.com/ansible/ansible/issues/82450).
- Interpreter discovery - Add ``Amzn`` to ``OS_FAMILY_MAP`` for correct family
fallback for interpreter discovery (https://github.com/ansible/ansible/issues/80882).
- Mirror the behavior of dnf on the command line when handling NEVRAs with omitted
epoch (https://github.com/ansible/ansible/issues/71808)
- Plugin loader does not dedupe nor cache filter/test plugins by file basename,
but full path name.
- Properly template tags in parent blocks (https://github.com/ansible/ansible/issues/81053)
- Provide additional information about the alternative plugin in the deprecation
message (https://github.com/ansible/ansible/issues/80561).
- Remove the galaxy_info field ``platforms`` from the role templates (https://github.com/ansible/ansible/issues/82453).
- Restoring the ability of filters/tests can have same file base name but different
tests/filters defined inside.
- Reword the error message when the module fails to parse parameters in JSON
format (https://github.com/ansible/ansible/issues/81188).
- Reword warning if the reserved keyword _ansible_ used as a module parameter
(https://github.com/ansible/ansible/issues/82514).
- Run all handlers with the same ``listen`` topic, even when notified from another
handler (https://github.com/ansible/ansible/issues/82363).
- Slight optimization to hostvars (instantiate template only once per host,
vs per call to var).
- Stopped misleadingly advertising ``async`` mode support in the ``reboot``
module (https://github.com/ansible/ansible/issues/71517).
- '``ansible-galaxy role import`` - fix using the ``role_name`` in a standalone
role''s ``galaxy_info`` metadata by disabling automatic removal of the ``ansible-role-``
prefix. This matches the behavior of the Galaxy UI which also no longer implicitly
removes the ``ansible-role-`` prefix. Use the ``--role-name`` option or add
a ``role_name`` to the ``galaxy_info`` dictionary in the role''s ``meta/main.yml``
to use an alternate role name.'
- '``ansible-test sanity --test runtime-metadata`` - add ``action_plugin`` as
a valid field for modules in the schema (https://github.com/ansible/ansible/pull/82562).'
- '``ansible.module_utils.service`` - ensure binary data transmission in ``daemonize()``'
- '``any_errors_fatal`` should fail all hosts and rescue all of them when a
``rescue`` section is specified (https://github.com/ansible/ansible/issues/80981)'
- '``include_role`` - properly execute ``v2_playbook_on_include`` and ``v2_runner_on_failed``
callbacks as well as increase ``ok`` and ``failed`` stats in the play recap,
when appropriate (https://github.com/ansible/ansible/issues/77336)'
- allow_duplicates - fix evaluating if the current role allows duplicates instead
of using the initial value from the duplicate's cached role.
- ansible-config init will now dedupe ini entries from plugins.
- ansible-galaxy - Deprecate use of the Galaxy v2 API (https://github.com/ansible/ansible/issues/81781)
- ansible-galaxy - Provide a better error message when using a requirements
file with an invalid format - https://github.com/ansible/ansible/issues/81901
- ansible-galaxy - Resolve issue with the dataclass used for galaxy.yml manifest
caused by using future annotations
- ansible-galaxy - ensure path to ansible collection when installing or downloading
doesn't have a backslash (https://github.com/ansible/ansible/pull/79705).
- ansible-galaxy - started allowing the use of pre-releases for collections
that do not have any stable versions published. (https://github.com/ansible/ansible/pull/81606)
- ansible-galaxy - started allowing the use of pre-releases for dependencies
on any level of the dependency tree that specifically demand exact pre-release
versions of collections and not version ranges. (https://github.com/ansible/ansible/pull/81606)
- ansible-galaxy error on dependency resolution will not error itself due to
'virtual' collections not having a name/namespace.
- ansible-galaxy info - fix reporting no role found when lookup_role_by_name
returns None.
- ansible-galaxy role import - exit with 1 when the import fails (https://github.com/ansible/ansible/issues/82175).
- ansible-galaxy role install - fix installing roles from Galaxy that have version
``None`` (https://github.com/ansible/ansible/issues/81832).
- ansible-galaxy role install - fix symlinks (https://github.com/ansible/ansible/issues/82702,
https://github.com/ansible/ansible/issues/81965).
- ansible-galaxy role install - normalize tarfile paths and symlinks using ``ansible.utils.path.unfrackpath``
and consider them valid as long as the realpath is in the tarfile's role directory
(https://github.com/ansible/ansible/issues/81965).
- ansible-inventory - index available_hosts for major performance boost when
dumping large inventories
- ansible-pull now will expand relative paths for the ``-d|--directory`` option
is now expanded before use.
- ansible-pull will now correctly handle become and connection password file
options for ansible-playbook.
- ansible-test - Add a ``pylint`` plugin to work around a known issue on Python
3.12.
- ansible-test - Explicitly supply ``ControlPath=none`` when setting up port
forwarding over SSH to address the scenario where the local ssh configuration
uses ``ControlPath`` for all hosts, and would prevent ports to be forwarded
after the initial connection to the host.
- ansible-test - Fix parsing of cgroup entries which contain a ``:`` in the
path (https://github.com/ansible/ansible/issues/81977).
- ansible-test - Include missing ``pylint`` requirements for Python 3.10.
- ansible-test - Properly detect docker host when using ``ssh://`` protocol
for connecting to the docker daemon.
- ansible-test - The ``libexpat`` package is automatically upgraded during remote
bootstrapping to maintain compatibility with newer Python packages.
- ansible-test - The ``validate-modules`` sanity test no longer attempts to
process files with unrecognized extensions as Python (resolves https://github.com/ansible/ansible/issues/82604).
- ansible-test - Update ``pylint`` to version 3.0.1.
- ansible-test ansible-doc sanity test - do not remove underscores from plugin
names in collections before calling ``ansible-doc`` (https://github.com/ansible/ansible/pull/82574).
- ansible-test validate-modules sanity test - do not treat leading underscores
for plugin names in collections as an attempted deprecation (https://github.com/ansible/ansible/pull/82575).
- "ansible-test \u2014 Python 3.8\u20133.12 will use ``coverage`` v7.3.2."
- ansible.builtin.apt - calling clean = true does not properly clean certain
cache files such as /var/cache/apt/pkgcache.bin and /var/cache/apt/pkgcache.bin
(https://github.com/ansible/ansible/issues/82611)
- ansible.builtin.uri - the module was ignoring the ``force`` parameter and
always requesting a cached copy (via the ``If-Modified-Since`` header) when
downloading to an existing local file. Disable caching when ``force`` is ``true``,
as documented (https://github.com/ansible/ansible/issues/82166).
- apt - honor install_recommends and dpkg_options while installing python3-apt
library (https://github.com/ansible/ansible/issues/40608).
- apt - install recommended packages when installing package via deb file (https://github.com/ansible/ansible/issues/29726).
- apt_repository - do not modify repo files if the file is a symlink (https://github.com/ansible/ansible/issues/49809).
- apt_repository - update PPA URL to point to https URL (https://github.com/ansible/ansible/issues/82463).
- assemble - fixed missing parameter 'content' in _get_diff_data API (https://github.com/ansible/ansible/issues/82359).
- 'async - Fix bug that stopped running async task in ``--check`` when ``check_mode:
False`` was set as a task attribute - https://github.com/ansible/ansible/issues/82811'
- blockinfile - when ``create=true`` is used with a filename without path, the
module crashed (https://github.com/ansible/ansible/pull/81638).
- check if there are attributes to set before attempting to set them (https://github.com/ansible/ansible/issues/76727)
- copy action now also generates temprary files as hidden ('.' prefixed) to
avoid accidental pickup by running services that glob by extension.
- copy action now ensures that tempfiles use the same suffix as destination,
to allow for ``validate`` to work with utilities that check extensions.
- deb822_repository - handle idempotency if the order of parameters is changed
(https://github.com/ansible/ansible/issues/82454).
- debconf - allow user to specify a list for value when vtype is multiselect
(https://github.com/ansible/ansible/issues/81345).
- delegate_to when set to an empty or undefined variable will now give a proper
error.
- distribution.py - Recognize ALP-Dolomite as part of the SUSE OS family in
Ansible, fixing its previous misidentification (https://github.com/ansible/ansible/pull/82496).
- distro - bump bundled distro version from 1.6.0 to 1.8.0 (https://github.com/ansible/ansible/issues/81713).
- dnf - fix an issue when cached RPMs were left in the cache directory even
when the keepcache setting was unset (https://github.com/ansible/ansible/issues/81954)
- dnf - fix an issue when installing a package by specifying a file it provides
could result in installing a different package providing the same file than
the package already installed resulting in resolution failure (https://github.com/ansible/ansible/issues/82461)
- dnf - properly set gpg check options on enabled repositories according to
the ``disable_gpg_check`` option (https://github.com/ansible/ansible/issues/80110)
- dnf - properly skip unavailable packages when ``skip_broken`` is enabled (https://github.com/ansible/ansible/issues/80590)
- dnf - the ``nobest`` option only overrides the distribution default when explicitly
used, and is used for all supported operations (https://github.com/ansible/ansible/issues/82616)
- dnf5 - respect ``allow_downgrade`` when installing packages directly from
rpm files
- dnf5 - the ``nobest`` option only overrides the distribution default when
used
- dwim functions for lookups should be better at detectging role context even
in abscense of tasks/main.
- expect - fix argument spec error using timeout=null (https://github.com/ansible/ansible/issues/80982).
- fact gathering on linux now handles thread count by using rounding vs dropping
decimals, it should give slightly more accurate numbers.
- facts - detect VMware ESXi 8.0 virtualization by product name VMware20,1
- fetch - Do not calculate the file size for Windows fetch targets to improve
performance.
- fetch - add error message when using ``dest`` with a trailing slash that becomes
a local directory - https://github.com/ansible/ansible/issues/82878
- find - do not fail on Permission errors (https://github.com/ansible/ansible/issues/82027).
- first_found lookup now always returns a full (absolute) and normalized path
- first_found lookup now always takes into account k=v options
- flush_handlers - properly handle a handler failure in a nested block when
``force_handlers`` is set (http://github.com/ansible/ansible/issues/81532)
- galaxy - skip verification for unwanted Python compiled bytecode files (https://github.com/ansible/ansible/issues/81628).
- handle exception raised while validating with elements='int' and value is
not within choices (https://github.com/ansible/ansible/issues/82776).
- include_tasks - include `ansible_loop_var` and `ansible_index_var` in a loop
(https://github.com/ansible/ansible/issues/82655).
- include_vars - fix calculating ``depth`` relative to the root and ensure all
files are included (https://github.com/ansible/ansible/issues/80987).
- interpreter_discovery - handle AnsibleError exception raised while interpreter
discovery (https://github.com/ansible/ansible/issues/78264).
- iptables - add option choices 'src,src' and 'dst,dst' in match_set_flags (https://github.com/ansible/ansible/issues/81281).
- iptables - set jump to DSCP when set_dscp_mark or set_dscp_mark_class is set
(https://github.com/ansible/ansible/issues/77077).
- known_hosts - Fix issue with `@cert-authority` entries in known_hosts incorrectly
being removed.
- module no_log will no longer affect top level booleans, for example ``no_log_module_parameter='a'``
will no longer hide ``changed=False`` as a 'no log value' (matches 'a').
- moved assemble, raw, copy, fetch, reboot, script and wait_for_connection to
query task instead of play_context ensuring they get the lastest and most
correct data.
- reboot action now handles connections with 'timeout' vs only 'connection_timeout'
settings.
- role params now have higher precedence than host facts again, matching documentation,
this had unintentionally changed in 2.15.
- roles, code cleanup and performance optimization of dependencies, now cached, and
``public`` setting is now determined once, at role instantiation.
- roles, the ``static`` property is now correctly set, this will fix issues
with ``public`` and ``DEFAULT_PRIVATE_ROLE_VARS`` controls on exporting vars.
- set_option method for plugins to update config now properly passes through
type casting and validation.
- ssh - add tests for the SSH connection plugin.
- support url-encoded credentials in URLs like http://x%40:%40@example.com (https://github.com/ansible/ansible/pull/82552)
- syslog - Handle ValueError exception raised when sending Null Characters to
syslog with Python 3.12.
- systemd_services - update documentation regarding required_one_of and required_by
parameters (https://github.com/ansible/ansible/issues/82914).
- template - Fix error when templating an unsafe string which corresponds to
an invalid type in Python (https://github.com/ansible/ansible/issues/82600).
- template action will also inherit the behavior from copy (as it uses it internally).
- templating - ensure syntax errors originating from a template being compiled
into Python code object result in a failure (https://github.com/ansible/ansible/issues/82606)
- unarchive - add support for 8 character permission strings for zip archives
(https://github.com/ansible/ansible/pull/81705).
- unarchive - force unarchive if symlink target changes (https://github.com/ansible/ansible/issues/30420).
- unarchive modules now uses zipinfo options without relying on implementation
defaults, making it more compatible with all OS/distributions.
- unsafe data - Address an incompatibility when iterating or getting a single
index from ``AnsibleUnsafeBytes``
- unsafe data - Address an incompatibility with ``AnsibleUnsafeText`` and ``AnsibleUnsafeBytes``
when pickling with ``protocol=0``
- unsafe data - Enable directly using ``AnsibleUnsafeText`` with Python ``pathlib``
(https://github.com/ansible/ansible/issues/82414)
- uri action plugin now skipped during check mode (not supported) instead of
even trying to execute the module, which already skipped, this does not really
change the result, but returns much faster.
- vars - handle exception while combining VarsWithSources and dict (https://github.com/ansible/ansible/issues/81659).
- wait_for should not handle 'non mmapable files' again.
- winrm - Better handle send input failures when communicating with hosts under
load
- winrm - Do not raise another exception during cleanup when a task is timed
out - https://github.com/ansible/ansible/issues/81095
- winrm - does not hang when attempting to get process output when stdin write
failed
deprecated_features:
- Old style vars plugins which use the entrypoints `get_host_vars` or `get_group_vars`
are deprecated. The plugin should be updated to inherit from `BaseVarsPlugin`
and define a `get_vars` method as the entrypoint.
- The 'required' parameter in 'ansible.module_utils.common.process.get_bin_path'
API is deprecated (https://github.com/ansible/ansible/issues/82464).
- '``module_utils`` - importing the following convenience helpers from ``ansible.module_utils.basic``
has been deprecated: ``get_exception``, ``literal_eval``, ``_literal_eval``,
``datetime``, ``signal``, ``types``, ``chain``, ``repeat``, ``PY2``, ``PY3``,
``b``, ``binary_type``, ``integer_types``, ``iteritems``, ``string_types``,
``test_type``, ``map`` and ``shlex_quote``.'
- ansible-doc - role entrypoint attributes are deprecated and eventually will
no longer be shown in ansible-doc from ansible-core 2.20 on (https://github.com/ansible/ansible/issues/82639,
https://github.com/ansible/ansible/pull/82678).
- paramiko connection plugin, configuration items in the global scope are being
deprecated and will be removed in favor or the existing same options in the
plugin itself. Users should not need to change anything (how to configure
them are the same) but plugin authors using the global constants should move
to using the plugin's get_option().
major_changes:
- urls.py - Removed support for Python 2
minor_changes:
- Add ``dump`` and ``passno`` mount information to facts component (https://github.com/ansible/ansible/issues/80478)
- Added MIRACLE LINUX 9.2 in RedHat OS Family.
- Interpreter Discovery - Remove hardcoded references to specific python interpreters
to use for certain distro versions, and modify logic for python3 to become
the default.
- Use Python's built-in ``functools.update_wrapper`` instead an inline copy
from Python 3.7.
- User can now set ansible.log to record higher verbosity than what is specified
for display via new configuration item LOG_VERBOSITY.
- '``DEFAULT_PRIVATE_ROLE_VARS`` is now overridden by explicit setting of ``public``
for ``include_roles`` and ``import_roles``.'
- '``ansible-galaxy role|collection init`` - accept ``--extra-vars`` to supplement/override
the variables ``ansible-galaxy`` injects for templating ``.j2`` files in the
skeleton.'
- '``import_role`` action now also gets a ``public`` option that controls variable
exports, default depending on ``DEFAULT_PRIVATE_ROLE_VARS`` (if using defaults
equates to ``public=True``).'
- added configuration item ``TARGET_LOG_INFO`` that allows the user/author to
add an information string to the log output on targets.
- ansible-doc - treat double newlines in documentation strings as paragraph
breaks. This is useful to create multi-paragraph notes in module/plugin documentation
(https://github.com/ansible/ansible/pull/82465).
- ansible-doc output has been revamped to make it more visually pleasing when
going to a terminal, also more concise, use -v to show extra information.
- ansible-galaxy - Started normalizing build directory with a trailing separator
when building collections, internally. (https://github.com/ansible/ansible/pull/81619).
- ansible-galaxy dependency resolution messages have changed the unexplained
'virtual' collection for the specific type ('scm', 'dir', etc) that is more
user friendly
- ansible-test - Add Alpine 3.19 container.
- ansible-test - Add Alpine 3.19 to remotes.
- ansible-test - Add Fedora 39 container.
- ansible-test - Add Fedora 39 remote.
- ansible-test - Add a work-around for permission denied errors when using ``pytest
>= 8`` on multi-user systems with an installed version of ``ansible-test``.
- ansible-test - Add support for RHEL 9.3 remotes.
- ansible-test - Added a macOS 14.3 remote VM.
- ansible-test - Bump the ``nios-test-container`` from version 2.0.0 to version
3.0.0.
- ansible-test - Containers and remotes managed by ansible-test will have their
Python ``EXTERNALLY-MANAGED`` marker (PEP668) removed. This provides backwards
compatibility for existing tests running in newer environments which mark
their Python as externally managed. A future version of ansible-test may change
this behavior, requiring tests to be adapted to such environments.
- ansible-test - Make Python 3.12 the default version used in the ``base`` and
``default`` containers.
- ansible-test - Remove Alpine 3(.18) container.
- ansible-test - Remove Alpine 3.18 from remotes.
- ansible-test - Remove Fedora 38 remote support.
- ansible-test - Remove Fedora 38 test container.
- ansible-test - Remove rhel/9.2 test remote
- ansible-test - Remove the FreeBSD 13.2 remote.
- ansible-test - Removed fallback to ``virtualenv`` when ``-m venv`` is non-functional.
- 'ansible-test - Removed test remotes: macos/13.2'
- ansible-test - Removed the ``no-basestring`` sanity test. The test is no longer
necessary now that Python 3 is required.
- ansible-test - Removed the ``no-dict-iteritems``, ``no-dict-iterkeys`` and
``no-dict-itervalues`` sanity tests. The tests are no longer necessary since
Python 3 is required.
- ansible-test - Removed the ``no-main-display`` sanity test. The unwanted pattern
is unlikely to occur, since the test has existed since Ansible 2.8.
- ansible-test - Removed the ``no-unicode-literals`` sanity test. The test is
unnecessary now that Python 3 is required and the ``unicode_literals`` feature
has no effect.
- ansible-test - Special handling for installation of ``cryptography`` has been
removed, as it is no longer necessary.
- ansible-test - The ``shellcheck`` sanity test no longer disables the ``SC2164``
check. In most cases, seeing this error means the script is missing ``set
-e``.
- ansible-test - The ``unidiomatic-typecheck`` rule has been enabled in the
``pylint`` sanity test.
- ansible-test - The ``unidiomatic-typecheck`` rule has been removed from the
``validate-modules`` sanity test.
- ansible-test - Update the base and default containers to use Ubuntu 22.04
for the base image. This also updates PowerShell to version 7.4.0 with .NET
8.0.0 and ShellCheck to version 0.8.0.
- ansible-test - Updated the CloudStack test container to version 1.7.0.
- ansible-test - Updated the distro test containers to version 6.3.0 to include
coverage 7.3.2 for Python 3.8+. The alpine3 container is now based on 3.18
instead of 3.17 and includes Python 3.11 instead of Python 3.10.
- ansible-test - Updated the distro test containers to version 7.1.0.
- ansible-test - When ansible-test installs requirements, it now instructs pip
to allow installs on externally managed environments as defined by PEP 668.
This only occurs in ephemeral environments managed by ansible-test, such as
containers, or when the `--requirements` option is used.
- ansible-test - When invoking ``sleep`` in containers during container setup,
the ``env`` command is used to avoid invoking the shell builtin, if present.
- ansible-test - document block name now included in error message for YAML
parsing errors (https://github.com/ansible/ansible/issues/82353).
- ansible-test - sanity test allows ``EXAMPLES`` to be multi-document YAML (https://github.com/ansible/ansible/issues/82353).
- ansible-test now has FreeBSD 13.3 and 14.0 support
- ansible.builtin.user - Remove user not found warning (https://github.com/ansible/ansible/issues/80267)
- apt_repository.py - use api.launchpad.net endpoint instead of launchpad.net/api
- async tasks can now also support check mode at the same time.
- async_status now supports check mode.
- constructed inventory plugin - Adding a note that only group_vars of explicit
groups are loaded (https://github.com/ansible/ansible/pull/82580).
- csvfile - add a keycol parameter to specify in which column to search.
- dnf - add the ``best`` option
- dnf5 - add the ``best`` option
- filter plugin - Add the count and mandatory_count parameters in the regex_replace
filter
- find - add a encoding parameter to specify which encoding of the files to
be searched.
- git module - gpg_allowlist name was added in 2.17 and we will eventually deprecate
the gpg_whitelist alias.
- import_role - allow subdirectories with ``_from`` options for parity with
``include_role`` (https://github.com/ansible/ansible/issues/82584).
- module argument spec - Allow module authors to include arbitrary additional
context in the argument spec, by making use of a new top level key called
``context``. This key should be a dict type. This allows for users to customize
what they place in the argument spec, without having to ignore sanity tests
that validate the schema.
- modules - Add the ability for an action plugin to call ``self._execute_module(*,
ignore_unknown_opts=True)`` to execute a module with options that may not
be supported for the version being called. This tells the module basic wrapper
to ignore validating the options provided match the arg spec.
- package action now has a configuration that overrides the detected package
manager, it is still overridden itself by the use option.
- py3compat - Remove ``ansible.utils.py3compat`` as it is no longer necessary
- removed the unused argument ``create_new_password`` from ``CLI.build_vault_ids``
(https://github.com/ansible/ansible/pull/82066).
- urls - Add support for TLS 1.3 post handshake certificate authentication -
https://github.com/ansible/ansible/issues/81782
- urls - reduce complexity of ``Request.open``
- user - accept yescrypt hash as user password
- validate-modules tests now correctly handles ``choices`` in dictionary format.
release_summary: '| Release Date: 2024-04-08
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__
'
removed_features:
- Remove deprecated APIs from ansible-docs (https://github.com/ansible/ansible/issues/81716).
- Remove deprecated JINJA2_NATIVE_WARNING environment variable (https://github.com/ansible/ansible/issues/81714)
- Remove deprecated ``scp_if_ssh`` from ssh connection plugin (https://github.com/ansible/ansible/issues/81715).
- Remove deprecated crypt support from ansible.utils.encrypt (https://github.com/ansible/ansible/issues/81717)
- With the removal of Python 2 support, the yum module and yum action plugin
are removed and redirected to ``dnf``.
security_fixes:
- ANSIBLE_NO_LOG - Address issue where ANSIBLE_NO_LOG was ignored (CVE-2024-0690)
- ansible-galaxy - Prevent roles from using symlinks to overwrite files outside
of the installation directory (CVE-2023-5115)
- templating - Address issues where internal templating can cause unsafe variables
to lose their unsafe designation (CVE-2023-5764)
codename: Gallows Pole
fragments:
- 2.17.0b1_summary.yaml
- 49809_apt_repository.yml
- 76727-chattr-fix-for-backups-of-symlinks.yml
- 77077_iptables.yml
- 77336-include_role-callbacks-stats.yml
- 78703_undefined.yml
- 79705-fix-ensure-path-to-collection-argument-doesnt-have-backslash.yml
- 79945-host_group_vars-improvements.yml
- 80110-repos-gpgcheck.yml
- 80267-ansible_builtin_user-remove-user-not-found-warning.yml
- 80478-extend-mount-info.yml
- 80561.yml
- 80590-dnf-skip_broken-unavailable-pkgs.yml
- 80882-Amazon-os-family-compat.yaml
- 80975-systemd-detect.yml
- 80995-include-all-var-files.yml
- 81053-templated-tags-inheritance.yml
- 81188_better_error.yml
- 81532-fix-nested-flush_handlers.yml
- 81584-daemonize-follow-up-fixes.yml
- 81606-ansible-galaxy-collection-pre-releases.yml
- 81628_galaxy_verify.yml
- 81638-blockinfile.yml
- 81659_varswithsources.yml
- 81666-handlers-run_once.yml
- 81699-zip-permission.yml
- 81713-distro.yml
- 81714-remove-deprecated-jinja2_native_warning.yml
- 81716-ansible-doc.yml
- 81717-remove-deprecated-crypt-support.yml
- 81722-handler-subdir-include_tasks.yml
- 81732-cloudstack-test-container-1.7.0.yml
- 81775-add-regex_replace-parameters.yml
- 81901-galaxy-requirements-format.yml
- 81931-locale-related-parsing-error-git.yml
- 81954-dnf-keepcache.yml
- 81978-launchpad-api-endpoint.yml
- 81995-enable_file_cache.yml
- 82027_find.yml
- 82066.yml
- 82175-fix-ansible-galaxy-role-import-rc.yml
- 82187-uri-handle-force.yml
- 82241-handler-include-tasks-from.yml
- 82353-ansible-sanity-examples.yml
- 82359_assemble_diff.yml
- 82363-multiple-handlers-with-recursive-notification.yml
- 82377-git-gpg-whitelist-allowlist.yml
- 82387-unquote-strings-from-ini-files.yml
- 82455-new-vmware-productname.yml
- 82461-dnf-provides.yml
- 82465-ansible-doc-paragraphs.yml
- 82496-add-alp-dolomite-suse-family.yaml
- 82574-ansible-test-ansible-doc-underscore.yml
- 82575-ansible-test-validate-modules-underscore.yml
- 82580_constructed.yml
- 82606-template-python-syntax-error.yml
- 82611_fix_alignment_apt_clean_with_ansible_apt_clean.yml
- 82616-dnf-best-nobest.yml
- 82655-fix-ansible-loop-index-var-in-includedtasks.yml
- 82675-fix-unsafe-templating-leading-to-type-error.yml
- 82678-role-entrypoint-attributes.yml
- 82683-ansible-fact_cache-permissions-changed-after-ansible-coreupdate.yml
- 82708-unsafe-plugin-name-error.yml
- 82878-fetch-dest-is-dir.yml
- 82954-fix-older-connection-plugins.yml
- a-g-install-version-None.yml
- ansible-galaxy-init-extra-vars.yml
- ansible-galaxy-role-install-symlink.yml
- ansible-test-added-fedora-39.yml
- ansible-test-added-macos-14.3.yml
- ansible-test-alpine-libexpat.yml
- ansible-test-cgroup-split.yml
- ansible-test-container-sleep.yml
- ansible-test-coverage-update.yml
- ansible-test-cryptography.yml
- ansible-test-default-containers.yml
- ansible-test-distro-containers.yml
- ansible-test-docker-forwards.yml
- ansible-test-externally-managed-python.yml
- ansible-test-nios-container.yml
- ansible-test-pep-668.yml
- ansible-test-pylint-update.yml
- ansible-test-pytest-8.yml
- ansible-test-python-3.12-compat.yml
- ansible-test-python-default.yml
- ansible-test-remove-freebsd-13.2.yml
- ansible-test-remove-rhel-9_2-remote.yml
- ansible-test-rhel-9.3.yml
- ansible-test-rmv-fedora-38.yml
- ansible-test-sanity-no-basestring.yml
- ansible-test-sanity-no-dict.yml
- ansible-test-sanity-no-main-display.yml
- ansible-test-sanity-unicode-literals.yml
- ansible-test-shellcheck-exclude.yml
- ansible-test-unidiomatic-type-check.yml
- ansible-test-validate-modules-non-python.yml
- ansible-test-venv.yml
- ansible_test_alpine_3.19.yml
- ansible_test_fbsd_add.yml
- ansible_test_rmv_alpine_318.yml
- ansible_test_rmv_macos_132.yml
- any_errors_fatal-fixes.yml
- apt_install.yml
- apt_recommends.yml
- argument-spec-context.yml
- async-task-check-mode.yml
- async_status_check_mode.yml
- atomic-move-fix-extended-attrs.yml
- check_arguments.yml
- clear-distro-interp-map.yml
- config_set_option_fix.yml
- config_validate_updates.yml
- copy_keep_suffix_temp.yml
- csvfile-keycol.yml
- cve-2023-5115.yml
- cve-2023-5764.yml
- cve-2024-0690.yml
- deb822_repo_idem.yml
- debconf_multiselect.yml
- dedupe_config_init.yml
- delegate_to_invalid.yml
- deprecate-v2-galaxy-api.yml
- distlib-dataclass-annotation.yml
- dnf-installed-checks-api.yml
- dnf5-from-rpm-allow_downgrade.yml
- dwim_is_role_fix.yml
- find-encoding.yml
- first_found_fixes.yml
- fix-allow-duplicates.yml
- fix-ansible-galaxy-info-no-role-found.yml
- fix-build-files-manifest-walk.yml
- fix-default-ansible-galaxy-role-import-name.yml
- fix-dnf-install-missing-url.yml
- fix-expect-indefinite-timeout.yml
- fix-import_role-_from-options.yml
- fix-reboot-plugin.yml
- fix-role-name-handler-prefix-listen.yml
- fix-runtime-metadata-modules-action_plugin.yml
- fix-vars-plugins-in-roles.yml
- functools-update-wrapper.yml
- galaxy_dep_res_msgs.yml
- get_bin_path_required_parameter.yml
- import_role_goes_public.yml
- improve-tombstone-error.yml
- internal_static_vars.yml
- interpreter_discovery.yml
- inv_available_hosts_to_frozenset.yml
- iptables_match_set_flag.yml
- j2_load_fix.yml
- known_hosts_cert-authority_keys.yml
- log_id.yml
- log_verbosity.yml
- lookups_updated.yml
- miracle_linux_distribution_support.yml
- mod_args.yml
- module-ignore-unknown-options.yml
- module_utils-basic-deprecations.yml
- no_log_booly.yml
- paramiko_globals.yml
- pc_fixes.yml
- pkg_mgr_peek.yml
- ppa_https.yml
- prettydoc.yml
- pull_file_secrets.yml
- pull_unfrack_dest.yml
- py-tmpl-hardening.yml
- reboot_timeout_fix.yml
- request-open-reduce-complexity.yml
- restore_role_param_precedence.yml
- rm-compat-environ.yml
- rm-obsolete-url-role-template.yml
- role_fixes.yml
- scp_if_ssh.yml
- ssh_connection_test.yml
- syslog_exception.yml
- systemd_service_note.yml
- thread_counts.yml
- unarchive.yml
- unarchive_fix.yml
- unsafe-fixes-2.yml
- unsafe-intern.yml
- uri_action_cmode.yml
- url_credentials_decode.yml
- urls-no-py2.yml
- urls-tls13-post-handshake-auth.yml
- user-accept-yescrypt-hash.yml
- v2.17.0-initial-commit.yaml
- wait_for_mmap.yml
- winrm-send-input.yml
- winrm-task-timeout.yml
- winrm-timeout.yml
- yum-removal.yml
release_date: '2024-04-08'
2.17.0rc1:
changes:
bugfixes:
- Fix handlers not being executed in lockstep using the linear strategy in some
cases (https://github.com/ansible/ansible/issues/82307)
- ansible-config will now properly template defaults before dumping them.
- ansible_managed restored it's 'templatability' by ensuring the possible injection
routes are cut off earlier in the process.
- dnf5 - replace removed API calls
- facts - add a generic detection for VMware in product name.
release_summary: '| Release Date: 2024-04-29
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__
'
removed_features:
- Removed Python 2.7 and Python 3.6 as a supported remote version. Python 3.7+
is now required for target execution.
codename: Gallows Pole
fragments:
- 2.17.0rc1_summary.yaml
- 82307-handlers-lockstep-linear-fix.yml
- ansible_managed_restore.yml
- config_init_fix.yml
- dnf5-api-breaks.yml
- python-support.yml
- vmware_facts.yml
release_date: '2024-04-29'
2.17.0rc2:
changes:
bugfixes:
- Add a version ceiling constraint for pypsrp to avoid potential breaking changes
in the 1.0.0 release.
- ansible-doc - fixed "inicates" typo in output
- ansible-doc - format top-level descriptions with multiple paragraphs as multiple
paragraphs, instead of concatenating them (https://github.com/ansible/ansible/pull/83155).
- ensure we have logger before we log when we have increased verbosity.
- uri - update the documentation for follow_redirects.
release_summary: '| Release Date: 2024-05-13
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__
'
codename: Gallows Pole
fragments:
- 2.17.0rc2_summary.yaml
- 83155-ansible-doc-paragraphs.yml
- ansible-doc-inicate.yml
- fix_log_verbosity.yml
- psrp-version-req.yml
- uri_follow_redirect_bool.yml
release_date: '2024-05-13'
2.17.1:
changes:
minor_changes:
- ansible-test - Update ``pypi-test-container`` to version 3.1.0.
release_summary: '| Release Date: 2024-06-17
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__
'
codename: Gallows Pole
fragments:
- 2.17.1_summary.yaml
- ansible-test-pypi-test-container-update.yml
release_date: '2024-06-17'
2.17.1rc1:
changes:
bugfixes:
- Fix rapid memory usage growth when notifying handlers using the ``listen``
keyword (https://github.com/ansible/ansible/issues/83392)
- Fix the task attribute ``resolved_action`` to show the FQCN instead of ``None``
when ``action`` or ``local_action`` is used in the playbook.
- Fix using ``module_defaults`` with ``local_action``/``action`` (https://github.com/ansible/ansible/issues/81905).
- fixed unit test test_borken_cowsay to address mock not been properly applied
when existing unix system already have cowsay installed.
- powershell - Implement more robust deletion mechanism for C# code compilation
temporary files. This should avoid scenarios where the underlying temporary
directory may be temporarily locked by antivirus tools or other IO problems.
A failure to delete one of these temporary directories will result in a warning
rather than an outright failure.
- shell plugin - properly quote all needed components of shell commands (https://github.com/ansible/ansible/issues/82535)
release_summary: '| Release Date: 2024-06-10
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__
'
codename: Gallows Pole
fragments:
- 2.17.1rc1_summary.yaml
- 82535-properly-quote-shell.yml
- 83327.yml
- 83392-fix-memory-issues-handlers.yml
- PowerShell-AddType-temp.yml
- correct-callback-fqcn-old-style-action-invocation.yml
release_date: '2024-06-10'
2.17.2:
changes:
release_summary: '| Release Date: 2024-07-15
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__
'
codename: Gallows Pole
fragments:
- 2.17.2_summary.yaml
release_date: '2024-07-15'
2.17.2rc1:
changes:
bugfixes:
- Fix a traceback when an environment variable contains certain special characters
(https://github.com/ansible/ansible/issues/83498)
- dnf, dnf5 - fix for installing a set of packages by specifying them using
a wildcard character (https://github.com/ansible/ansible/issues/83373)
- linear strategy now provides a properly templated task name to the v2_runner_on_started
callback event.
- replace - Updated before/after example (https://github.com/ansible/ansible/issues/83390).
- templating hostvars under native jinja will not cause serialization errors
anymore.
release_summary: '| Release Date: 2024-07-08
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__
'
codename: Gallows Pole
fragments:
- 2.17.2rc1_summary.yaml
- 83373-dnf5-wildcard.yml
- 83498-command-tb-env.yml
- hostvars_fix.yml
- linear_started_name.yml
- replace_regex.yml
release_date: '2024-07-08'
2.17.2rc2:
changes:
bugfixes:
- dnf - reverted incomplete fix from 2.17.2rc1 (https://github.com/ansible/ansible/pull/83504)
- package_facts - ignore warnings sent by apk on stderr (https://github.com/ansible/ansible/issues/83501).
release_summary: '| Release Date: 2024-07-09
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__
'
codename: Gallows Pole
fragments:
- 2.17.2rc2_summary.yaml
- dnf-revert.yaml
- package_facts_apk.yml
release_date: '2024-07-09'
2.17.3:
changes:
release_summary: '| Release Date: 2024-08-12
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__
'
codename: Gallows Pole
fragments:
- 2.17.3_summary.yaml
release_date: '2024-08-12'
2.17.3rc1:
changes:
bugfixes:
- Warning now includes filename and line number of variable when specifying
a list of dictionaries for vars (https://github.com/ansible/ansible/issues/82528).
- config, restored the ability to set module compression via a variable
- debconf - fix normalization of value representation for boolean vtypes in
new packages (https://github.com/ansible/ansible/issues/83594)
- 'linear strategy: fix handlers included via ``include_tasks`` handler to be
executed in lockstep (https://github.com/ansible/ansible/issues/83019)'
minor_changes:
- ansible-test - Improve the error message shown when an unknown ``--remote``
or ``--docker`` option is given.
- ansible-test - Removed the ``vyos/1.1.8`` network remote as it is no longer
functional.
release_summary: '| Release Date: 2024-08-05
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__
'
codename: Gallows Pole
fragments:
- 2.17.3rc1_summary.yaml
- 82528summary.yml
- 83019-linear-handlers-lockstep-fix.yml
- 83601-debconf-normalize-bools.yml
- ansible-test-error-message-improvement.yml
- ansible-test-vyos.yml
- mc_fix.yml
release_date: '2024-08-05'
2.17.4:
changes:
release_summary: '| Release Date: 2024-09-09
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__
'
codename: Gallows Pole
fragments:
- 2.17.4_summary.yaml
release_date: '2024-09-09'
2.17.4rc1:
changes:
bugfixes:
- Fix ``SemanticVersion.parse()`` to store the version string so that ``__repr__``
reports it instead of ``None`` (https://github.com/ansible/ansible/pull/83831).
- Fix an issue where registered variable was not available for templating in
``loop_control.label`` on skipped looped tasks (https://github.com/ansible/ansible/issues/83619)
- Fix for ``meta`` tasks breaking host/fork affinity with ``host_pinned`` strategy
(https://github.com/ansible/ansible/issues/83294)
- Fix using the current task's directory for looking up relative paths within
roles (https://github.com/ansible/ansible/issues/82695).
- atomic_move - fix using the setgid bit on the parent directory when creating
files (https://github.com/ansible/ansible/issues/46742, https://github.com/ansible/ansible/issues/67177).
- connection plugins using the 'extras' option feature would need variables
to match the plugin's loaded name, sometimes requiring fqcn, which is not
the same as the documented/declared/expected variables. Now we fall back to
the 'basename' of the fqcn, but plugin authors can still set the expected
value directly.
- csvfile lookup - give an error when no search term is provided using modern
config syntax (https://github.com/ansible/ansible/issues/83689).
- include_tasks - Display location when attempting to load a task list where
``include_*`` did not specify any value - https://github.com/ansible/ansible/issues/83874
- powershell - Improve CLIXML decoding to decode all control characters and
unicode characters that are encoded as surrogate pairs.
- psrp - Fix bug when attempting to fetch a file path that contains special
glob characters like ``[]``
- runtime-metadata sanity test - do not crash on deprecations if ``galaxy.yml``
contains an empty ``version`` field (https://github.com/ansible/ansible/pull/83831).
- ssh - Fix bug when attempting to fetch a file path with characters that should
be quoted when using the ``piped`` transfer method
release_summary: '| Release Date: 2024-09-03
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__
'
codename: Gallows Pole
fragments:
- 2.17.4rc1_summary.yaml
- 46742-atomic_move-fix-setgid.yml
- 83294-meta-host_pinned-affinity.yml
- 83619-loop-label-register.yml
- 83831-runtime-metadata-fix.yml
- 83874-include-parse-error-location.yml
- dwim_is_role_fix_task_relative.yml
- extras_fix.yml
- fetch-filename.yml
- fix-inconsistent-csvfile-missing-search-error.yml
- powershell-clixml.yml
release_date: '2024-09-03'

View File

@ -1,22 +0,0 @@
---
title: ansible-core
release_tag_re: '(v(?:[\d.ab\-]|rc)+)'
pre_release_tag_re: '(?P<pre_release>(?:[ab]|rc)+\d*)$'
changes_file: changelog.yaml
changes_format: combined
keep_fragments: true
always_refresh: true
ignore_other_fragment_extensions: true
mention_ancestor: false
notesdir: fragments
prelude_section_name: release_summary
new_plugins_after_name: removed_features
sections:
- ['major_changes', 'Major Changes']
- ['minor_changes', 'Minor Changes']
- ['breaking_changes', 'Breaking Changes / Porting Guide']
- ['deprecated_features', 'Deprecated Features']
- ['removed_features', 'Removed Features (previously deprecated)']
- ['security_fixes', 'Security Fixes']
- ['bugfixes', 'Bugfixes']
- ['known_issues', 'Known Issues']

View File

@ -1,3 +0,0 @@
release_summary: |
| Release Date: 2024-05-20
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__

View File

@ -1,3 +0,0 @@
release_summary: |
| Release Date: 2024-04-08
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__

View File

@ -1,3 +0,0 @@
release_summary: |
| Release Date: 2024-04-29
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__

View File

@ -1,3 +0,0 @@
release_summary: |
| Release Date: 2024-05-13
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__

View File

@ -1,3 +0,0 @@
release_summary: |
| Release Date: 2024-06-17
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__

View File

@ -1,3 +0,0 @@
release_summary: |
| Release Date: 2024-06-10
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__

View File

@ -1,3 +0,0 @@
release_summary: |
| Release Date: 2024-07-15
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__

View File

@ -1,3 +0,0 @@
release_summary: |
| Release Date: 2024-07-08
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__

View File

@ -1,3 +0,0 @@
release_summary: |
| Release Date: 2024-07-09
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__

View File

@ -1,3 +0,0 @@
release_summary: |
| Release Date: 2024-08-12
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__

View File

@ -1,3 +0,0 @@
release_summary: |
| Release Date: 2024-08-05
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__

View File

@ -1,3 +0,0 @@
release_summary: |
| Release Date: 2024-09-09
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__

View File

@ -1,3 +0,0 @@
release_summary: |
| Release Date: 2024-09-03
| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__

View File

@ -1,2 +0,0 @@
bugfixes:
- atomic_move - fix using the setgid bit on the parent directory when creating files (https://github.com/ansible/ansible/issues/46742, https://github.com/ansible/ansible/issues/67177).

View File

@ -1,3 +0,0 @@
---
bugfixes:
- apt_repository - do not modify repo files if the file is a symlink (https://github.com/ansible/ansible/issues/49809).

View File

@ -1,2 +0,0 @@
bugfixes:
- check if there are attributes to set before attempting to set them (https://github.com/ansible/ansible/issues/76727)

View File

@ -1,3 +0,0 @@
---
bugfixes:
- iptables - set jump to DSCP when set_dscp_mark or set_dscp_mark_class is set (https://github.com/ansible/ansible/issues/77077).

View File

@ -1,2 +0,0 @@
bugfixes:
- "``include_role`` - properly execute ``v2_playbook_on_include`` and ``v2_runner_on_failed`` callbacks as well as increase ``ok`` and ``failed`` stats in the play recap, when appropriate (https://github.com/ansible/ansible/issues/77336)"

View File

@ -1,3 +0,0 @@
---
bugfixes:
- Do not print undefined error message twice (https://github.com/ansible/ansible/issues/78703).

Some files were not shown because too many files have changed in this diff Show More