mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-04-28 17:36:49 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4aeb322bb | ||
|
|
165da11731 |
@@ -4,6 +4,6 @@ GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://w
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
-->
|
||||
|
||||
### Description
|
||||
## Azure Pipelines Configuration
|
||||
|
||||
Merge Request test description
|
||||
Please see the [Documentation](https://github.com/ansible/community/wiki/Testing:-Azure-Pipelines) for more information.
|
||||
488
.azure-pipelines/azure-pipelines.yml
Normal file
488
.azure-pipelines/azure-pipelines.yml
Normal file
@@ -0,0 +1,488 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
trigger:
|
||||
batch: true
|
||||
branches:
|
||||
include:
|
||||
- main
|
||||
- stable-*
|
||||
|
||||
pr:
|
||||
autoCancel: true
|
||||
branches:
|
||||
include:
|
||||
- main
|
||||
- stable-*
|
||||
|
||||
schedules:
|
||||
- cron: 0 8 * * *
|
||||
displayName: Nightly (main)
|
||||
always: true
|
||||
branches:
|
||||
include:
|
||||
- main
|
||||
- cron: 0 10 * * *
|
||||
displayName: Nightly (active stable branches)
|
||||
always: true
|
||||
branches:
|
||||
include:
|
||||
- stable-7
|
||||
- stable-6
|
||||
- cron: 0 11 * * 0
|
||||
displayName: Weekly (old stable branches)
|
||||
always: true
|
||||
branches:
|
||||
include:
|
||||
- stable-5
|
||||
|
||||
variables:
|
||||
- name: checkoutPath
|
||||
value: ansible_collections/community/general
|
||||
- name: coverageBranches
|
||||
value: main
|
||||
- name: pipelinesCoverage
|
||||
value: coverage
|
||||
- name: entryPoint
|
||||
value: tests/utils/shippable/shippable.sh
|
||||
- name: fetchDepth
|
||||
value: 0
|
||||
|
||||
resources:
|
||||
containers:
|
||||
- container: default
|
||||
image: quay.io/ansible/azure-pipelines-test-container:3.0.0
|
||||
|
||||
pool: Standard
|
||||
|
||||
stages:
|
||||
### Sanity
|
||||
- stage: Sanity_devel
|
||||
displayName: Sanity devel
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Test {0}
|
||||
testFormat: devel/sanity/{0}
|
||||
targets:
|
||||
- test: 1
|
||||
- test: 2
|
||||
- test: 3
|
||||
- test: 4
|
||||
- test: extra
|
||||
- stage: Sanity_2_15
|
||||
displayName: Sanity 2.15
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Test {0}
|
||||
testFormat: 2.15/sanity/{0}
|
||||
targets:
|
||||
- test: 1
|
||||
- test: 2
|
||||
- test: 3
|
||||
- test: 4
|
||||
- stage: Sanity_2_14
|
||||
displayName: Sanity 2.14
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Test {0}
|
||||
testFormat: 2.14/sanity/{0}
|
||||
targets:
|
||||
- test: 1
|
||||
- test: 2
|
||||
- test: 3
|
||||
- test: 4
|
||||
- stage: Sanity_2_13
|
||||
displayName: Sanity 2.13
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Test {0}
|
||||
testFormat: 2.13/sanity/{0}
|
||||
targets:
|
||||
- test: 1
|
||||
- test: 2
|
||||
- test: 3
|
||||
- test: 4
|
||||
- stage: Sanity_2_12
|
||||
displayName: Sanity 2.12
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Test {0}
|
||||
testFormat: 2.12/sanity/{0}
|
||||
targets:
|
||||
- test: 1
|
||||
- test: 2
|
||||
- test: 3
|
||||
- test: 4
|
||||
### Units
|
||||
- stage: Units_devel
|
||||
displayName: Units devel
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: devel/units/{0}/1
|
||||
targets:
|
||||
- test: 2.7
|
||||
- test: 3.5
|
||||
- test: 3.6
|
||||
- test: 3.7
|
||||
- test: 3.8
|
||||
- test: 3.9
|
||||
- test: '3.10'
|
||||
- test: '3.11'
|
||||
- stage: Units_2_15
|
||||
displayName: Units 2.15
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: 2.15/units/{0}/1
|
||||
targets:
|
||||
- test: "3.10"
|
||||
- stage: Units_2_14
|
||||
displayName: Units 2.14
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: 2.14/units/{0}/1
|
||||
targets:
|
||||
- test: 3.9
|
||||
- stage: Units_2_13
|
||||
displayName: Units 2.13
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: 2.13/units/{0}/1
|
||||
targets:
|
||||
- test: 2.7
|
||||
- test: 3.8
|
||||
- stage: Units_2_12
|
||||
displayName: Units 2.12
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: 2.12/units/{0}/1
|
||||
targets:
|
||||
- test: 2.6
|
||||
- test: 3.8
|
||||
|
||||
## Remote
|
||||
- stage: Remote_devel_extra_vms
|
||||
displayName: Remote devel extra VMs
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: devel/{0}
|
||||
targets:
|
||||
- name: Alpine 3.17
|
||||
test: alpine/3.17
|
||||
# - name: Fedora 37
|
||||
# test: fedora/37
|
||||
# - name: Ubuntu 20.04
|
||||
# test: ubuntu/20.04
|
||||
- name: Ubuntu 22.04
|
||||
test: ubuntu/22.04
|
||||
groups:
|
||||
- vm
|
||||
- stage: Remote_devel
|
||||
displayName: Remote devel
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: devel/{0}
|
||||
targets:
|
||||
- name: macOS 13.2
|
||||
test: macos/13.2
|
||||
- name: RHEL 9.1
|
||||
test: rhel/9.1
|
||||
- name: FreeBSD 13.2
|
||||
test: freebsd/13.2
|
||||
- name: FreeBSD 12.4
|
||||
test: freebsd/12.4
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- stage: Remote_2_15
|
||||
displayName: Remote 2.15
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.15/{0}
|
||||
targets:
|
||||
- name: RHEL 7.9
|
||||
test: rhel/7.9
|
||||
- name: FreeBSD 13.1
|
||||
test: freebsd/13.1
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- stage: Remote_2_14
|
||||
displayName: Remote 2.14
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.14/{0}
|
||||
targets:
|
||||
- name: RHEL 9.0
|
||||
test: rhel/9.0
|
||||
- name: FreeBSD 12.3
|
||||
test: freebsd/12.3
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- stage: Remote_2_13
|
||||
displayName: Remote 2.13
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.13/{0}
|
||||
targets:
|
||||
- name: macOS 12.0
|
||||
test: macos/12.0
|
||||
- name: RHEL 8.5
|
||||
test: rhel/8.5
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- stage: Remote_2_12
|
||||
displayName: Remote 2.12
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.12/{0}
|
||||
targets:
|
||||
- name: macOS 11.1
|
||||
test: macos/11.1
|
||||
- name: RHEL 8.4
|
||||
test: rhel/8.4
|
||||
- name: FreeBSD 13.0
|
||||
test: freebsd/13.0
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
|
||||
### Docker
|
||||
- stage: Docker_devel
|
||||
displayName: Docker devel
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: devel/linux/{0}
|
||||
targets:
|
||||
- name: Fedora 37
|
||||
test: fedora37
|
||||
- name: openSUSE 15
|
||||
test: opensuse15
|
||||
- name: Ubuntu 20.04
|
||||
test: ubuntu2004
|
||||
- name: Ubuntu 22.04
|
||||
test: ubuntu2204
|
||||
- name: Alpine 3
|
||||
test: alpine3
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- stage: Docker_2_15
|
||||
displayName: Docker 2.15
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.15/linux/{0}
|
||||
targets:
|
||||
- name: CentOS 7
|
||||
test: centos7
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- stage: Docker_2_14
|
||||
displayName: Docker 2.14
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.14/linux/{0}
|
||||
targets:
|
||||
- name: Fedora 36
|
||||
test: fedora36
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- stage: Docker_2_13
|
||||
displayName: Docker 2.13
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.13/linux/{0}
|
||||
targets:
|
||||
- name: Fedora 35
|
||||
test: fedora35
|
||||
- name: openSUSE 15 py2
|
||||
test: opensuse15py2
|
||||
- name: Alpine 3
|
||||
test: alpine3
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- stage: Docker_2_12
|
||||
displayName: Docker 2.12
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: 2.12/linux/{0}
|
||||
targets:
|
||||
- name: CentOS 6
|
||||
test: centos6
|
||||
- name: Fedora 34
|
||||
test: fedora34
|
||||
- name: Ubuntu 18.04
|
||||
test: ubuntu1804
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
|
||||
### Community Docker
|
||||
- stage: Docker_community_devel
|
||||
displayName: Docker (community images) devel
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
testFormat: devel/linux-community/{0}
|
||||
targets:
|
||||
- name: Debian Bullseye
|
||||
test: debian-bullseye/3.9
|
||||
- name: ArchLinux
|
||||
test: archlinux/3.11
|
||||
- name: CentOS Stream 8
|
||||
test: centos-stream8/3.9
|
||||
groups:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
|
||||
### Generic
|
||||
- stage: Generic_devel
|
||||
displayName: Generic devel
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: devel/generic/{0}/1
|
||||
targets:
|
||||
- test: 2.7
|
||||
- test: '3.11'
|
||||
- stage: Generic_2_15
|
||||
displayName: Generic 2.15
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: 2.15/generic/{0}/1
|
||||
targets:
|
||||
- test: 3.9
|
||||
- stage: Generic_2_14
|
||||
displayName: Generic 2.14
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: 2.14/generic/{0}/1
|
||||
targets:
|
||||
- test: '3.10'
|
||||
- stage: Generic_2_13
|
||||
displayName: Generic 2.13
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: 2.13/generic/{0}/1
|
||||
targets:
|
||||
- test: 3.9
|
||||
- stage: Generic_2_12
|
||||
displayName: Generic 2.12
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/matrix.yml
|
||||
parameters:
|
||||
nameFormat: Python {0}
|
||||
testFormat: 2.12/generic/{0}/1
|
||||
targets:
|
||||
- test: 3.8
|
||||
|
||||
- stage: Summary
|
||||
condition: succeededOrFailed()
|
||||
dependsOn:
|
||||
- Sanity_devel
|
||||
- Sanity_2_12
|
||||
- Sanity_2_13
|
||||
- Sanity_2_14
|
||||
- Sanity_2_15
|
||||
- Units_devel
|
||||
- Units_2_12
|
||||
- Units_2_13
|
||||
- Units_2_14
|
||||
- Units_2_15
|
||||
- Remote_devel_extra_vms
|
||||
- Remote_devel
|
||||
- Remote_2_12
|
||||
- Remote_2_13
|
||||
- Remote_2_14
|
||||
- Remote_2_15
|
||||
- Docker_devel
|
||||
- Docker_2_12
|
||||
- Docker_2_13
|
||||
- Docker_2_14
|
||||
- Docker_2_15
|
||||
- Docker_community_devel
|
||||
# Right now all generic tests are disabled. Uncomment when at least one of them is re-enabled.
|
||||
# - Generic_devel
|
||||
# - Generic_2_12
|
||||
# - Generic_2_13
|
||||
# - Generic_2_14
|
||||
# - Generic_2_15
|
||||
jobs:
|
||||
- template: templates/coverage.yml
|
||||
24
.azure-pipelines/scripts/aggregate-coverage.sh
Executable file
24
.azure-pipelines/scripts/aggregate-coverage.sh
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Aggregate code coverage results for later processing.
|
||||
|
||||
set -o pipefail -eu
|
||||
|
||||
agent_temp_directory="$1"
|
||||
|
||||
PATH="${PWD}/bin:${PATH}"
|
||||
|
||||
mkdir "${agent_temp_directory}/coverage/"
|
||||
|
||||
options=(--venv --venv-system-site-packages --color -v)
|
||||
|
||||
ansible-test coverage combine --group-by command --export "${agent_temp_directory}/coverage/" "${options[@]}"
|
||||
|
||||
if ansible-test coverage analyze targets generate --help >/dev/null 2>&1; then
|
||||
# Only analyze coverage if the installed version of ansible-test supports it.
|
||||
# Doing so allows this script to work unmodified for multiple Ansible versions.
|
||||
ansible-test coverage analyze targets generate "${agent_temp_directory}/coverage/coverage-analyze-targets.json" "${options[@]}"
|
||||
fi
|
||||
64
.azure-pipelines/scripts/combine-coverage.py
Executable file
64
.azure-pipelines/scripts/combine-coverage.py
Executable file
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
"""
|
||||
Combine coverage data from multiple jobs, keeping the data only from the most recent attempt from each job.
|
||||
Coverage artifacts must be named using the format: "Coverage $(System.JobAttempt) {StableUniqueNameForEachJob}"
|
||||
The recommended coverage artifact name format is: Coverage $(System.JobAttempt) $(System.StageDisplayName) $(System.JobDisplayName)
|
||||
Keep in mind that Azure Pipelines does not enforce unique job display names (only names).
|
||||
It is up to pipeline authors to avoid name collisions when deviating from the recommended format.
|
||||
"""
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
"""Main program entry point."""
|
||||
source_directory = sys.argv[1]
|
||||
|
||||
if '/ansible_collections/' in os.getcwd():
|
||||
output_path = "tests/output"
|
||||
else:
|
||||
output_path = "test/results"
|
||||
|
||||
destination_directory = os.path.join(output_path, 'coverage')
|
||||
|
||||
if not os.path.exists(destination_directory):
|
||||
os.makedirs(destination_directory)
|
||||
|
||||
jobs = {}
|
||||
count = 0
|
||||
|
||||
for name in os.listdir(source_directory):
|
||||
match = re.search('^Coverage (?P<attempt>[0-9]+) (?P<label>.+)$', name)
|
||||
label = match.group('label')
|
||||
attempt = int(match.group('attempt'))
|
||||
jobs[label] = max(attempt, jobs.get(label, 0))
|
||||
|
||||
for label, attempt in jobs.items():
|
||||
name = 'Coverage {attempt} {label}'.format(label=label, attempt=attempt)
|
||||
source = os.path.join(source_directory, name)
|
||||
source_files = os.listdir(source)
|
||||
|
||||
for source_file in source_files:
|
||||
source_path = os.path.join(source, source_file)
|
||||
destination_path = os.path.join(destination_directory, source_file + '.' + label)
|
||||
print('"%s" -> "%s"' % (source_path, destination_path))
|
||||
shutil.copyfile(source_path, destination_path)
|
||||
count += 1
|
||||
|
||||
print('Coverage file count: %d' % count)
|
||||
print('##vso[task.setVariable variable=coverageFileCount]%d' % count)
|
||||
print('##vso[task.setVariable variable=outputPath]%s' % output_path)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
28
.azure-pipelines/scripts/process-results.sh
Executable file
28
.azure-pipelines/scripts/process-results.sh
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Check the test results and set variables for use in later steps.
|
||||
|
||||
set -o pipefail -eu
|
||||
|
||||
if [[ "$PWD" =~ /ansible_collections/ ]]; then
|
||||
output_path="tests/output"
|
||||
else
|
||||
output_path="test/results"
|
||||
fi
|
||||
|
||||
echo "##vso[task.setVariable variable=outputPath]${output_path}"
|
||||
|
||||
if compgen -G "${output_path}"'/junit/*.xml' > /dev/null; then
|
||||
echo "##vso[task.setVariable variable=haveTestResults]true"
|
||||
fi
|
||||
|
||||
if compgen -G "${output_path}"'/bot/ansible-test-*' > /dev/null; then
|
||||
echo "##vso[task.setVariable variable=haveBotResults]true"
|
||||
fi
|
||||
|
||||
if compgen -G "${output_path}"'/coverage/*' > /dev/null; then
|
||||
echo "##vso[task.setVariable variable=haveCoverageData]true"
|
||||
fi
|
||||
105
.azure-pipelines/scripts/publish-codecov.py
Executable file
105
.azure-pipelines/scripts/publish-codecov.py
Executable file
@@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
"""
|
||||
Upload code coverage reports to codecov.io.
|
||||
Multiple coverage files from multiple languages are accepted and aggregated after upload.
|
||||
Python coverage, as well as PowerShell and Python stubs can all be uploaded.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import dataclasses
|
||||
import pathlib
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import typing as t
|
||||
import urllib.request
|
||||
|
||||
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class CoverageFile:
|
||||
name: str
|
||||
path: pathlib.Path
|
||||
flags: t.List[str]
|
||||
|
||||
|
||||
@dataclasses.dataclass(frozen=True)
|
||||
class Args:
|
||||
dry_run: bool
|
||||
path: pathlib.Path
|
||||
|
||||
|
||||
def parse_args() -> Args:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-n', '--dry-run', action='store_true')
|
||||
parser.add_argument('path', type=pathlib.Path)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Store arguments in a typed dataclass
|
||||
fields = dataclasses.fields(Args)
|
||||
kwargs = {field.name: getattr(args, field.name) for field in fields}
|
||||
|
||||
return Args(**kwargs)
|
||||
|
||||
|
||||
def process_files(directory: pathlib.Path) -> t.Tuple[CoverageFile, ...]:
|
||||
processed = []
|
||||
for file in directory.joinpath('reports').glob('coverage*.xml'):
|
||||
name = file.stem.replace('coverage=', '')
|
||||
|
||||
# Get flags from name
|
||||
flags = name.replace('-powershell', '').split('=') # Drop '-powershell' suffix
|
||||
flags = [flag if not flag.startswith('stub') else flag.split('-')[0] for flag in flags] # Remove "-01" from stub files
|
||||
|
||||
processed.append(CoverageFile(name, file, flags))
|
||||
|
||||
return tuple(processed)
|
||||
|
||||
|
||||
def upload_files(codecov_bin: pathlib.Path, files: t.Tuple[CoverageFile, ...], dry_run: bool = False) -> None:
|
||||
for file in files:
|
||||
cmd = [
|
||||
str(codecov_bin),
|
||||
'--name', file.name,
|
||||
'--file', str(file.path),
|
||||
]
|
||||
for flag in file.flags:
|
||||
cmd.extend(['--flags', flag])
|
||||
|
||||
if dry_run:
|
||||
print(f'DRY-RUN: Would run command: {cmd}')
|
||||
continue
|
||||
|
||||
subprocess.run(cmd, check=True)
|
||||
|
||||
|
||||
def download_file(url: str, dest: pathlib.Path, flags: int, dry_run: bool = False) -> None:
|
||||
if dry_run:
|
||||
print(f'DRY-RUN: Would download {url} to {dest} and set mode to {flags:o}')
|
||||
return
|
||||
|
||||
with urllib.request.urlopen(url) as resp:
|
||||
with dest.open('w+b') as f:
|
||||
# Read data in chunks rather than all at once
|
||||
shutil.copyfileobj(resp, f, 64 * 1024)
|
||||
|
||||
dest.chmod(flags)
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
url = 'https://ansible-ci-files.s3.amazonaws.com/codecov/linux/codecov'
|
||||
with tempfile.TemporaryDirectory(prefix='codecov-') as tmpdir:
|
||||
codecov_bin = pathlib.Path(tmpdir) / 'codecov'
|
||||
download_file(url, codecov_bin, 0o755, args.dry_run)
|
||||
|
||||
files = process_files(args.path)
|
||||
upload_files(codecov_bin, files, args.dry_run)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
19
.azure-pipelines/scripts/report-coverage.sh
Executable file
19
.azure-pipelines/scripts/report-coverage.sh
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Generate code coverage reports for uploading to Azure Pipelines and codecov.io.
|
||||
|
||||
set -o pipefail -eu
|
||||
|
||||
PATH="${PWD}/bin:${PATH}"
|
||||
|
||||
if ! ansible-test --help >/dev/null 2>&1; then
|
||||
# Install the devel version of ansible-test for generating code coverage reports.
|
||||
# This is only used by Ansible Collections, which are typically tested against multiple Ansible versions (in separate jobs).
|
||||
# Since a version of ansible-test is required that can work the output from multiple older releases, the devel version is used.
|
||||
pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check
|
||||
fi
|
||||
|
||||
ansible-test coverage xml --group-by command --stub --venv --venv-system-site-packages --color -v
|
||||
38
.azure-pipelines/scripts/run-tests.sh
Executable file
38
.azure-pipelines/scripts/run-tests.sh
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Configure the test environment and run the tests.
|
||||
|
||||
set -o pipefail -eu
|
||||
|
||||
entry_point="$1"
|
||||
test="$2"
|
||||
read -r -a coverage_branches <<< "$3" # space separated list of branches to run code coverage on for scheduled builds
|
||||
|
||||
export COMMIT_MESSAGE
|
||||
export COMPLETE
|
||||
export COVERAGE
|
||||
export IS_PULL_REQUEST
|
||||
|
||||
if [ "${SYSTEM_PULLREQUEST_TARGETBRANCH:-}" ]; then
|
||||
IS_PULL_REQUEST=true
|
||||
COMMIT_MESSAGE=$(git log --format=%B -n 1 HEAD^2)
|
||||
else
|
||||
IS_PULL_REQUEST=
|
||||
COMMIT_MESSAGE=$(git log --format=%B -n 1 HEAD)
|
||||
fi
|
||||
|
||||
COMPLETE=
|
||||
COVERAGE=
|
||||
|
||||
if [ "${BUILD_REASON}" = "Schedule" ]; then
|
||||
COMPLETE=yes
|
||||
|
||||
if printf '%s\n' "${coverage_branches[@]}" | grep -q "^${BUILD_SOURCEBRANCHNAME}$"; then
|
||||
COVERAGE=yes
|
||||
fi
|
||||
fi
|
||||
|
||||
"${entry_point}" "${test}" 2>&1 | "$(dirname "$0")/time-command.py"
|
||||
29
.azure-pipelines/scripts/time-command.py
Executable file
29
.azure-pipelines/scripts/time-command.py
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
"""Prepends a relative timestamp to each input line from stdin and writes it to stdout."""
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
import sys
|
||||
import time
|
||||
|
||||
|
||||
def main():
|
||||
"""Main program entry point."""
|
||||
start = time.time()
|
||||
|
||||
sys.stdin.reconfigure(errors='surrogateescape')
|
||||
sys.stdout.reconfigure(errors='surrogateescape')
|
||||
|
||||
for line in sys.stdin:
|
||||
seconds = time.time() - start
|
||||
sys.stdout.write('%02d:%02d %s' % (seconds // 60, seconds % 60, line))
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
44
.azure-pipelines/templates/coverage.yml
Normal file
44
.azure-pipelines/templates/coverage.yml
Normal file
@@ -0,0 +1,44 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# This template adds a job for processing code coverage data.
|
||||
# It will upload results to Azure Pipelines and codecov.io.
|
||||
# Use it from a job stage that completes after all other jobs have completed.
|
||||
# This can be done by placing it in a separate summary stage that runs after the test stage(s) have completed.
|
||||
|
||||
jobs:
|
||||
- job: Coverage
|
||||
displayName: Code Coverage
|
||||
container: default
|
||||
workspace:
|
||||
clean: all
|
||||
steps:
|
||||
- checkout: self
|
||||
fetchDepth: $(fetchDepth)
|
||||
path: $(checkoutPath)
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: Download Coverage Data
|
||||
inputs:
|
||||
path: coverage/
|
||||
patterns: "Coverage */*=coverage.combined"
|
||||
- bash: .azure-pipelines/scripts/combine-coverage.py coverage/
|
||||
displayName: Combine Coverage Data
|
||||
- bash: .azure-pipelines/scripts/report-coverage.sh
|
||||
displayName: Generate Coverage Report
|
||||
condition: gt(variables.coverageFileCount, 0)
|
||||
- task: PublishCodeCoverageResults@1
|
||||
inputs:
|
||||
codeCoverageTool: Cobertura
|
||||
# Azure Pipelines only accepts a single coverage data file.
|
||||
# That means only Python or PowerShell coverage can be uploaded, but not both.
|
||||
# Set the "pipelinesCoverage" variable to determine which type is uploaded.
|
||||
# Use "coverage" for Python and "coverage-powershell" for PowerShell.
|
||||
summaryFileLocation: "$(outputPath)/reports/$(pipelinesCoverage).xml"
|
||||
displayName: Publish to Azure Pipelines
|
||||
condition: gt(variables.coverageFileCount, 0)
|
||||
- bash: .azure-pipelines/scripts/publish-codecov.py "$(outputPath)"
|
||||
displayName: Publish to codecov.io
|
||||
condition: gt(variables.coverageFileCount, 0)
|
||||
continueOnError: true
|
||||
60
.azure-pipelines/templates/matrix.yml
Normal file
60
.azure-pipelines/templates/matrix.yml
Normal file
@@ -0,0 +1,60 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# This template uses the provided targets and optional groups to generate a matrix which is then passed to the test template.
|
||||
# If this matrix template does not provide the required functionality, consider using the test template directly instead.
|
||||
|
||||
parameters:
|
||||
# A required list of dictionaries, one per test target.
|
||||
# Each item in the list must contain a "test" or "name" key.
|
||||
# Both may be provided. If one is omitted, the other will be used.
|
||||
- name: targets
|
||||
type: object
|
||||
|
||||
# An optional list of values which will be used to multiply the targets list into a matrix.
|
||||
# Values can be strings or numbers.
|
||||
- name: groups
|
||||
type: object
|
||||
default: []
|
||||
|
||||
# An optional format string used to generate the job name.
|
||||
# - {0} is the name of an item in the targets list.
|
||||
- name: nameFormat
|
||||
type: string
|
||||
default: "{0}"
|
||||
|
||||
# An optional format string used to generate the test name.
|
||||
# - {0} is the name of an item in the targets list.
|
||||
- name: testFormat
|
||||
type: string
|
||||
default: "{0}"
|
||||
|
||||
# An optional format string used to add the group to the job name.
|
||||
# {0} is the formatted name of an item in the targets list.
|
||||
# {{1}} is the group -- be sure to include the double "{{" and "}}".
|
||||
- name: nameGroupFormat
|
||||
type: string
|
||||
default: "{0} - {{1}}"
|
||||
|
||||
# An optional format string used to add the group to the test name.
|
||||
# {0} is the formatted test of an item in the targets list.
|
||||
# {{1}} is the group -- be sure to include the double "{{" and "}}".
|
||||
- name: testGroupFormat
|
||||
type: string
|
||||
default: "{0}/{{1}}"
|
||||
|
||||
jobs:
|
||||
- template: test.yml
|
||||
parameters:
|
||||
jobs:
|
||||
- ${{ if eq(length(parameters.groups), 0) }}:
|
||||
- ${{ each target in parameters.targets }}:
|
||||
- name: ${{ format(parameters.nameFormat, coalesce(target.name, target.test)) }}
|
||||
test: ${{ format(parameters.testFormat, coalesce(target.test, target.name)) }}
|
||||
- ${{ if not(eq(length(parameters.groups), 0)) }}:
|
||||
- ${{ each group in parameters.groups }}:
|
||||
- ${{ each target in parameters.targets }}:
|
||||
- name: ${{ format(format(parameters.nameGroupFormat, parameters.nameFormat), coalesce(target.name, target.test), group) }}
|
||||
test: ${{ format(format(parameters.testGroupFormat, parameters.testFormat), coalesce(target.test, target.name), group) }}
|
||||
50
.azure-pipelines/templates/test.yml
Normal file
50
.azure-pipelines/templates/test.yml
Normal file
@@ -0,0 +1,50 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# This template uses the provided list of jobs to create test one or more test jobs.
|
||||
# It can be used directly if needed, or through the matrix template.
|
||||
|
||||
parameters:
|
||||
# A required list of dictionaries, one per test job.
|
||||
# Each item in the list must contain a "job" and "name" key.
|
||||
- name: jobs
|
||||
type: object
|
||||
|
||||
jobs:
|
||||
- ${{ each job in parameters.jobs }}:
|
||||
- job: test_${{ replace(replace(replace(job.test, '/', '_'), '.', '_'), '-', '_') }}
|
||||
displayName: ${{ job.name }}
|
||||
container: default
|
||||
workspace:
|
||||
clean: all
|
||||
steps:
|
||||
- checkout: self
|
||||
fetchDepth: $(fetchDepth)
|
||||
path: $(checkoutPath)
|
||||
- bash: .azure-pipelines/scripts/run-tests.sh "$(entryPoint)" "${{ job.test }}" "$(coverageBranches)"
|
||||
displayName: Run Tests
|
||||
- bash: .azure-pipelines/scripts/process-results.sh
|
||||
condition: succeededOrFailed()
|
||||
displayName: Process Results
|
||||
- bash: .azure-pipelines/scripts/aggregate-coverage.sh "$(Agent.TempDirectory)"
|
||||
condition: eq(variables.haveCoverageData, 'true')
|
||||
displayName: Aggregate Coverage Data
|
||||
- task: PublishTestResults@2
|
||||
condition: eq(variables.haveTestResults, 'true')
|
||||
inputs:
|
||||
testResultsFiles: "$(outputPath)/junit/*.xml"
|
||||
displayName: Publish Test Results
|
||||
- task: PublishPipelineArtifact@1
|
||||
condition: eq(variables.haveBotResults, 'true')
|
||||
displayName: Publish Bot Results
|
||||
inputs:
|
||||
targetPath: "$(outputPath)/bot/"
|
||||
artifactName: "Bot $(System.JobAttempt) $(System.StageDisplayName) $(System.JobDisplayName)"
|
||||
- task: PublishPipelineArtifact@1
|
||||
condition: eq(variables.haveCoverageData, 'true')
|
||||
displayName: Publish Coverage Data
|
||||
inputs:
|
||||
targetPath: "$(Agent.TempDirectory)/coverage/"
|
||||
artifactName: "Coverage $(System.JobAttempt) $(System.StageDisplayName) $(System.JobDisplayName)"
|
||||
197
.github/BOTMETA.yml
vendored
197
.github/BOTMETA.yml
vendored
@@ -50,8 +50,6 @@ files:
|
||||
$callbacks/cgroup_memory_recap.py: {}
|
||||
$callbacks/context_demo.py: {}
|
||||
$callbacks/counter_enabled.py: {}
|
||||
$callbacks/default_without_diff.py:
|
||||
maintainers: felixfontein
|
||||
$callbacks/dense.py:
|
||||
maintainers: dagwieers
|
||||
$callbacks/diy.py:
|
||||
@@ -99,9 +97,6 @@ files:
|
||||
$connections/funcd.py:
|
||||
maintainers: mscherer
|
||||
$connections/iocage.py: {}
|
||||
$connections/incus.py:
|
||||
labels: incus
|
||||
maintainers: stgraber
|
||||
$connections/jail.py:
|
||||
maintainers: $team_ansible_core
|
||||
$connections/lxc.py: {}
|
||||
@@ -124,7 +119,7 @@ files:
|
||||
labels: hwc
|
||||
maintainers: $team_huawei
|
||||
$doc_fragments/nomad.py:
|
||||
maintainers: chris93111 apecnascimento
|
||||
maintainers: chris93111
|
||||
$doc_fragments/xenserver.py:
|
||||
labels: xenserver
|
||||
maintainers: bvitnik
|
||||
@@ -138,8 +133,6 @@ files:
|
||||
maintainers: giner
|
||||
$filters/from_csv.py:
|
||||
maintainers: Ajpantuso
|
||||
$filters/from_ini.py:
|
||||
maintainers: sscheib
|
||||
$filters/groupby_as_dict.py:
|
||||
maintainers: felixfontein
|
||||
$filters/hashids.py:
|
||||
@@ -151,18 +144,8 @@ files:
|
||||
$filters/jc.py:
|
||||
maintainers: kellyjonbrazil
|
||||
$filters/json_query.py: {}
|
||||
$filters/lists.py:
|
||||
maintainers: cfiehe
|
||||
$filters/lists_difference.yml:
|
||||
maintainers: cfiehe
|
||||
$filters/lists_intersect.yml:
|
||||
maintainers: cfiehe
|
||||
$filters/lists_mergeby.py:
|
||||
maintainers: vbotka
|
||||
$filters/lists_symmetric_difference.yml:
|
||||
maintainers: cfiehe
|
||||
$filters/lists_union.yml:
|
||||
maintainers: cfiehe
|
||||
$filters/random_mac.py: {}
|
||||
$filters/time.py:
|
||||
maintainers: resmo
|
||||
@@ -170,8 +153,6 @@ files:
|
||||
maintainers: resmo
|
||||
$filters/to_hours.yml:
|
||||
maintainers: resmo
|
||||
$filters/to_ini.py:
|
||||
maintainers: sscheib
|
||||
$filters/to_milliseconds.yml:
|
||||
maintainers: resmo
|
||||
$filters/to_minutes.yml:
|
||||
@@ -212,7 +193,7 @@ files:
|
||||
labels: cloud opennebula
|
||||
maintainers: feldsam
|
||||
$inventories/proxmox.py:
|
||||
maintainers: $team_virt ilijamt krauthosting
|
||||
maintainers: $team_virt ilijamt
|
||||
$inventories/scaleway.py:
|
||||
labels: cloud scaleway
|
||||
maintainers: $team_scaleway
|
||||
@@ -223,8 +204,6 @@ files:
|
||||
maintainers: ddelnano shinuza
|
||||
$lookups/:
|
||||
labels: lookups
|
||||
$lookups/bitwarden_secrets_manager.py:
|
||||
maintainers: jantari
|
||||
$lookups/bitwarden.py:
|
||||
maintainers: lungj
|
||||
$lookups/cartesian.py: {}
|
||||
@@ -253,8 +232,6 @@ files:
|
||||
$lookups/filetree.py:
|
||||
maintainers: dagwieers
|
||||
$lookups/flattened.py: {}
|
||||
$lookups/github_app_access_token.py:
|
||||
maintainers: weisheng-p
|
||||
$lookups/hiera.py:
|
||||
maintainers: jparrill
|
||||
$lookups/keyring.py: {}
|
||||
@@ -265,16 +242,14 @@ files:
|
||||
labels: manifold
|
||||
maintainers: galanoff
|
||||
$lookups/merge_variables.py:
|
||||
maintainers: rlenferink m-a-r-k-e alpex8
|
||||
maintainers: rlenferink m-a-r-k-e
|
||||
$lookups/onepass:
|
||||
labels: onepassword
|
||||
maintainers: samdoran
|
||||
$lookups/onepassword.py:
|
||||
ignore: scottsb
|
||||
maintainers: azenk
|
||||
maintainers: azenk scottsb
|
||||
$lookups/onepassword_raw.py:
|
||||
ignore: scottsb
|
||||
maintainers: azenk
|
||||
maintainers: azenk scottsb
|
||||
$lookups/passwordstore.py: {}
|
||||
$lookups/random_pet.py:
|
||||
maintainers: Akasurde
|
||||
@@ -299,8 +274,6 @@ files:
|
||||
$module_utils/gconftool2.py:
|
||||
labels: gconftool2
|
||||
maintainers: russoz
|
||||
$module_utils/gio_mime.py:
|
||||
maintainers: russoz
|
||||
$module_utils/gitlab.py:
|
||||
keywords: gitlab source_control
|
||||
labels: gitlab
|
||||
@@ -353,9 +326,6 @@ files:
|
||||
$module_utils/scaleway.py:
|
||||
labels: cloud scaleway
|
||||
maintainers: $team_scaleway
|
||||
$module_utils/snap.py:
|
||||
labels: snap
|
||||
maintainers: russoz
|
||||
$module_utils/ssh.py:
|
||||
maintainers: russoz
|
||||
$module_utils/storage/hpe3par/hpe3par.py:
|
||||
@@ -363,9 +333,6 @@ files:
|
||||
$module_utils/utm_utils.py:
|
||||
labels: utm_utils
|
||||
maintainers: $team_e_spirit
|
||||
$module_utils/vardict.py:
|
||||
labels: vardict
|
||||
maintainers: russoz
|
||||
$module_utils/wdc_redfish_utils.py:
|
||||
labels: wdc_redfish_utils
|
||||
maintainers: $team_wdc
|
||||
@@ -425,7 +392,7 @@ files:
|
||||
$modules/bearychat.py:
|
||||
maintainers: tonyseek
|
||||
$modules/bigpanda.py:
|
||||
ignore: hkariti
|
||||
maintainers: hkariti
|
||||
$modules/bitbucket_:
|
||||
maintainers: catcombo
|
||||
$modules/bower.py:
|
||||
@@ -461,7 +428,7 @@ files:
|
||||
ignore: resmo
|
||||
maintainers: dmtrs
|
||||
$modules/consul:
|
||||
ignore: colin-nolan Hakon
|
||||
ignore: colin-nolan
|
||||
maintainers: $team_consul
|
||||
$modules/copr.py:
|
||||
maintainers: schlupov
|
||||
@@ -496,8 +463,6 @@ files:
|
||||
maintainers: russoz
|
||||
$modules/dnf_versionlock.py:
|
||||
maintainers: moreda
|
||||
$modules/dnf_config_manager.py:
|
||||
maintainers: ahyattdev
|
||||
$modules/dnsimple.py:
|
||||
maintainers: drcapulet
|
||||
$modules/dnsimple_info.py:
|
||||
@@ -520,9 +485,6 @@ files:
|
||||
$modules/facter.py:
|
||||
labels: facter
|
||||
maintainers: $team_ansible_core gamethis
|
||||
$modules/facter_facts.py:
|
||||
labels: facter
|
||||
maintainers: russoz $team_ansible_core gamethis
|
||||
$modules/filesize.py:
|
||||
maintainers: quidame
|
||||
$modules/filesystem.py:
|
||||
@@ -545,12 +507,8 @@ files:
|
||||
$modules/gem.py:
|
||||
labels: gem
|
||||
maintainers: $team_ansible_core johanwiren
|
||||
$modules/gio_mime.py:
|
||||
maintainers: russoz
|
||||
$modules/git_config.py:
|
||||
maintainers: djmattyg007 mgedmin
|
||||
$modules/git_config_info.py:
|
||||
maintainers: guenhter
|
||||
$modules/github_:
|
||||
maintainers: stpierre
|
||||
$modules/github_deploy_key.py:
|
||||
@@ -569,29 +527,14 @@ files:
|
||||
keywords: gitlab source_control
|
||||
maintainers: $team_gitlab
|
||||
notify: jlozadad
|
||||
ignore: dj-wasabi
|
||||
$modules/gitlab_branch.py:
|
||||
maintainers: paytroff
|
||||
$modules/gitlab_issue.py:
|
||||
maintainers: zvaraondrej
|
||||
$modules/gitlab_label.py:
|
||||
maintainers: gpongelli
|
||||
$modules/gitlab_merge_request.py:
|
||||
maintainers: zvaraondrej
|
||||
$modules/gitlab_milestone.py:
|
||||
maintainers: gpongelli
|
||||
$modules/gitlab_project_variable.py:
|
||||
maintainers: markuman
|
||||
$modules/gitlab_instance_variable.py:
|
||||
maintainers: benibr
|
||||
$modules/gitlab_runner.py:
|
||||
maintainers: SamyCoenen
|
||||
$modules/gitlab_user.py:
|
||||
maintainers: LennertMertens stgrace
|
||||
$modules/gitlab_group_access_token.py:
|
||||
maintainers: pixslx
|
||||
$modules/gitlab_project_access_token.py:
|
||||
maintainers: pixslx
|
||||
$modules/grove.py:
|
||||
maintainers: zimbatm
|
||||
$modules/gunicorn.py:
|
||||
@@ -680,9 +623,6 @@ files:
|
||||
maintainers: bregman-arie
|
||||
$modules/ipa_:
|
||||
maintainers: $team_ipa
|
||||
ignore: fxfitz
|
||||
$modules/ipa_dnsrecord.py:
|
||||
maintainers: $team_ipa jwbernin
|
||||
$modules/ipbase_info.py:
|
||||
maintainers: dominikkukacka
|
||||
$modules/ipa_pwpolicy.py:
|
||||
@@ -719,9 +659,7 @@ files:
|
||||
labels: jboss
|
||||
maintainers: $team_jboss jhoekx
|
||||
$modules/jenkins_build.py:
|
||||
maintainers: brettmilford unnecessary-username juanmcasanova
|
||||
$modules/jenkins_build_info.py:
|
||||
maintainers: juanmcasanova
|
||||
maintainers: brettmilford unnecessary-username
|
||||
$modules/jenkins_job.py:
|
||||
maintainers: sermilrod
|
||||
$modules/jenkins_job_info.py:
|
||||
@@ -731,9 +669,9 @@ files:
|
||||
$modules/jenkins_script.py:
|
||||
maintainers: hogarthj
|
||||
$modules/jira.py:
|
||||
ignore: DWSR tarka
|
||||
ignore: DWSR
|
||||
labels: jira
|
||||
maintainers: Slezhuk pertoft
|
||||
maintainers: Slezhuk tarka pertoft
|
||||
$modules/kdeconfig.py:
|
||||
maintainers: smeso
|
||||
$modules/kernel_blacklist.py:
|
||||
@@ -742,16 +680,8 @@ files:
|
||||
maintainers: $team_keycloak
|
||||
$modules/keycloak_authentication.py:
|
||||
maintainers: elfelip Gaetan2907
|
||||
$modules/keycloak_authentication_required_actions.py:
|
||||
maintainers: Skrekulko
|
||||
$modules/keycloak_authz_authorization_scope.py:
|
||||
maintainers: mattock
|
||||
$modules/keycloak_authz_permission.py:
|
||||
maintainers: mattock
|
||||
$modules/keycloak_authz_custom_policy.py:
|
||||
maintainers: mattock
|
||||
$modules/keycloak_authz_permission_info.py:
|
||||
maintainers: mattock
|
||||
$modules/keycloak_client_rolemapping.py:
|
||||
maintainers: Gaetan2907
|
||||
$modules/keycloak_clientscope.py:
|
||||
@@ -770,22 +700,12 @@ files:
|
||||
maintainers: kris2kris
|
||||
$modules/keycloak_realm_info.py:
|
||||
maintainers: fynncfchen
|
||||
$modules/keycloak_realm_key.py:
|
||||
maintainers: mattock
|
||||
$modules/keycloak_role.py:
|
||||
maintainers: laurpaum
|
||||
$modules/keycloak_user.py:
|
||||
maintainers: elfelip
|
||||
$modules/keycloak_user_federation.py:
|
||||
maintainers: laurpaum
|
||||
$modules/keycloak_component_info.py:
|
||||
maintainers: desand01
|
||||
$modules/keycloak_client_rolescope.py:
|
||||
maintainers: desand01
|
||||
$modules/keycloak_user_rolemapping.py:
|
||||
maintainers: bratwurzt
|
||||
$modules/keycloak_realm_rolemapping.py:
|
||||
maintainers: agross mhuysamen Gaetan2907
|
||||
$modules/keyring.py:
|
||||
maintainers: ahussey-redhat
|
||||
$modules/keyring_info.py:
|
||||
@@ -828,8 +748,6 @@ files:
|
||||
maintainers: nerzhul
|
||||
$modules/lvg.py:
|
||||
maintainers: abulimov
|
||||
$modules/lvg_rename.py:
|
||||
maintainers: lszomor
|
||||
$modules/lvol.py:
|
||||
maintainers: abulimov jhoekx zigaSRC unkaputtbar112
|
||||
$modules/lxc_container.py:
|
||||
@@ -914,7 +832,7 @@ files:
|
||||
$modules/nmcli.py:
|
||||
maintainers: alcamie101
|
||||
$modules/nomad_:
|
||||
maintainers: chris93111 apecnascimento
|
||||
maintainers: chris93111
|
||||
$modules/nosh.py:
|
||||
maintainers: tacatac
|
||||
$modules/npm.py:
|
||||
@@ -999,7 +917,7 @@ files:
|
||||
labels: pagerduty
|
||||
maintainers: suprememoocow thaumos
|
||||
$modules/pagerduty_alert.py:
|
||||
maintainers: ApsOps xshen1
|
||||
maintainers: ApsOps
|
||||
$modules/pagerduty_change.py:
|
||||
maintainers: adamvaughan
|
||||
$modules/pagerduty_user.py:
|
||||
@@ -1011,7 +929,7 @@ files:
|
||||
$modules/pamd.py:
|
||||
maintainers: kevensen
|
||||
$modules/parted.py:
|
||||
maintainers: ColOfAbRiX jake2184
|
||||
maintainers: ColOfAbRiX rosowiecki jake2184
|
||||
$modules/pear.py:
|
||||
ignore: jle64
|
||||
labels: pear
|
||||
@@ -1042,9 +960,6 @@ files:
|
||||
maintainers: $team_solaris dermute
|
||||
$modules/pmem.py:
|
||||
maintainers: mizumm
|
||||
$modules/pnpm.py:
|
||||
ignore: chrishoffman
|
||||
maintainers: aretrosen
|
||||
$modules/portage.py:
|
||||
ignore: sayap
|
||||
labels: portage
|
||||
@@ -1061,27 +976,22 @@ files:
|
||||
$modules/proxmox:
|
||||
keywords: kvm libvirt proxmox qemu
|
||||
labels: proxmox virt
|
||||
maintainers: $team_virt UnderGreen krauthosting
|
||||
ignore: tleguern
|
||||
maintainers: $team_virt
|
||||
$modules/proxmox.py:
|
||||
ignore: skvidal
|
||||
maintainers: UnderGreen krauthosting
|
||||
maintainers: UnderGreen
|
||||
$modules/proxmox_disk.py:
|
||||
maintainers: castorsky krauthosting
|
||||
maintainers: castorsky
|
||||
$modules/proxmox_kvm.py:
|
||||
ignore: skvidal
|
||||
maintainers: helldorado krauthosting
|
||||
maintainers: helldorado
|
||||
$modules/proxmox_nic.py:
|
||||
maintainers: Kogelvis krauthosting
|
||||
$modules/proxmox_node_info.py:
|
||||
maintainers: jwbernin krauthosting
|
||||
$modules/proxmox_storage_contents_info.py:
|
||||
maintainers: l00ptr krauthosting
|
||||
maintainers: Kogelvis
|
||||
$modules/proxmox_tasks_info:
|
||||
maintainers: paginabianca krauthosting
|
||||
maintainers: paginabianca
|
||||
$modules/proxmox_template.py:
|
||||
ignore: skvidal
|
||||
maintainers: UnderGreen krauthosting
|
||||
maintainers: UnderGreen
|
||||
$modules/pubnub_blocks.py:
|
||||
maintainers: parfeon pubnub
|
||||
$modules/pulp_repo.py:
|
||||
@@ -1264,8 +1174,6 @@ files:
|
||||
ignore: ryansb
|
||||
$modules/shutdown.py:
|
||||
maintainers: nitzmahone samdoran aminvakil
|
||||
$modules/simpleinit_msb.py:
|
||||
maintainers: vaygr
|
||||
$modules/sl_vm.py:
|
||||
maintainers: mcltn
|
||||
$modules/slack.py:
|
||||
@@ -1278,7 +1186,7 @@ files:
|
||||
maintainers: $team_solaris
|
||||
$modules/snap.py:
|
||||
labels: snap
|
||||
maintainers: angristan vcarceler russoz
|
||||
maintainers: angristan vcarceler
|
||||
$modules/snap_alias.py:
|
||||
labels: snap
|
||||
maintainers: russoz
|
||||
@@ -1356,25 +1264,20 @@ files:
|
||||
maintainers: nate-kingsley
|
||||
$modules/urpmi.py:
|
||||
maintainers: pmakowski
|
||||
$modules/usb_facts.py:
|
||||
maintainers: maxopoly
|
||||
$modules/utm_:
|
||||
keywords: sophos utm
|
||||
maintainers: $team_e_spirit
|
||||
$modules/utm_ca_host_key_cert.py:
|
||||
ignore: stearz
|
||||
maintainers: $team_e_spirit
|
||||
maintainers: stearz
|
||||
$modules/utm_ca_host_key_cert_info.py:
|
||||
ignore: stearz
|
||||
maintainers: $team_e_spirit
|
||||
maintainers: stearz
|
||||
$modules/utm_network_interface_address.py:
|
||||
maintainers: steamx
|
||||
$modules/utm_network_interface_address_info.py:
|
||||
maintainers: steamx
|
||||
$modules/utm_proxy_auth_profile.py:
|
||||
keywords: sophos utm
|
||||
ignore: stearz
|
||||
maintainers: $team_e_spirit
|
||||
maintainers: $team_e_spirit stearz
|
||||
$modules/utm_proxy_exception.py:
|
||||
keywords: sophos utm
|
||||
maintainers: $team_e_spirit RickS-C137
|
||||
@@ -1450,47 +1353,8 @@ files:
|
||||
ignore: matze
|
||||
labels: zypper
|
||||
maintainers: $team_suse
|
||||
$plugin_utils/unsafe.py:
|
||||
maintainers: felixfontein
|
||||
$tests/a_module.py:
|
||||
maintainers: felixfontein
|
||||
$tests/fqdn_valid.py:
|
||||
maintainers: vbotka
|
||||
#########################
|
||||
docs/docsite/rst/filter_guide.rst: {}
|
||||
docs/docsite/rst/filter_guide_abstract_informations.rst: {}
|
||||
docs/docsite/rst/filter_guide_abstract_informations_counting_elements_in_sequence.rst:
|
||||
maintainers: keilr
|
||||
docs/docsite/rst/filter_guide_abstract_informations_dictionaries.rst:
|
||||
maintainers: felixfontein giner
|
||||
docs/docsite/rst/filter_guide_abstract_informations_grouping.rst:
|
||||
maintainers: felixfontein
|
||||
docs/docsite/rst/filter_guide_abstract_informations_lists_helper.rst:
|
||||
maintainers: cfiehe
|
||||
docs/docsite/rst/filter_guide_abstract_informations_merging_lists_of_dictionaries.rst:
|
||||
maintainers: vbotka
|
||||
docs/docsite/rst/filter_guide_conversions.rst:
|
||||
maintainers: Ajpantuso kellyjonbrazil
|
||||
docs/docsite/rst/filter_guide_creating_identifiers.rst:
|
||||
maintainers: Ajpantuso
|
||||
docs/docsite/rst/filter_guide_paths.rst: {}
|
||||
docs/docsite/rst/filter_guide_selecting_json_data.rst: {}
|
||||
docs/docsite/rst/filter_guide_working_with_times.rst:
|
||||
maintainers: resmo
|
||||
docs/docsite/rst/filter_guide_working_with_unicode.rst:
|
||||
maintainers: Ajpantuso
|
||||
docs/docsite/rst/filter_guide_working_with_versions.rst:
|
||||
maintainers: ericzolf
|
||||
docs/docsite/rst/guide_alicloud.rst:
|
||||
maintainers: xiaozhu36
|
||||
docs/docsite/rst/guide_online.rst:
|
||||
maintainers: remyleone
|
||||
docs/docsite/rst/guide_packet.rst:
|
||||
maintainers: baldwinSPC nurfet-becirevic t0mk teebes
|
||||
docs/docsite/rst/guide_scaleway.rst:
|
||||
maintainers: $team_scaleway
|
||||
docs/docsite/rst/test_guide.rst:
|
||||
maintainers: felixfontein
|
||||
#########################
|
||||
tests/:
|
||||
labels: tests
|
||||
@@ -1508,6 +1372,7 @@ macros:
|
||||
becomes: plugins/become
|
||||
caches: plugins/cache
|
||||
callbacks: plugins/callback
|
||||
cliconfs: plugins/cliconf
|
||||
connections: plugins/connection
|
||||
doc_fragments: plugins/doc_fragments
|
||||
filters: plugins/filter
|
||||
@@ -1515,19 +1380,19 @@ macros:
|
||||
lookups: plugins/lookup
|
||||
module_utils: plugins/module_utils
|
||||
modules: plugins/modules
|
||||
plugin_utils: plugins/plugin_utils
|
||||
terminals: plugins/terminal
|
||||
tests: plugins/test
|
||||
team_ansible_core:
|
||||
team_aix: MorrisA bcoca d-little flynn1973 gforster kairoaraujo marvin-sinister mator molekuul ramooncamacho wtcross
|
||||
team_bsd: JoergFiedler MacLemon bcoca dch jasperla mekanix opoplawski overhacked tuxillo
|
||||
team_consul: sgargan apollo13
|
||||
team_consul: sgargan
|
||||
team_cyberark_conjur: jvanderhoof ryanprior
|
||||
team_e_spirit: MatrixCrawler getjack
|
||||
team_flatpak: JayKayy oolongbrothers
|
||||
team_gitlab: Lunik Shaps marwatk waheedi zanssa scodeman metanovii sh0shin nejch lgatellier suukit
|
||||
team_gitlab: Lunik Shaps dj-wasabi marwatk waheedi zanssa scodeman metanovii sh0shin nejch lgatellier suukit
|
||||
team_hpux: bcoca davx8342
|
||||
team_huawei: QijunPan TommyLike edisonxiang freesky-edward hwDCN niuzhenguo xuxiaowei0512 yanzhangi zengchen1024 zhongjun2
|
||||
team_ipa: Akasurde Nosmoht justchris1
|
||||
team_ipa: Akasurde Nosmoht fxfitz justchris1
|
||||
team_jboss: Wolfant jairojunior wbrefvem
|
||||
team_keycloak: eikef ndclt mattock
|
||||
team_linode: InTheCloudDan decentral1se displague rmcintosh Charliekenney23 LBGarber
|
||||
@@ -1542,6 +1407,6 @@ macros:
|
||||
team_rhsm: cnsnyder ptoscano
|
||||
team_scaleway: remyleone abarbare
|
||||
team_solaris: bcoca fishman jasperla jpdasma mator scathatheworm troy2914 xen0l
|
||||
team_suse: commel evrardjp lrupp AnderEnder alxgu andytom sealor
|
||||
team_virt: joshainglis karmab Thulium-Drake Ajpantuso
|
||||
team_suse: commel evrardjp lrupp toabctl AnderEnder alxgu andytom sealor
|
||||
team_virt: joshainglis karmab tleguern Thulium-Drake Ajpantuso
|
||||
team_wdc: mikemoerk
|
||||
|
||||
193
.github/workflows/ansible-test.yml
vendored
Normal file
193
.github/workflows/ansible-test.yml
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# For the comprehensive list of the inputs supported by the ansible-community/ansible-test-gh-action GitHub Action, see
|
||||
# https://github.com/marketplace/actions/ansible-test
|
||||
|
||||
name: EOL CI
|
||||
on:
|
||||
# Run EOL CI against all pushes (direct commits, also merged PRs), Pull Requests
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- stable-*
|
||||
pull_request:
|
||||
# Run EOL CI once per day (at 08:00 UTC)
|
||||
schedule:
|
||||
- cron: '0 8 * * *'
|
||||
|
||||
concurrency:
|
||||
# Make sure there is at most one active run per PR, but do not cancel any non-PR runs
|
||||
group: ${{ github.workflow }}-${{ (github.head_ref && github.event.number) || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
sanity:
|
||||
name: EOL Sanity (Ⓐ${{ matrix.ansible }})
|
||||
strategy:
|
||||
matrix:
|
||||
ansible:
|
||||
- '2.11'
|
||||
# Ansible-test on various stable branches does not yet work well with cgroups v2.
|
||||
# Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04
|
||||
# image for these stable branches. The list of branches where this is necessary will
|
||||
# shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28
|
||||
# for the latest list.
|
||||
runs-on: >-
|
||||
${{ contains(fromJson(
|
||||
'["2.9", "2.10", "2.11"]'
|
||||
), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }}
|
||||
steps:
|
||||
- name: Perform sanity testing
|
||||
uses: felixfontein/ansible-test-gh-action@main
|
||||
with:
|
||||
ansible-core-github-repository-slug: felixfontein/ansible
|
||||
ansible-core-version: stable-${{ matrix.ansible }}
|
||||
coverage: ${{ github.event_name == 'schedule' && 'always' || 'never' }}
|
||||
pull-request-change-detection: 'true'
|
||||
testing-type: sanity
|
||||
|
||||
units:
|
||||
# Ansible-test on various stable branches does not yet work well with cgroups v2.
|
||||
# Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04
|
||||
# image for these stable branches. The list of branches where this is necessary will
|
||||
# shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28
|
||||
# for the latest list.
|
||||
runs-on: >-
|
||||
${{ contains(fromJson(
|
||||
'["2.9", "2.10", "2.11"]'
|
||||
), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }}
|
||||
name: EOL Units (Ⓐ${{ matrix.ansible }}+py${{ matrix.python }})
|
||||
strategy:
|
||||
# As soon as the first unit test fails, cancel the others to free up the CI queue
|
||||
fail-fast: true
|
||||
matrix:
|
||||
ansible:
|
||||
- ''
|
||||
python:
|
||||
- ''
|
||||
exclude:
|
||||
- ansible: ''
|
||||
include:
|
||||
- ansible: '2.11'
|
||||
python: '2.7'
|
||||
- ansible: '2.11'
|
||||
python: '3.5'
|
||||
|
||||
steps:
|
||||
- name: >-
|
||||
Perform unit testing against
|
||||
Ansible version ${{ matrix.ansible }}
|
||||
uses: felixfontein/ansible-test-gh-action@main
|
||||
with:
|
||||
ansible-core-github-repository-slug: felixfontein/ansible
|
||||
ansible-core-version: stable-${{ matrix.ansible }}
|
||||
coverage: ${{ github.event_name == 'schedule' && 'always' || 'never' }}
|
||||
pre-test-cmd: >-
|
||||
mkdir -p ../../ansible
|
||||
;
|
||||
git clone --depth=1 --single-branch https://github.com/ansible-collections/community.internal_test_tools.git ../../community/internal_test_tools
|
||||
pull-request-change-detection: 'true'
|
||||
target-python-version: ${{ matrix.python }}
|
||||
testing-type: units
|
||||
|
||||
integration:
|
||||
# Ansible-test on various stable branches does not yet work well with cgroups v2.
|
||||
# Since ubuntu-latest now uses Ubuntu 22.04, we need to fall back to the ubuntu-20.04
|
||||
# image for these stable branches. The list of branches where this is necessary will
|
||||
# shrink over time, check out https://github.com/ansible-collections/news-for-maintainers/issues/28
|
||||
# for the latest list.
|
||||
runs-on: >-
|
||||
${{ contains(fromJson(
|
||||
'["2.9", "2.10", "2.11"]'
|
||||
), matrix.ansible) && 'ubuntu-20.04' || 'ubuntu-latest' }}
|
||||
name: EOL I (Ⓐ${{ matrix.ansible }}+${{ matrix.docker }}+py${{ matrix.python }}:${{ matrix.target }})
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
ansible:
|
||||
- ''
|
||||
docker:
|
||||
- ''
|
||||
python:
|
||||
- ''
|
||||
target:
|
||||
- ''
|
||||
exclude:
|
||||
- ansible: ''
|
||||
include:
|
||||
# 2.11
|
||||
- ansible: '2.11'
|
||||
docker: fedora32
|
||||
python: ''
|
||||
target: azp/posix/1/
|
||||
- ansible: '2.11'
|
||||
docker: fedora32
|
||||
python: ''
|
||||
target: azp/posix/2/
|
||||
- ansible: '2.11'
|
||||
docker: fedora32
|
||||
python: ''
|
||||
target: azp/posix/3/
|
||||
- ansible: '2.11'
|
||||
docker: fedora33
|
||||
python: ''
|
||||
target: azp/posix/1/
|
||||
- ansible: '2.11'
|
||||
docker: fedora33
|
||||
python: ''
|
||||
target: azp/posix/2/
|
||||
- ansible: '2.11'
|
||||
docker: fedora33
|
||||
python: ''
|
||||
target: azp/posix/3/
|
||||
- ansible: '2.11'
|
||||
docker: alpine3
|
||||
python: ''
|
||||
target: azp/posix/1/
|
||||
- ansible: '2.11'
|
||||
docker: alpine3
|
||||
python: ''
|
||||
target: azp/posix/2/
|
||||
- ansible: '2.11'
|
||||
docker: alpine3
|
||||
python: ''
|
||||
target: azp/posix/3/
|
||||
# Right now all generic tests are disabled. Uncomment when at least one of them is re-enabled.
|
||||
# - ansible: '2.11'
|
||||
# docker: default
|
||||
# python: '2.7'
|
||||
# target: azp/generic/1/
|
||||
# - ansible: '2.11'
|
||||
# docker: default
|
||||
# python: '3.5'
|
||||
# target: azp/generic/2/
|
||||
|
||||
steps:
|
||||
- name: >-
|
||||
Perform integration testing against
|
||||
Ansible version ${{ matrix.ansible }}
|
||||
under Python ${{ matrix.python }}
|
||||
uses: felixfontein/ansible-test-gh-action@main
|
||||
with:
|
||||
ansible-core-github-repository-slug: felixfontein/ansible
|
||||
ansible-core-version: stable-${{ matrix.ansible }}
|
||||
coverage: ${{ github.event_name == 'schedule' && 'always' || 'never' }}
|
||||
docker-image: ${{ matrix.docker }}
|
||||
integration-continue-on-error: 'false'
|
||||
integration-diff: 'false'
|
||||
integration-retry-on-error: 'true'
|
||||
pre-test-cmd: >-
|
||||
mkdir -p ../../ansible
|
||||
;
|
||||
git clone --depth=1 --single-branch https://github.com/ansible-collections/ansible.posix.git ../../ansible/posix
|
||||
;
|
||||
git clone --depth=1 --single-branch https://github.com/ansible-collections/community.crypto.git ../../community/crypto
|
||||
;
|
||||
git clone --depth=1 --single-branch https://github.com/ansible-collections/community.internal_test_tools.git ../../community/internal_test_tools
|
||||
pull-request-change-detection: 'true'
|
||||
target: ${{ matrix.target }}
|
||||
target-python-version: ${{ matrix.python }}
|
||||
testing-type: integration
|
||||
36
.github/workflows/codeql-analysis.yml
vendored
Normal file
36
.github/workflows/codeql-analysis.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
name: "Code scanning - action"
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '26 19 * * 1'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
CodeQL-Build:
|
||||
|
||||
permissions:
|
||||
actions: read # for github/codeql-action/init to get workflow details
|
||||
contents: read # for actions/checkout to fetch code
|
||||
security-events: write # for github/codeql-action/autobuild to send a status report
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: python
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
35
.github/workflows/reuse.yml
vendored
Normal file
35
.github/workflows/reuse.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
name: Verify REUSE
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened]
|
||||
branches: [main]
|
||||
# Run CI once per day (at 07:30 UTC)
|
||||
schedule:
|
||||
- cron: '30 7 * * *'
|
||||
|
||||
jobs:
|
||||
check:
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || '' }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install reuse
|
||||
|
||||
- name: Check REUSE compliance
|
||||
run: |
|
||||
reuse lint
|
||||
23
.pre-commit-config.yaml
Normal file
23
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.0.1
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: mixed-line-ending
|
||||
args: [--fix=lf]
|
||||
- id: fix-encoding-pragma
|
||||
- id: check-ast
|
||||
- id: check-merge-conflict
|
||||
- id: check-symlinks
|
||||
- repo: https://github.com/pre-commit/pygrep-hooks
|
||||
rev: v1.9.0
|
||||
hooks:
|
||||
- id: rst-backticks
|
||||
types: [file]
|
||||
files: changelogs/fragments/.*\.(yml|yaml)$
|
||||
5
.reuse/dep5
Normal file
5
.reuse/dep5
Normal file
@@ -0,0 +1,5 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
|
||||
Files: changelogs/fragments/*
|
||||
Copyright: Ansible Project
|
||||
License: GPL-3.0-or-later
|
||||
1014
CHANGELOG.md
1014
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
1162
CHANGELOG.rst
1162
CHANGELOG.rst
File diff suppressed because it is too large
Load Diff
@@ -31,9 +31,7 @@ Also, consider taking up a valuable, reviewed, but abandoned pull request which
|
||||
* Try committing your changes with an informative but short commit message.
|
||||
* Do not squash your commits and force-push to your branch if not needed. Reviews of your pull request are much easier with individual commits to comprehend the pull request history. All commits of your pull request branch will be squashed into one commit by GitHub upon merge.
|
||||
* Do not add merge commits to your PR. The bot will complain and you will have to rebase ([instructions for rebasing](https://docs.ansible.com/ansible/latest/dev_guide/developing_rebasing.html)) to remove them before your PR can be merged. To avoid that git automatically does merges during pulls, you can configure it to do rebases instead by running `git config pull.rebase true` inside the repository checkout.
|
||||
* Make sure your PR includes a [changelog fragment](https://docs.ansible.com/ansible/devel/community/collection_development_process.html#creating-a-changelog-fragment).
|
||||
* You must not include a fragment for new modules or new plugins. Also you shouldn't include one for docs-only changes. (If you're not sure, simply don't include one, we'll tell you whether one is needed or not :) )
|
||||
* Please always include a link to the pull request itself, and if the PR is about an issue, also a link to the issue. Also make sure the fragment ends with a period, and begins with a lower-case letter after `-`. (Again, if you don't do this, we'll add suggestions to fix it, so don't worry too much :) )
|
||||
* Make sure your PR includes a [changelog fragment](https://docs.ansible.com/ansible/devel/community/development_process.html#creating-changelog-fragments). (You must not include a fragment for new modules or new plugins. Also you shouldn't include one for docs-only changes. If you're not sure, simply don't include one, we'll tell you whether one is needed or not :) )
|
||||
* Avoid reformatting unrelated parts of the codebase in your PR. These types of changes will likely be requested for reversion, create additional work for reviewers, and may cause approval to be delayed.
|
||||
|
||||
You can also read [our Quick-start development guide](https://github.com/ansible/community-docs/blob/main/create_pr_quick_start_guide.rst).
|
||||
@@ -56,8 +54,6 @@ cd ~/dev/ansible_collections/community/general
|
||||
|
||||
Then you can run `ansible-test` (which is a part of [ansible-core](https://pypi.org/project/ansible-core/)) inside the checkout. The following example commands expect that you have installed Docker or Podman. Note that Podman has only been supported by more recent ansible-core releases. If you are using Docker, the following will work with Ansible 2.9+.
|
||||
|
||||
### Sanity tests
|
||||
|
||||
The following commands show how to run sanity tests:
|
||||
|
||||
```.bash
|
||||
@@ -68,8 +64,6 @@ ansible-test sanity --docker -v
|
||||
ansible-test sanity --docker -v plugins/modules/system/pids.py tests/integration/targets/pids/
|
||||
```
|
||||
|
||||
### Unit tests
|
||||
|
||||
The following commands show how to run unit tests:
|
||||
|
||||
```.bash
|
||||
@@ -83,32 +77,13 @@ ansible-test units --docker -v --python 3.8
|
||||
ansible-test units --docker -v --python 3.8 tests/unit/plugins/modules/net_tools/test_nmcli.py
|
||||
```
|
||||
|
||||
### Integration tests
|
||||
|
||||
The following commands show how to run integration tests:
|
||||
|
||||
#### In Docker
|
||||
|
||||
Integration tests on Docker have the following parameters:
|
||||
- `image_name` (required): The name of the Docker image. To get the list of supported Docker images, run
|
||||
`ansible-test integration --help` and look for _target docker images_.
|
||||
- `test_name` (optional): The name of the integration test.
|
||||
For modules, this equals the short name of the module; for example, `pacman` in case of `community.general.pacman`.
|
||||
For plugins, the plugin type is added before the plugin's short name, for example `callback_yaml` for the `community.general.yaml` callback.
|
||||
```.bash
|
||||
# Test all plugins/modules on fedora40
|
||||
ansible-test integration -v --docker fedora40
|
||||
# Run integration tests for the interfaces_files module in a Docker container using the
|
||||
# fedora35 operating system image (the supported images depend on your ansible-core version):
|
||||
ansible-test integration --docker fedora35 -v interfaces_file
|
||||
|
||||
# Template
|
||||
ansible-test integration -v --docker image_name test_name
|
||||
|
||||
# Example community.general.ini_file module on fedora40 Docker image:
|
||||
ansible-test integration -v --docker fedora40 ini_file
|
||||
```
|
||||
|
||||
#### Without isolation
|
||||
|
||||
```.bash
|
||||
# Run integration tests for the flattened lookup **without any isolation**:
|
||||
ansible-test integration -v lookup_flattened
|
||||
```
|
||||
@@ -146,3 +121,19 @@ Creating new modules and plugins requires a bit more work than other Pull Reques
|
||||
listed as `maintainers` will be pinged for new issues and PRs that modify the module/plugin or its tests.
|
||||
|
||||
When you add a new plugin/module, we expect that you perform maintainer duty for at least some time after contributing it.
|
||||
|
||||
## pre-commit
|
||||
|
||||
To help ensure high-quality contributions this repository includes a [pre-commit](https://pre-commit.com) configuration which
|
||||
corrects and tests against common issues that would otherwise cause CI to fail. To begin using these pre-commit hooks see
|
||||
the [Installation](#installation) section below.
|
||||
|
||||
This is optional and not required to contribute to this repository.
|
||||
|
||||
### Installation
|
||||
|
||||
Follow the [instructions](https://pre-commit.com/#install) provided with pre-commit and run `pre-commit install` under the repository base. If for any reason you would like to disable the pre-commit hooks run `pre-commit uninstall`.
|
||||
|
||||
This is optional to run it locally.
|
||||
|
||||
You can trigger it locally with `pre-commit run --all-files` or even to run only for a given file `pre-commit run --files YOUR_FILE`.
|
||||
|
||||
56
README.md
56
README.md
@@ -6,11 +6,9 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Community General Collection
|
||||
|
||||
[](https://docs.ansible.com/ansible/devel/collections/community/general/)
|
||||
[](https://dev.azure.com/ansible/community.general/_build?definitionId=31)
|
||||
[](https://github.com/ansible-collections/community.general/actions)
|
||||
[](https://dev.azure.com/ansible/community.general/_build?definitionId=31)
|
||||
[](https://github.com/ansible-collections/community.general/actions)
|
||||
[](https://codecov.io/gh/ansible-collections/community.general)
|
||||
[](https://api.reuse.software/info/github.com/ansible-collections/community.general)
|
||||
|
||||
This repository contains the `community.general` Ansible Collection. The collection is a part of the Ansible package and includes many modules and plugins supported by Ansible community which are not part of more specialized community collections.
|
||||
|
||||
@@ -24,21 +22,11 @@ We follow [Ansible Code of Conduct](https://docs.ansible.com/ansible/latest/comm
|
||||
|
||||
If you encounter abusive behavior violating the [Ansible Code of Conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html), please refer to the [policy violations](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html#policy-violations) section of the Code of Conduct for information on how to raise a complaint.
|
||||
|
||||
## Communication
|
||||
|
||||
* Join the Ansible forum:
|
||||
* [Get Help](https://forum.ansible.com/c/help/6): get help or help others. This is for questions about modules or plugins in the collection. Please add appropriate tags if you start new discussions.
|
||||
* [Tag `community-general`](https://forum.ansible.com/tag/community-general): discuss the *collection itself*, instead of specific modules or plugins.
|
||||
* [Social Spaces](https://forum.ansible.com/c/chat/4): gather and interact with fellow enthusiasts.
|
||||
* [News & Announcements](https://forum.ansible.com/c/news/5): track project-wide announcements including social events.
|
||||
|
||||
* The Ansible [Bullhorn newsletter](https://docs.ansible.com/ansible/devel/community/communication.html#the-bullhorn): used to announce releases and important changes.
|
||||
|
||||
For more information about communication, see the [Ansible communication guide](https://docs.ansible.com/ansible/devel/community/communication.html).
|
||||
|
||||
## Tested with Ansible
|
||||
|
||||
Tested with the current ansible-core 2.13, ansible-core 2.14, ansible-core 2.15, ansible-core 2.16, ansible-core 2.17, and ansible-core 2.18 releases of ansible-core. Ansible-core versions before 2.13.0 are not supported. This includes all ansible-base 2.10 and Ansible 2.9 releases.
|
||||
Tested with the current ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, ansible-core 2.14 releases and the current development version of ansible-core. Ansible-core versions before 2.11.0 are not supported. This includes all ansible-base 2.10 and Ansible 2.9 releases.
|
||||
|
||||
Parts of this collection will not work with ansible-core 2.11 on Python 3.12+.
|
||||
|
||||
## External requirements
|
||||
|
||||
@@ -46,13 +34,13 @@ Some modules and plugins require external libraries. Please check the requiremen
|
||||
|
||||
## Included content
|
||||
|
||||
Please check the included content on the [Ansible Galaxy page for this collection](https://galaxy.ansible.com/ui/repo/published/community/general/) or the [documentation on the Ansible docs site](https://docs.ansible.com/ansible/latest/collections/community/general/).
|
||||
Please check the included content on the [Ansible Galaxy page for this collection](https://galaxy.ansible.com/community/general) or the [documentation on the Ansible docs site](https://docs.ansible.com/ansible/latest/collections/community/general/).
|
||||
|
||||
## Using this collection
|
||||
|
||||
This collection is shipped with the Ansible package. So if you have it installed, no more action is required.
|
||||
|
||||
If you have a minimal installation (only Ansible Core installed) or you want to use the latest version of the collection along with the whole Ansible package, you need to install the collection from [Ansible Galaxy](https://galaxy.ansible.com/ui/repo/published/community/general/) manually with the `ansible-galaxy` command-line tool:
|
||||
If you have a minimal installation (only Ansible Core installed) or you want to use the latest version of the collection along with the whole Ansible package, you need to install the collection from [Ansible Galaxy](https://galaxy.ansible.com/community/general) manually with the `ansible-galaxy` command-line tool:
|
||||
|
||||
ansible-galaxy collection install community.general
|
||||
|
||||
@@ -69,7 +57,7 @@ Note that if you install the collection manually, it will not be upgraded automa
|
||||
ansible-galaxy collection install community.general --upgrade
|
||||
```
|
||||
|
||||
You can also install a specific version of the collection, for example, if you need to downgrade when something is broken in the latest version (please report an issue in this repository). Use the following syntax where `X.Y.Z` can be any [available version](https://galaxy.ansible.com/ui/repo/published/community/general/):
|
||||
You can also install a specific version of the collection, for example, if you need to downgrade when something is broken in the latest version (please report an issue in this repository). Use the following syntax where `X.Y.Z` can be any [available version](https://galaxy.ansible.com/community/general):
|
||||
|
||||
```bash
|
||||
ansible-galaxy collection install community.general:==X.Y.Z
|
||||
@@ -85,13 +73,13 @@ We are actively accepting new contributors.
|
||||
|
||||
All types of contributions are very welcome.
|
||||
|
||||
You don't know how to start? Refer to our [contribution guide](https://github.com/ansible-collections/community.general/blob/main/CONTRIBUTING.md)!
|
||||
You don't know how to start? Refer to our [contribution guide](https://github.com/ansible-collections/community.general/blob/stable-7/CONTRIBUTING.md)!
|
||||
|
||||
The current maintainers are listed in the [commit-rights.md](https://github.com/ansible-collections/community.general/blob/main/commit-rights.md#people) file. If you have questions or need help, feel free to mention them in the proposals.
|
||||
The current maintainers are listed in the [commit-rights.md](https://github.com/ansible-collections/community.general/blob/stable-7/commit-rights.md#people) file. If you have questions or need help, feel free to mention them in the proposals.
|
||||
|
||||
You can find more information in the [developer guide for collections](https://docs.ansible.com/ansible/devel/dev_guide/developing_collections.html#contributing-to-collections), and in the [Ansible Community Guide](https://docs.ansible.com/ansible/latest/community/index.html).
|
||||
|
||||
Also for some notes specific to this collection see [our CONTRIBUTING documentation](https://github.com/ansible-collections/community.general/blob/main/CONTRIBUTING.md).
|
||||
Also for some notes specific to this collection see [our CONTRIBUTING documentation](https://github.com/ansible-collections/community.general/blob/stable-7/CONTRIBUTING.md).
|
||||
|
||||
### Running tests
|
||||
|
||||
@@ -101,7 +89,7 @@ See [here](https://docs.ansible.com/ansible/devel/dev_guide/developing_collectio
|
||||
|
||||
To learn how to maintain / become a maintainer of this collection, refer to:
|
||||
|
||||
* [Committer guidelines](https://github.com/ansible-collections/community.general/blob/main/commit-rights.md).
|
||||
* [Committer guidelines](https://github.com/ansible-collections/community.general/blob/stable-7/commit-rights.md).
|
||||
* [Maintainer guidelines](https://github.com/ansible/community-docs/blob/main/maintaining.rst).
|
||||
|
||||
It is necessary for maintainers of this collection to be subscribed to:
|
||||
@@ -111,13 +99,25 @@ It is necessary for maintainers of this collection to be subscribed to:
|
||||
|
||||
They also should be subscribed to Ansible's [The Bullhorn newsletter](https://docs.ansible.com/ansible/devel/community/communication.html#the-bullhorn).
|
||||
|
||||
## Communication
|
||||
|
||||
We announce important development changes and releases through Ansible's [The Bullhorn newsletter](https://eepurl.com/gZmiEP). If you are a collection developer, be sure you are subscribed.
|
||||
|
||||
Join us in the `#ansible` (general use questions and support), `#ansible-community` (community and collection development questions), and other [IRC channels](https://docs.ansible.com/ansible/devel/community/communication.html#irc-channels) on [Libera.chat](https://libera.chat).
|
||||
|
||||
We take part in the global quarterly [Ansible Contributor Summit](https://github.com/ansible/community/wiki/Contributor-Summit) virtually or in-person. Track [The Bullhorn newsletter](https://eepurl.com/gZmiEP) and join us.
|
||||
|
||||
For more information about communities, meetings and agendas see [Community Wiki](https://github.com/ansible/community/wiki/Community).
|
||||
|
||||
For more information about communication, refer to Ansible's the [Communication guide](https://docs.ansible.com/ansible/devel/community/communication.html).
|
||||
|
||||
## Publishing New Version
|
||||
|
||||
See the [Releasing guidelines](https://github.com/ansible/community-docs/blob/main/releasing_collections.rst) to learn how to release this collection.
|
||||
|
||||
## Release notes
|
||||
|
||||
See the [changelog](https://github.com/ansible-collections/community.general/blob/stable-8/CHANGELOG.md).
|
||||
See the [changelog](https://github.com/ansible-collections/community.general/blob/stable-7/CHANGELOG.rst).
|
||||
|
||||
## Roadmap
|
||||
|
||||
@@ -136,8 +136,8 @@ See [this issue](https://github.com/ansible-collections/community.general/issues
|
||||
|
||||
This collection is primarily licensed and distributed as a whole under the GNU General Public License v3.0 or later.
|
||||
|
||||
See [LICENSES/GPL-3.0-or-later.txt](https://github.com/ansible-collections/community.general/blob/main/COPYING) for the full text.
|
||||
See [LICENSES/GPL-3.0-or-later.txt](https://github.com/ansible-collections/community.general/blob/stable-7/COPYING) for the full text.
|
||||
|
||||
Parts of the collection are licensed under the [BSD 2-Clause license](https://github.com/ansible-collections/community.general/blob/main/LICENSES/BSD-2-Clause.txt), the [MIT license](https://github.com/ansible-collections/community.general/blob/main/LICENSES/MIT.txt), and the [PSF 2.0 license](https://github.com/ansible-collections/community.general/blob/main/LICENSES/PSF-2.0.txt).
|
||||
Parts of the collection are licensed under the [BSD 2-Clause license](https://github.com/ansible-collections/community.general/blob/stable-7/LICENSES/BSD-2-Clause.txt), the [MIT license](https://github.com/ansible-collections/community.general/blob/stable-7/LICENSES/MIT.txt), and the [PSF 2.0 license](https://github.com/ansible-collections/community.general/blob/stable-7/LICENSES/PSF-2.0.txt).
|
||||
|
||||
All files have a machine readable `SDPX-License-Identifier:` comment denoting its respective license(s) or an equivalent entry in an accompanying `.license` file. Only changelog fragments (which will not be part of a release) are covered by a blanket statement in `REUSE.toml`. This conforms to the [REUSE specification](https://reuse.software/spec/).
|
||||
All files have a machine readable `SDPX-License-Identifier:` comment denoting its respective license(s) or an equivalent entry in an accompanying `.license` file. Only changelog fragments (which will not be part of a release) are covered by a blanket statement in `.reuse/dep5`. This conforms to the [REUSE specification](https://reuse.software/spec/).
|
||||
|
||||
11
REUSE.toml
11
REUSE.toml
@@ -1,11 +0,0 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
version = 1
|
||||
|
||||
[[annotations]]
|
||||
path = "changelogs/fragments/**"
|
||||
precedence = "aggregate"
|
||||
SPDX-FileCopyrightText = "Ansible Project"
|
||||
SPDX-License-Identifier = "GPL-3.0-or-later"
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,31 +12,23 @@ mention_ancestor: true
|
||||
flatmap: true
|
||||
new_plugins_after_name: removed_features
|
||||
notesdir: fragments
|
||||
output_formats:
|
||||
- md
|
||||
- rst
|
||||
prelude_section_name: release_summary
|
||||
prelude_section_title: Release Summary
|
||||
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
|
||||
- - 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
|
||||
title: Community General
|
||||
trivial_section_name: trivial
|
||||
use_fqcn: true
|
||||
add_plugin_period: true
|
||||
changelog_nice_yaml: true
|
||||
changelog_sort: version
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
changelog:
|
||||
write_changelog: true
|
||||
@@ -8,9 +8,3 @@ sections:
|
||||
toctree:
|
||||
- filter_guide
|
||||
- test_guide
|
||||
- title: Cloud Guides
|
||||
toctree:
|
||||
- guide_alicloud
|
||||
- guide_online
|
||||
- guide_packet
|
||||
- guide_scaleway
|
||||
|
||||
@@ -2,11 +2,17 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
list1:
|
||||
- {name: foo, extra: true}
|
||||
- {name: bar, extra: false}
|
||||
- {name: meh, extra: true}
|
||||
- name: foo
|
||||
extra: true
|
||||
- name: bar
|
||||
extra: false
|
||||
- name: meh
|
||||
extra: true
|
||||
|
||||
list2:
|
||||
- {name: foo, path: /foo}
|
||||
- {name: baz, path: /baz}
|
||||
- name: foo
|
||||
path: /foo
|
||||
- name: baz
|
||||
path: /baz
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
list1:
|
||||
- name: myname01
|
||||
param01:
|
||||
x: default_value
|
||||
y: default_value
|
||||
list: [default_value]
|
||||
list:
|
||||
- default_value
|
||||
- name: myname02
|
||||
param01: [1, 1, 2, 3]
|
||||
|
||||
@@ -16,6 +18,7 @@ list2:
|
||||
param01:
|
||||
y: patch_value
|
||||
z: patch_value
|
||||
list: [patch_value]
|
||||
list:
|
||||
- patch_value
|
||||
- name: myname02
|
||||
param01: [3, 4, 4]
|
||||
param01: [3, 4, 4, {key: value}]
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
dir: example-001_vars
|
||||
- debug:
|
||||
var: list3
|
||||
when: debug | d(false) | bool
|
||||
when: debug|d(false)|bool
|
||||
- template:
|
||||
src: list3.out.j2
|
||||
dest: example-001.out
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
list3: "{{ list1 |
|
||||
|
||||
list3: "{{ list1|
|
||||
community.general.lists_mergeby(list2, 'name') }}"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
dir: example-002_vars
|
||||
- debug:
|
||||
var: list3
|
||||
when: debug | d(false) | bool
|
||||
when: debug|d(false)|bool
|
||||
- template:
|
||||
src: list3.out.j2
|
||||
dest: example-002.out
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
list3: "{{ [list1, list2] |
|
||||
|
||||
list3: "{{ [list1, list2]|
|
||||
community.general.lists_mergeby('name') }}"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
dir: example-003_vars
|
||||
- debug:
|
||||
var: list3
|
||||
when: debug | d(false) | bool
|
||||
when: debug|d(false)|bool
|
||||
- template:
|
||||
src: list3.out.j2
|
||||
dest: example-003.out
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
list3: "{{ [list1, list2] |
|
||||
|
||||
list3: "{{ [list1, list2]|
|
||||
community.general.lists_mergeby('name',
|
||||
recursive=true) }}"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
dir: example-004_vars
|
||||
- debug:
|
||||
var: list3
|
||||
when: debug | d(false) | bool
|
||||
when: debug|d(false)|bool
|
||||
- template:
|
||||
src: list3.out.j2
|
||||
dest: example-004.out
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
list3: "{{ [list1, list2] |
|
||||
|
||||
list3: "{{ [list1, list2]|
|
||||
community.general.lists_mergeby('name',
|
||||
recursive=true,
|
||||
list_merge='keep') }}"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
dir: example-005_vars
|
||||
- debug:
|
||||
var: list3
|
||||
when: debug | d(false) | bool
|
||||
when: debug|d(false)|bool
|
||||
- template:
|
||||
src: list3.out.j2
|
||||
dest: example-005.out
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
list3: "{{ [list1, list2] |
|
||||
|
||||
list3: "{{ [list1, list2]|
|
||||
community.general.lists_mergeby('name',
|
||||
recursive=true,
|
||||
list_merge='append') }}"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
dir: example-006_vars
|
||||
- debug:
|
||||
var: list3
|
||||
when: debug | d(false) | bool
|
||||
when: debug|d(false)|bool
|
||||
- template:
|
||||
src: list3.out.j2
|
||||
dest: example-006.out
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
list3: "{{ [list1, list2] |
|
||||
|
||||
list3: "{{ [list1, list2]|
|
||||
community.general.lists_mergeby('name',
|
||||
recursive=true,
|
||||
list_merge='prepend') }}"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
dir: example-007_vars
|
||||
- debug:
|
||||
var: list3
|
||||
when: debug|d(false) | bool
|
||||
when: debug|d(false)|bool
|
||||
- template:
|
||||
src: list3.out.j2
|
||||
dest: example-007.out
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
list3: "{{ [list1, list2] |
|
||||
|
||||
list3: "{{ [list1, list2]|
|
||||
community.general.lists_mergeby('name',
|
||||
recursive=true,
|
||||
list_merge='append_rp') }}"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
dir: example-008_vars
|
||||
- debug:
|
||||
var: list3
|
||||
when: debug | d(false) | bool
|
||||
when: debug|d(false)|bool
|
||||
- template:
|
||||
src: list3.out.j2
|
||||
dest: example-008.out
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
list3: "{{ [list1, list2] |
|
||||
|
||||
list3: "{{ [list1, list2]|
|
||||
community.general.lists_mergeby('name',
|
||||
recursive=true,
|
||||
list_merge='prepend_rp') }}"
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: 9. Merge single list by common attribute 'name'
|
||||
include_vars:
|
||||
dir: example-009_vars
|
||||
- debug:
|
||||
var: list3
|
||||
when: debug | d(false) | bool
|
||||
- template:
|
||||
src: list3.out.j2
|
||||
dest: example-009.out
|
||||
@@ -1 +0,0 @@
|
||||
../default-common.yml
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
list3: "{{ [list1 + list2, []] |
|
||||
community.general.lists_mergeby('name') }}"
|
||||
@@ -4,75 +4,51 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
examples:
|
||||
- title: Two lists
|
||||
description: 'In the example below the lists are merged by the attribute ``name``:'
|
||||
- label: 'In the example below the lists are merged by the attribute ``name``:'
|
||||
file: example-001_vars/list3.yml
|
||||
lang: 'yaml+jinja'
|
||||
- title:
|
||||
description: 'This produces:'
|
||||
- label: 'This produces:'
|
||||
file: example-001.out
|
||||
lang: 'yaml'
|
||||
- title: List of two lists
|
||||
description: 'It is possible to use a list of lists as an input of the filter:'
|
||||
- label: 'It is possible to use a list of lists as an input of the filter:'
|
||||
file: example-002_vars/list3.yml
|
||||
lang: 'yaml+jinja'
|
||||
- title:
|
||||
description: 'This produces the same result as in the previous example:'
|
||||
- label: 'This produces the same result as in the previous example:'
|
||||
file: example-002.out
|
||||
lang: 'yaml'
|
||||
- title: Single list
|
||||
description: 'It is possible to merge single list:'
|
||||
file: example-009_vars/list3.yml
|
||||
lang: 'yaml+jinja'
|
||||
- title:
|
||||
description: 'This produces the same result as in the previous example:'
|
||||
file: example-009.out
|
||||
lang: 'yaml'
|
||||
- title: list_merge=replace (default)
|
||||
description: 'Example :ansopt:`community.general.lists_mergeby#filter:list_merge=replace` (default):'
|
||||
- label: 'Example ``list_merge=replace`` (default):'
|
||||
file: example-003_vars/list3.yml
|
||||
lang: 'yaml+jinja'
|
||||
- title:
|
||||
description: 'This produces:'
|
||||
- label: 'This produces:'
|
||||
file: example-003.out
|
||||
lang: 'yaml'
|
||||
- title: list_merge=keep
|
||||
description: 'Example :ansopt:`community.general.lists_mergeby#filter:list_merge=keep`:'
|
||||
- label: 'Example ``list_merge=keep``:'
|
||||
file: example-004_vars/list3.yml
|
||||
lang: 'yaml+jinja'
|
||||
- title:
|
||||
description: 'This produces:'
|
||||
- label: 'This produces:'
|
||||
file: example-004.out
|
||||
lang: 'yaml'
|
||||
- title: list_merge=append
|
||||
description: 'Example :ansopt:`community.general.lists_mergeby#filter:list_merge=append`:'
|
||||
- label: 'Example ``list_merge=append``:'
|
||||
file: example-005_vars/list3.yml
|
||||
lang: 'yaml+jinja'
|
||||
- title:
|
||||
description: 'This produces:'
|
||||
- label: 'This produces:'
|
||||
file: example-005.out
|
||||
lang: 'yaml'
|
||||
- title: list_merge=prepend
|
||||
description: 'Example :ansopt:`community.general.lists_mergeby#filter:list_merge=prepend`:'
|
||||
- label: 'Example ``list_merge=prepend``:'
|
||||
file: example-006_vars/list3.yml
|
||||
lang: 'yaml+jinja'
|
||||
- title:
|
||||
description: 'This produces:'
|
||||
- label: 'This produces:'
|
||||
file: example-006.out
|
||||
lang: 'yaml'
|
||||
- title: list_merge=append_rp
|
||||
description: 'Example :ansopt:`community.general.lists_mergeby#filter:list_merge=append_rp`:'
|
||||
- label: 'Example ``list_merge=append_rp``:'
|
||||
file: example-007_vars/list3.yml
|
||||
lang: 'yaml+jinja'
|
||||
- title:
|
||||
description: 'This produces:'
|
||||
- label: 'This produces:'
|
||||
file: example-007.out
|
||||
lang: 'yaml'
|
||||
- title: list_merge=prepend_rp
|
||||
description: 'Example :ansopt:`community.general.lists_mergeby#filter:list_merge=prepend_rp`:'
|
||||
- label: 'Example ``list_merge=prepend_rp``:'
|
||||
file: example-008_vars/list3.yml
|
||||
lang: 'yaml+jinja'
|
||||
- title:
|
||||
description: 'This produces:'
|
||||
- label: 'This produces:'
|
||||
file: example-008.out
|
||||
lang: 'yaml'
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
{% for i in examples %}
|
||||
{{ i.description }}
|
||||
{{ i.label }}
|
||||
|
||||
.. code-block:: {{ i.lang }}
|
||||
|
||||
{{ lookup('file', i.file) | split('\n') | reject('match', '^(#|---)') | join ('\n') | indent(2) }}
|
||||
{{ lookup('file', i.file)|indent(2) }}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
examples_one: true
|
||||
examples_all: true
|
||||
merging_lists_of_dictionaries: true
|
||||
@@ -6,69 +6,57 @@
|
||||
Merging lists of dictionaries
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you have two or more lists of dictionaries and want to combine them into a list of merged dictionaries, where the dictionaries are merged by an attribute, you can use the :ansplugin:`community.general.lists_mergeby <community.general.lists_mergeby#filter>` filter.
|
||||
If you have two or more lists of dictionaries and want to combine them into a list of merged dictionaries, where the dictionaries are merged by an attribute, you can use the ``lists_mergeby`` filter.
|
||||
|
||||
.. note:: The output of the examples in this section use the YAML callback plugin. Quoting: "Ansible output that can be quite a bit easier to read than the default JSON formatting." See the documentation for the :ansplugin:`community.general.yaml callback plugin <community.general.yaml#callback>`.
|
||||
.. note:: The output of the examples in this section use the YAML callback plugin. Quoting: "Ansible output that can be quite a bit easier to read than the default JSON formatting." See :ref:`the documentation for the community.general.yaml callback plugin <ansible_collections.community.general.yaml_callback>`.
|
||||
|
||||
Let us use the lists below in the following examples:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
{{ lookup('file', 'default-common.yml') | split('\n') | reject('match', '^(#|---)') | join ('\n') | indent(2) }}
|
||||
{{ lookup('file', 'default-common.yml')|indent(2) }}
|
||||
|
||||
{% for i in examples[0:2] %}
|
||||
{% if i.title | d('', true) | length > 0 %}
|
||||
{{ i.title }}
|
||||
{{ "%s" % ('"' * i.title|length) }}
|
||||
{% endif %}
|
||||
{{ i.description }}
|
||||
{{ i.label }}
|
||||
|
||||
.. code-block:: {{ i.lang }}
|
||||
|
||||
{{ lookup('file', i.file) | split('\n') | reject('match', '^(#|---)') | join ('\n') | indent(2) }}
|
||||
{{ lookup('file', i.file)|indent(2) }}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
.. versionadded:: 2.0.0
|
||||
|
||||
{% for i in examples[2:6] %}
|
||||
{% if i.title | d('', true) | length > 0 %}
|
||||
{{ i.title }}
|
||||
{{ "%s" % ('"' * i.title|length) }}
|
||||
{% endif %}
|
||||
{{ i.description }}
|
||||
{% for i in examples[2:4] %}
|
||||
{{ i.label }}
|
||||
|
||||
.. code-block:: {{ i.lang }}
|
||||
|
||||
{{ lookup('file', i.file) | split('\n') | reject('match', '^(#|---)') | join ('\n') | indent(2) }}
|
||||
{{ lookup('file', i.file)|indent(2) }}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
The filter also accepts two optional parameters: :ansopt:`community.general.lists_mergeby#filter:recursive` and :ansopt:`community.general.lists_mergeby#filter:list_merge`. This is available since community.general 4.4.0.
|
||||
The filter also accepts two optional parameters: ``recursive`` and ``list_merge``. These parameters are only supported when used with ansible-base 2.10 or ansible-core, but not with Ansible 2.9. This is available since community.general 4.4.0.
|
||||
|
||||
**recursive**
|
||||
Is a boolean, default to ``false``. Should the :ansplugin:`community.general.lists_mergeby#filter` filter recursively merge nested hashes. Note: It does not depend on the value of the ``hash_behaviour`` setting in ``ansible.cfg``.
|
||||
Is a boolean, default to ``False``. Should the ``community.general.lists_mergeby`` recursively merge nested hashes. Note: It does not depend on the value of the ``hash_behaviour`` setting in ``ansible.cfg``.
|
||||
|
||||
**list_merge**
|
||||
Is a string, its possible values are :ansval:`replace` (default), :ansval:`keep`, :ansval:`append`, :ansval:`prepend`, :ansval:`append_rp` or :ansval:`prepend_rp`. It modifies the behaviour of :ansplugin:`community.general.lists_mergeby#filter` when the hashes to merge contain arrays/lists.
|
||||
Is a string, its possible values are ``replace`` (default), ``keep``, ``append``, ``prepend``, ``append_rp`` or ``prepend_rp``. It modifies the behaviour of ``community.general.lists_mergeby`` when the hashes to merge contain arrays/lists.
|
||||
|
||||
The examples below set :ansopt:`community.general.lists_mergeby#filter:recursive=true` and display the differences among all six options of :ansopt:`community.general.lists_mergeby#filter:list_merge`. Functionality of the parameters is exactly the same as in the filter :ansplugin:`ansible.builtin.combine#filter`. See :ref:`Combining hashes/dictionaries <combine_filter>` to learn details about these options.
|
||||
The examples below set ``recursive=true`` and display the differences among all six options of ``list_merge``. Functionality of the parameters is exactly the same as in the filter ``combine``. See :ref:`Combining hashes/dictionaries <combine_filter>` to learn details about these options.
|
||||
|
||||
Let us use the lists below in the following examples
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
{{ lookup('file', 'default-recursive-true.yml') | split('\n') | reject('match', '^(#|---)') | join ('\n') |indent(2) }}
|
||||
{{ lookup('file', 'default-recursive-true.yml')|indent(2) }}
|
||||
|
||||
{% for i in examples[6:] %}
|
||||
{% if i.title | d('', true) | length > 0 %}
|
||||
{{ i.title }}
|
||||
{{ "%s" % ('"' * i.title|length) }}
|
||||
{% endif %}
|
||||
{{ i.description }}
|
||||
{% for i in examples[4:16] %}
|
||||
{{ i.label }}
|
||||
|
||||
.. code-block:: {{ i.lang }}
|
||||
|
||||
{{ lookup('file', i.file) | split('\n') | reject('match', '^(#|---)') | join ('\n') |indent(2) }}
|
||||
{{ lookup('file', i.file)|indent(2) }}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
@@ -4,4 +4,4 @@ GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://w
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#}
|
||||
list3:
|
||||
{{ list3 | to_yaml(indent=2, sort_keys=false) | indent(2) }}
|
||||
{{ list3|to_nice_yaml(indent=0) }}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# 1) Run all examples and create example-XXX.out
|
||||
# shell> ansible-playbook playbook.yml -e examples_one=true
|
||||
# shell> ansible-playbook playbook.yml -e examples=true
|
||||
#
|
||||
# 2) Optionally, for testing, create examples_all.rst
|
||||
# shell> ansible-playbook playbook.yml -e examples_all=true
|
||||
@@ -45,20 +45,18 @@
|
||||
tags: t007
|
||||
- import_tasks: example-008.yml
|
||||
tags: t008
|
||||
- import_tasks: example-009.yml
|
||||
tags: t009
|
||||
when: examples_one | d(false) | bool
|
||||
when: examples|d(false)|bool
|
||||
|
||||
- block:
|
||||
- include_vars: examples.yml
|
||||
- template:
|
||||
src: examples_all.rst.j2
|
||||
dest: examples_all.rst
|
||||
when: examples_all | d(false) | bool
|
||||
when: examples_all|d(false)|bool
|
||||
|
||||
- block:
|
||||
- include_vars: examples.yml
|
||||
- template:
|
||||
src: filter_guide_abstract_informations_merging_lists_of_dictionaries.rst.j2
|
||||
dest: filter_guide_abstract_informations_merging_lists_of_dictionaries.rst
|
||||
when: merging_lists_of_dictionaries | d(false) | bool
|
||||
when: merging_lists_of_dictionaries|d(false)|bool
|
||||
|
||||
@@ -9,8 +9,6 @@ edit_on_github:
|
||||
path_prefix: ''
|
||||
|
||||
extra_links:
|
||||
- description: Ask for help
|
||||
url: https://forum.ansible.com/c/help/6/none
|
||||
- description: Submit a bug report
|
||||
url: https://github.com/ansible-collections/community.general/issues/new?assignees=&labels=&template=bug_report.yml
|
||||
- description: Request a feature
|
||||
@@ -24,10 +22,6 @@ communication:
|
||||
- topic: General usage and support questions
|
||||
network: Libera
|
||||
channel: '#ansible'
|
||||
forums:
|
||||
- topic: "Ansible Forum: General usage and support questions"
|
||||
# The following URL directly points to the "Get Help" section
|
||||
url: https://forum.ansible.com/c/help/6/none
|
||||
- topic: "Ansible Forum: Discussions about the collection itself, not for specific modules or plugins"
|
||||
# The following URL directly points to the "community-general" tag
|
||||
url: https://forum.ansible.com/tag/community-general
|
||||
mailing_lists:
|
||||
- topic: Ansible Project List
|
||||
url: https://groups.google.com/g/ansible-project
|
||||
|
||||
@@ -12,5 +12,4 @@ Abstract transformations
|
||||
filter_guide_abstract_informations_dictionaries
|
||||
filter_guide_abstract_informations_grouping
|
||||
filter_guide_abstract_informations_merging_lists_of_dictionaries
|
||||
filter_guide_abstract_informations_lists_helper
|
||||
filter_guide_abstract_informations_counting_elements_in_sequence
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
Counting elements in a sequence
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The :ansplugin:`community.general.counter filter plugin <community.general.counter#filter>` allows you to count (hashable) elements in a sequence. Elements are returned as dictionary keys and their counts are stored as dictionary values.
|
||||
The ``community.general.counter`` filter plugin allows you to count (hashable) elements in a sequence. Elements are returned as dictionary keys and their counts are stored as dictionary values.
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
Dictionaries
|
||||
^^^^^^^^^^^^
|
||||
|
||||
You can use the :ansplugin:`community.general.dict_kv filter <community.general.dict_kv#filter>` to create a single-entry dictionary with ``value | community.general.dict_kv(key)``:
|
||||
You can use the ``dict_kv`` filter to create a single-entry dictionary with ``value | community.general.dict_kv(key)``:
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
@@ -58,7 +58,7 @@ This produces:
|
||||
|
||||
.. versionadded:: 2.0.0
|
||||
|
||||
If you need to convert a list of key-value pairs to a dictionary, you can use the ``dict`` function. Unfortunately, this function cannot be used with ``map``. For this, the :ansplugin:`community.general.dict filter <community.general.dict#filter>` can be used:
|
||||
If you need to convert a list of key-value pairs to a dictionary, you can use the ``dict`` function. Unfortunately, this function cannot be used with ``map``. For this, the ``community.general.dict`` filter can be used:
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
Grouping
|
||||
^^^^^^^^
|
||||
|
||||
If you have a list of dictionaries, the Jinja2 ``groupby`` filter allows to group the list by an attribute. This results in a list of ``(grouper, list)`` namedtuples, where ``list`` contains all dictionaries where the selected attribute equals ``grouper``. If you know that for every ``grouper``, there will be a most one entry in that list, you can use the :ansplugin:`community.general.groupby_as_dict filter <community.general.groupby_as_dict#filter>` to convert the original list into a dictionary which maps ``grouper`` to the corresponding dictionary.
|
||||
If you have a list of dictionaries, the Jinja2 ``groupby`` filter allows to group the list by an attribute. This results in a list of ``(grouper, list)`` namedtuples, where ``list`` contains all dictionaries where the selected attribute equals ``grouper``. If you know that for every ``grouper``, there will be a most one entry in that list, you can use the ``community.general.groupby_as_dict`` filter to convert the original list into a dictionary which maps ``grouper`` to the corresponding dictionary.
|
||||
|
||||
One example is ``ansible_facts.mounts``, which is a list of dictionaries where each has one ``device`` element to indicate the device which is mounted. Therefore, ``ansible_facts.mounts | community.general.groupby_as_dict('device')`` is a dictionary mapping a device to the mount information:
|
||||
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
..
|
||||
Copyright (c) Ansible Project
|
||||
GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
Union, intersection and difference of lists
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Starting with Ansible Core 2.16, the builtin filters :ansplugin:`ansible.builtin.union#filter`, :ansplugin:`ansible.builtin.intersect#filter`, :ansplugin:`ansible.builtin.difference#filter` and :ansplugin:`ansible.builtin.symmetric_difference#filter` began to behave differently and do no longer preserve the item order. Items in the resulting lists are returned in arbitrary order and the order can vary between subsequent runs.
|
||||
|
||||
The Ansible community.general collection provides the following additional list filters:
|
||||
|
||||
- :ansplugin:`community.general.lists_union#filter`
|
||||
- :ansplugin:`community.general.lists_intersect#filter`
|
||||
- :ansplugin:`community.general.lists_difference#filter`
|
||||
- :ansplugin:`community.general.lists_symmetric_difference#filter`
|
||||
|
||||
These filters preserve the item order, eliminate duplicates and are an extended version of the builtin ones, because they can operate on more than two lists.
|
||||
|
||||
.. note:: Stick to the builtin filters, when item order is not important or when you do not need the n-ary operating mode. The builtin filters are faster, because they rely mostly on sets as their underlying datastructure.
|
||||
|
||||
Let us use the lists below in the following examples:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
A: [9, 5, 7, 1, 9, 4, 10, 5, 9, 7]
|
||||
B: [4, 1, 2, 8, 3, 1, 7]
|
||||
C: [10, 2, 1, 9, 1]
|
||||
|
||||
The union of ``A`` and ``B`` can be written as:
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
result: "{{ A | community.general.lists_union(B) }}"
|
||||
|
||||
This statement produces:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
result: [9, 5, 7, 1, 4, 10, 2, 8, 3]
|
||||
|
||||
If you want to calculate the intersection of ``A``, ``B`` and ``C``, you can use the following statement:
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
result: "{{ A | community.general.lists_intersect(B, C) }}"
|
||||
|
||||
Alternatively, you can use a list of lists as an input of the filter
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
result: "{{ [A, B] | community.general.lists_intersect(C) }}"
|
||||
|
||||
or
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
result: "{{ [A, B, C] | community.general.lists_intersect(flatten=true) }}"
|
||||
|
||||
All three statements are equivalent and give:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
result: [1]
|
||||
|
||||
.. note:: Be aware that in most cases, filter calls without any argument require ``flatten=true``, otherwise the input is returned as result. The reason for this is, that the input is considered as a variable argument and is wrapped by an additional outer list. ``flatten=true`` ensures that this list is removed before the input is processed by the filter logic.
|
||||
|
||||
The filters :ansplugin:`community.general.lists_difference#filter` or :ansplugin:`community.general.lists_symmetric_difference#filter` can be used in the same way as the filters in the examples above. They calculate the difference or the symmetric difference between two or more lists and preserve the item order.
|
||||
|
||||
For example, the symmetric difference of ``A``, ``B`` and ``C`` may be written as:
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
result: "{{ A | community.general.lists_symmetric_difference(B, C) }}"
|
||||
|
||||
This gives:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
result: [5, 8, 3, 1]
|
||||
|
||||
@@ -6,30 +6,33 @@
|
||||
Merging lists of dictionaries
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you have two or more lists of dictionaries and want to combine them into a list of merged dictionaries, where the dictionaries are merged by an attribute, you can use the :ansplugin:`community.general.lists_mergeby <community.general.lists_mergeby#filter>` filter.
|
||||
If you have two or more lists of dictionaries and want to combine them into a list of merged dictionaries, where the dictionaries are merged by an attribute, you can use the ``lists_mergeby`` filter.
|
||||
|
||||
.. note:: The output of the examples in this section use the YAML callback plugin. Quoting: "Ansible output that can be quite a bit easier to read than the default JSON formatting." See the documentation for the :ansplugin:`community.general.yaml callback plugin <community.general.yaml#callback>`.
|
||||
.. note:: The output of the examples in this section use the YAML callback plugin. Quoting: "Ansible output that can be quite a bit easier to read than the default JSON formatting." See :ref:`the documentation for the community.general.yaml callback plugin <ansible_collections.community.general.yaml_callback>`.
|
||||
|
||||
Let us use the lists below in the following examples:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
list1:
|
||||
- {name: foo, extra: true}
|
||||
- {name: bar, extra: false}
|
||||
- {name: meh, extra: true}
|
||||
- name: foo
|
||||
extra: true
|
||||
- name: bar
|
||||
extra: false
|
||||
- name: meh
|
||||
extra: true
|
||||
|
||||
list2:
|
||||
- {name: foo, path: /foo}
|
||||
- {name: baz, path: /baz}
|
||||
- name: foo
|
||||
path: /foo
|
||||
- name: baz
|
||||
path: /baz
|
||||
|
||||
Two lists
|
||||
"""""""""
|
||||
In the example below the lists are merged by the attribute ``name``:
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
list3: "{{ list1 |
|
||||
list3: "{{ list1|
|
||||
community.general.lists_mergeby(list2, 'name') }}"
|
||||
|
||||
This produces:
|
||||
@@ -37,21 +40,24 @@ This produces:
|
||||
.. code-block:: yaml
|
||||
|
||||
list3:
|
||||
- {name: bar, extra: false}
|
||||
- {name: baz, path: /baz}
|
||||
- {name: foo, extra: true, path: /foo}
|
||||
- {name: meh, extra: true}
|
||||
- extra: false
|
||||
name: bar
|
||||
- name: baz
|
||||
path: /baz
|
||||
- extra: true
|
||||
name: foo
|
||||
path: /foo
|
||||
- extra: true
|
||||
name: meh
|
||||
|
||||
|
||||
.. versionadded:: 2.0.0
|
||||
|
||||
List of two lists
|
||||
"""""""""""""""""
|
||||
It is possible to use a list of lists as an input of the filter:
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
list3: "{{ [list1, list2] |
|
||||
list3: "{{ [list1, list2]|
|
||||
community.general.lists_mergeby('name') }}"
|
||||
|
||||
This produces the same result as in the previous example:
|
||||
@@ -59,40 +65,26 @@ This produces the same result as in the previous example:
|
||||
.. code-block:: yaml
|
||||
|
||||
list3:
|
||||
- {name: bar, extra: false}
|
||||
- {name: baz, path: /baz}
|
||||
- {name: foo, extra: true, path: /foo}
|
||||
- {name: meh, extra: true}
|
||||
|
||||
Single list
|
||||
"""""""""""
|
||||
It is possible to merge single list:
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
list3: "{{ [list1 + list2, []] |
|
||||
community.general.lists_mergeby('name') }}"
|
||||
|
||||
This produces the same result as in the previous example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
list3:
|
||||
- {name: bar, extra: false}
|
||||
- {name: baz, path: /baz}
|
||||
- {name: foo, extra: true, path: /foo}
|
||||
- {name: meh, extra: true}
|
||||
- extra: false
|
||||
name: bar
|
||||
- name: baz
|
||||
path: /baz
|
||||
- extra: true
|
||||
name: foo
|
||||
path: /foo
|
||||
- extra: true
|
||||
name: meh
|
||||
|
||||
|
||||
The filter also accepts two optional parameters: :ansopt:`community.general.lists_mergeby#filter:recursive` and :ansopt:`community.general.lists_mergeby#filter:list_merge`. This is available since community.general 4.4.0.
|
||||
The filter also accepts two optional parameters: ``recursive`` and ``list_merge``. These parameters are only supported when used with ansible-base 2.10 or ansible-core, but not with Ansible 2.9. This is available since community.general 4.4.0.
|
||||
|
||||
**recursive**
|
||||
Is a boolean, default to ``false``. Should the :ansplugin:`community.general.lists_mergeby#filter` filter recursively merge nested hashes. Note: It does not depend on the value of the ``hash_behaviour`` setting in ``ansible.cfg``.
|
||||
Is a boolean, default to ``False``. Should the ``community.general.lists_mergeby`` recursively merge nested hashes. Note: It does not depend on the value of the ``hash_behaviour`` setting in ``ansible.cfg``.
|
||||
|
||||
**list_merge**
|
||||
Is a string, its possible values are :ansval:`replace` (default), :ansval:`keep`, :ansval:`append`, :ansval:`prepend`, :ansval:`append_rp` or :ansval:`prepend_rp`. It modifies the behaviour of :ansplugin:`community.general.lists_mergeby#filter` when the hashes to merge contain arrays/lists.
|
||||
Is a string, its possible values are ``replace`` (default), ``keep``, ``append``, ``prepend``, ``append_rp`` or ``prepend_rp``. It modifies the behaviour of ``community.general.lists_mergeby`` when the hashes to merge contain arrays/lists.
|
||||
|
||||
The examples below set :ansopt:`community.general.lists_mergeby#filter:recursive=true` and display the differences among all six options of :ansopt:`community.general.lists_mergeby#filter:list_merge`. Functionality of the parameters is exactly the same as in the filter :ansplugin:`ansible.builtin.combine#filter`. See :ref:`Combining hashes/dictionaries <combine_filter>` to learn details about these options.
|
||||
The examples below set ``recursive=true`` and display the differences among all six options of ``list_merge``. Functionality of the parameters is exactly the same as in the filter ``combine``. See :ref:`Combining hashes/dictionaries <combine_filter>` to learn details about these options.
|
||||
|
||||
Let us use the lists below in the following examples
|
||||
|
||||
@@ -103,7 +95,8 @@ Let us use the lists below in the following examples
|
||||
param01:
|
||||
x: default_value
|
||||
y: default_value
|
||||
list: [default_value]
|
||||
list:
|
||||
- default_value
|
||||
- name: myname02
|
||||
param01: [1, 1, 2, 3]
|
||||
|
||||
@@ -112,17 +105,16 @@ Let us use the lists below in the following examples
|
||||
param01:
|
||||
y: patch_value
|
||||
z: patch_value
|
||||
list: [patch_value]
|
||||
list:
|
||||
- patch_value
|
||||
- name: myname02
|
||||
param01: [3, 4, 4]
|
||||
param01: [3, 4, 4, {key: value}]
|
||||
|
||||
list_merge=replace (default)
|
||||
""""""""""""""""""""""""""""
|
||||
Example :ansopt:`community.general.lists_mergeby#filter:list_merge=replace` (default):
|
||||
Example ``list_merge=replace`` (default):
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
list3: "{{ [list1, list2] |
|
||||
list3: "{{ [list1, list2]|
|
||||
community.general.lists_mergeby('name',
|
||||
recursive=true) }}"
|
||||
|
||||
@@ -131,22 +123,25 @@ This produces:
|
||||
.. code-block:: yaml
|
||||
|
||||
list3:
|
||||
- name: myname01
|
||||
param01:
|
||||
x: default_value
|
||||
y: patch_value
|
||||
list: [patch_value]
|
||||
z: patch_value
|
||||
- name: myname02
|
||||
param01: [3, 4, 4]
|
||||
- name: myname01
|
||||
param01:
|
||||
list:
|
||||
- patch_value
|
||||
x: default_value
|
||||
y: patch_value
|
||||
z: patch_value
|
||||
- name: myname02
|
||||
param01:
|
||||
- 3
|
||||
- 4
|
||||
- 4
|
||||
- key: value
|
||||
|
||||
list_merge=keep
|
||||
"""""""""""""""
|
||||
Example :ansopt:`community.general.lists_mergeby#filter:list_merge=keep`:
|
||||
Example ``list_merge=keep``:
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
list3: "{{ [list1, list2] |
|
||||
list3: "{{ [list1, list2]|
|
||||
community.general.lists_mergeby('name',
|
||||
recursive=true,
|
||||
list_merge='keep') }}"
|
||||
@@ -156,22 +151,25 @@ This produces:
|
||||
.. code-block:: yaml
|
||||
|
||||
list3:
|
||||
- name: myname01
|
||||
param01:
|
||||
x: default_value
|
||||
y: patch_value
|
||||
list: [default_value]
|
||||
z: patch_value
|
||||
- name: myname02
|
||||
param01: [1, 1, 2, 3]
|
||||
- name: myname01
|
||||
param01:
|
||||
list:
|
||||
- default_value
|
||||
x: default_value
|
||||
y: patch_value
|
||||
z: patch_value
|
||||
- name: myname02
|
||||
param01:
|
||||
- 1
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
|
||||
list_merge=append
|
||||
"""""""""""""""""
|
||||
Example :ansopt:`community.general.lists_mergeby#filter:list_merge=append`:
|
||||
Example ``list_merge=append``:
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
list3: "{{ [list1, list2] |
|
||||
list3: "{{ [list1, list2]|
|
||||
community.general.lists_mergeby('name',
|
||||
recursive=true,
|
||||
list_merge='append') }}"
|
||||
@@ -181,22 +179,30 @@ This produces:
|
||||
.. code-block:: yaml
|
||||
|
||||
list3:
|
||||
- name: myname01
|
||||
param01:
|
||||
x: default_value
|
||||
y: patch_value
|
||||
list: [default_value, patch_value]
|
||||
z: patch_value
|
||||
- name: myname02
|
||||
param01: [1, 1, 2, 3, 3, 4, 4]
|
||||
- name: myname01
|
||||
param01:
|
||||
list:
|
||||
- default_value
|
||||
- patch_value
|
||||
x: default_value
|
||||
y: patch_value
|
||||
z: patch_value
|
||||
- name: myname02
|
||||
param01:
|
||||
- 1
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 3
|
||||
- 4
|
||||
- 4
|
||||
- key: value
|
||||
|
||||
list_merge=prepend
|
||||
""""""""""""""""""
|
||||
Example :ansopt:`community.general.lists_mergeby#filter:list_merge=prepend`:
|
||||
Example ``list_merge=prepend``:
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
list3: "{{ [list1, list2] |
|
||||
list3: "{{ [list1, list2]|
|
||||
community.general.lists_mergeby('name',
|
||||
recursive=true,
|
||||
list_merge='prepend') }}"
|
||||
@@ -206,22 +212,30 @@ This produces:
|
||||
.. code-block:: yaml
|
||||
|
||||
list3:
|
||||
- name: myname01
|
||||
param01:
|
||||
x: default_value
|
||||
y: patch_value
|
||||
list: [patch_value, default_value]
|
||||
z: patch_value
|
||||
- name: myname02
|
||||
param01: [3, 4, 4, 1, 1, 2, 3]
|
||||
- name: myname01
|
||||
param01:
|
||||
list:
|
||||
- patch_value
|
||||
- default_value
|
||||
x: default_value
|
||||
y: patch_value
|
||||
z: patch_value
|
||||
- name: myname02
|
||||
param01:
|
||||
- 3
|
||||
- 4
|
||||
- 4
|
||||
- key: value
|
||||
- 1
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
|
||||
list_merge=append_rp
|
||||
""""""""""""""""""""
|
||||
Example :ansopt:`community.general.lists_mergeby#filter:list_merge=append_rp`:
|
||||
Example ``list_merge=append_rp``:
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
list3: "{{ [list1, list2] |
|
||||
list3: "{{ [list1, list2]|
|
||||
community.general.lists_mergeby('name',
|
||||
recursive=true,
|
||||
list_merge='append_rp') }}"
|
||||
@@ -231,22 +245,29 @@ This produces:
|
||||
.. code-block:: yaml
|
||||
|
||||
list3:
|
||||
- name: myname01
|
||||
param01:
|
||||
x: default_value
|
||||
y: patch_value
|
||||
list: [default_value, patch_value]
|
||||
z: patch_value
|
||||
- name: myname02
|
||||
param01: [1, 1, 2, 3, 4, 4]
|
||||
- name: myname01
|
||||
param01:
|
||||
list:
|
||||
- default_value
|
||||
- patch_value
|
||||
x: default_value
|
||||
y: patch_value
|
||||
z: patch_value
|
||||
- name: myname02
|
||||
param01:
|
||||
- 1
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
- 4
|
||||
- key: value
|
||||
|
||||
list_merge=prepend_rp
|
||||
"""""""""""""""""""""
|
||||
Example :ansopt:`community.general.lists_mergeby#filter:list_merge=prepend_rp`:
|
||||
Example ``list_merge=prepend_rp``:
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
list3: "{{ [list1, list2] |
|
||||
list3: "{{ [list1, list2]|
|
||||
community.general.lists_mergeby('name',
|
||||
recursive=true,
|
||||
list_merge='prepend_rp') }}"
|
||||
@@ -256,12 +277,21 @@ This produces:
|
||||
.. code-block:: yaml
|
||||
|
||||
list3:
|
||||
- name: myname01
|
||||
param01:
|
||||
x: default_value
|
||||
y: patch_value
|
||||
list: [patch_value, default_value]
|
||||
z: patch_value
|
||||
- name: myname02
|
||||
param01: [3, 4, 4, 1, 1, 2]
|
||||
- name: myname01
|
||||
param01:
|
||||
list:
|
||||
- patch_value
|
||||
- default_value
|
||||
x: default_value
|
||||
y: patch_value
|
||||
z: patch_value
|
||||
- name: myname02
|
||||
param01:
|
||||
- 3
|
||||
- 4
|
||||
- 4
|
||||
- key: value
|
||||
- 1
|
||||
- 1
|
||||
- 2
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ Conversions
|
||||
Parsing CSV files
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
Ansible offers the :ansplugin:`community.general.read_csv module <community.general.read_csv#module>` to read CSV files. Sometimes you need to convert strings to CSV files instead. For this, the :ansplugin:`community.general.from_csv filter <community.general.from_csv#filter>` exists.
|
||||
Ansible offers the :ref:`community.general.read_csv module <ansible_collections.community.general.read_csv_module>` to read CSV files. Sometimes you need to convert strings to CSV files instead. For this, the ``from_csv`` filter exists.
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
@@ -42,7 +42,7 @@ This produces:
|
||||
]
|
||||
}
|
||||
|
||||
The :ansplugin:`community.general.from_csv filter <community.general.from_csv#filter>` has several keyword arguments to control its behavior:
|
||||
The ``from_csv`` filter has several keyword arguments to control its behavior:
|
||||
|
||||
:dialect: Dialect of the CSV file. Default is ``excel``. Other possible choices are ``excel-tab`` and ``unix``. If one of ``delimiter``, ``skipinitialspace`` or ``strict`` is specified, ``dialect`` is ignored.
|
||||
:fieldnames: A set of column names to use. If not provided, the first line of the CSV is assumed to contain the column names.
|
||||
@@ -55,7 +55,7 @@ The :ansplugin:`community.general.from_csv filter <community.general.from_csv#fi
|
||||
Converting to JSON
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
`JC <https://pypi.org/project/jc/>`_ is a CLI tool and Python library which allows to interpret output of various CLI programs as JSON. It is also available as a filter in community.general, called :ansplugin:`community.general.jc#filter`. This filter needs the `jc Python library <https://pypi.org/project/jc/>`_ installed on the controller.
|
||||
`JC <https://pypi.org/project/jc/>`_ is a CLI tool and Python library which allows to interpret output of various CLI programs as JSON. It is also available as a filter in community.general. This filter needs the `jc Python library <https://pypi.org/project/jc/>`_ installed on the controller.
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ The following filters allow to create identifiers.
|
||||
Hashids
|
||||
^^^^^^^
|
||||
|
||||
`Hashids <https://hashids.org/>`_ allow to convert sequences of integers to short unique string identifiers. The :ansplugin:`community.general.hashids_encode#filter` and :ansplugin:`community.general.hashids_decode#filter` filters need the `hashids Python library <https://pypi.org/project/hashids/>`_ installed on the controller.
|
||||
`Hashids <https://hashids.org/>`_ allow to convert sequences of integers to short unique string identifiers. This filter needs the `hashids Python library <https://pypi.org/project/hashids/>`_ installed on the controller.
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
@@ -52,7 +52,7 @@ The hashids filters accept keyword arguments to allow fine-tuning the hashids ge
|
||||
Random MACs
|
||||
^^^^^^^^^^^
|
||||
|
||||
You can use the :ansplugin:`community.general.random_mac filter <community.general.random_mac#filter>` to complete a partial `MAC address <https://en.wikipedia.org/wiki/MAC_address>`_ to a random 6-byte MAC address.
|
||||
You can use the ``random_mac`` filter to complete a partial `MAC address <https://en.wikipedia.org/wiki/MAC_address>`_ to a random 6-byte MAC address.
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
|
||||
@@ -6,4 +6,14 @@
|
||||
Paths
|
||||
-----
|
||||
|
||||
The :ansplugin:`ansible.builtin.path_join filter <ansible.builtin.path_join#filter>` has been added in ansible-base 2.10. Community.general 3.0.0 and newer contains an alias ``community.general.path_join`` for this filter that could be used on Ansible 2.9 as well. Since community.general no longer supports Ansible 2.9, this is now a simple redirect to :ansplugin:`ansible.builtin.path_join filter <ansible.builtin.path_join#filter>`.
|
||||
The ``path_join`` filter has been added in ansible-base 2.10. If you want to use this filter, but also need to support Ansible 2.9, you can use ``community.general``'s ``path_join`` shim, ``community.general.path_join``. This filter redirects to ``path_join`` for ansible-base 2.10 and ansible-core 2.11 or newer, and re-implements the filter for Ansible 2.9.
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
# ansible-base 2.10 or newer:
|
||||
path: {{ ('/etc', path, 'subdir', file) | path_join }}
|
||||
|
||||
# Also works with Ansible 2.9:
|
||||
path: {{ ('/etc', path, 'subdir', file) | community.general.path_join }}
|
||||
|
||||
.. versionadded:: 3.0.0
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
Selecting JSON data: JSON queries
|
||||
---------------------------------
|
||||
|
||||
To select a single element or a data subset from a complex data structure in JSON format (for example, Ansible facts), use the :ansplugin:`community.general.json_query filter <community.general.json_query#filter>`. The :ansplugin:`community.general.json_query#filter` filter lets you query a complex JSON structure and iterate over it using a loop structure.
|
||||
To select a single element or a data subset from a complex data structure in JSON format (for example, Ansible facts), use the ``json_query`` filter. The ``json_query`` filter lets you query a complex JSON structure and iterate over it using a loop structure.
|
||||
|
||||
.. note:: You must manually install the **jmespath** dependency on the Ansible controller before using this filter. This filter is built upon **jmespath**, and you can use the same syntax. For examples, see `jmespath examples <http://jmespath.org/examples.html>`_.
|
||||
|
||||
@@ -124,7 +124,7 @@ To get a hash map with all ports and names of a cluster:
|
||||
var: item
|
||||
loop: "{{ domain_definition | community.general.json_query(server_name_cluster1_query) }}"
|
||||
vars:
|
||||
server_name_cluster1_query: "domain.server[?cluster=='cluster1'].{name: name, port: port}"
|
||||
server_name_cluster1_query: "domain.server[?cluster=='cluster2'].{name: name, port: port}"
|
||||
|
||||
To extract ports from all clusters with name starting with 'server1':
|
||||
|
||||
@@ -146,4 +146,4 @@ To extract ports from all clusters with name containing 'server1':
|
||||
vars:
|
||||
server_name_query: "domain.server[?contains(name,'server1')].port"
|
||||
|
||||
.. note:: while using ``starts_with`` and ``contains``, you have to use ``to_json | from_json`` filter for correct parsing of data structure.
|
||||
.. note:: while using ``starts_with`` and ``contains``, you have to use `` to_json | from_json `` filter for correct parsing of data structure.
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
Working with times
|
||||
------------------
|
||||
|
||||
The :ansplugin:`community.general.to_time_unit filter <community.general.to_time_unit#filter>` allows to convert times from a human-readable string to a unit. For example, ``'4h 30min 12second' | community.general.to_time_unit('hour')`` gives the number of hours that correspond to 4 hours, 30 minutes and 12 seconds.
|
||||
The ``to_time_unit`` filter allows to convert times from a human-readable string to a unit. For example, ``'4h 30min 12second' | community.general.to_time_unit('hour')`` gives the number of hours that correspond to 4 hours, 30 minutes and 12 seconds.
|
||||
|
||||
There are shorthands to directly convert to various units, like :ansplugin:`community.general.to_hours#filter`, :ansplugin:`community.general.to_minutes#filter`, :ansplugin:`community.general.to_seconds#filter`, and so on. The following table lists all units that can be used:
|
||||
There are shorthands to directly convert to various units, like ``to_hours``, ``to_minutes``, ``to_seconds``, and so on. The following table lists all units that can be used:
|
||||
|
||||
.. list-table:: Units
|
||||
:widths: 25 25 25 25
|
||||
@@ -21,37 +21,37 @@ There are shorthands to directly convert to various units, like :ansplugin:`comm
|
||||
* - Millisecond
|
||||
- 1/1000 second
|
||||
- ``ms``, ``millisecond``, ``milliseconds``, ``msec``, ``msecs``, ``msecond``, ``mseconds``
|
||||
- :ansplugin:`community.general.to_milliseconds#filter`
|
||||
- ``to_milliseconds``
|
||||
* - Second
|
||||
- 1 second
|
||||
- ``s``, ``sec``, ``secs``, ``second``, ``seconds``
|
||||
- :ansplugin:`community.general.to_seconds#filter`
|
||||
- ``to_seconds``
|
||||
* - Minute
|
||||
- 60 seconds
|
||||
- ``m``, ``min``, ``mins``, ``minute``, ``minutes``
|
||||
- :ansplugin:`community.general.to_minutes#filter`
|
||||
- ``to_minutes``
|
||||
* - Hour
|
||||
- 60*60 seconds
|
||||
- ``h``, ``hour``, ``hours``
|
||||
- :ansplugin:`community.general.to_hours#filter`
|
||||
- ``to_hours``
|
||||
* - Day
|
||||
- 24*60*60 seconds
|
||||
- ``d``, ``day``, ``days``
|
||||
- :ansplugin:`community.general.to_days#filter`
|
||||
- ``to_days``
|
||||
* - Week
|
||||
- 7*24*60*60 seconds
|
||||
- ``w``, ``week``, ``weeks``
|
||||
- :ansplugin:`community.general.to_weeks#filter`
|
||||
- ``to_weeks``
|
||||
* - Month
|
||||
- 30*24*60*60 seconds
|
||||
- ``mo``, ``month``, ``months``
|
||||
- :ansplugin:`community.general.to_months#filter`
|
||||
- ``to_months``
|
||||
* - Year
|
||||
- 365*24*60*60 seconds
|
||||
- ``y``, ``year``, ``years``
|
||||
- :ansplugin:`community.general.to_years#filter`
|
||||
- ``to_years``
|
||||
|
||||
Note that months and years are using a simplified representation: a month is 30 days, and a year is 365 days. If you need different definitions of months or years, you can pass them as keyword arguments. For example, if you want a year to be 365.25 days, and a month to be 30.5 days, you can write ``'11months 4' | community.general.to_years(year=365.25, month=30.5)``. These keyword arguments can be specified to :ansplugin:`community.general.to_time_unit#filter` and to all shorthand filters.
|
||||
Note that months and years are using a simplified representation: a month is 30 days, and a year is 365 days. If you need different definitions of months or years, you can pass them as keyword arguments. For example, if you want a year to be 365.25 days, and a month to be 30.5 days, you can write ``'11months 4' | community.general.to_years(year=365.25, month=30.5)``. These keyword arguments can be specified to ``to_time_unit`` and to all shorthand filters.
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
Working with Unicode
|
||||
---------------------
|
||||
|
||||
`Unicode <https://unicode.org/main.html>`_ makes it possible to produce two strings which may be visually equivalent, but are comprised of distinctly different characters/character sequences. To address this Unicode defines `normalization forms <https://unicode.org/reports/tr15/>`_ which avoid these distinctions by choosing a unique character sequence for a given visual representation.
|
||||
`Unicode <https://unicode.org/main.html>`_ makes it possible to produce two strings which may be visually equivalent, but are comprised of distinctly different characters/character sequences. To address this ``Unicode`` defines `normalization forms <https://unicode.org/reports/tr15/>`_ which avoid these distinctions by choosing a unique character sequence for a given visual representation.
|
||||
|
||||
You can use the :ansplugin:`community.general.unicode_normalize filter <community.general.unicode_normalize#filter>` to normalize Unicode strings within your playbooks.
|
||||
You can use the ``community.general.unicode_normalize`` filter to normalize ``Unicode`` strings within your playbooks.
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
@@ -28,7 +28,7 @@ This produces:
|
||||
"msg": true
|
||||
}
|
||||
|
||||
The :ansplugin:`community.general.unicode_normalize filter <community.general.unicode_normalize#filter>` accepts a keyword argument :ansopt:`community.general.unicode_normalize#filter:form` to select the Unicode form used to normalize the input string.
|
||||
The ``community.general.unicode_normalize`` filter accepts a keyword argument to select the ``Unicode`` form used to normalize the input string.
|
||||
|
||||
:form: One of ``'NFC'`` (default), ``'NFD'``, ``'NFKC'``, or ``'NFKD'``. See the `Unicode reference <https://unicode.org/reports/tr15/>`_ for more information.
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
Working with versions
|
||||
---------------------
|
||||
|
||||
If you need to sort a list of version numbers, the Jinja ``sort`` filter is problematic. Since it sorts lexicographically, ``2.10`` will come before ``2.9``. To treat version numbers correctly, you can use the :ansplugin:`community.general.version_sort filter <community.general.version_sort#filter>`:
|
||||
If you need to sort a list of version numbers, the Jinja ``sort`` filter is problematic. Since it sorts lexicographically, ``2.10`` will come before ``2.9``. To treat version numbers correctly, you can use the ``version_sort`` filter:
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
..
|
||||
Copyright (c) Ansible Project
|
||||
GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
.. _ansible_collections.community.general.docsite.guide_alicloud:
|
||||
|
||||
Alibaba Cloud Compute Services Guide
|
||||
====================================
|
||||
|
||||
Introduction
|
||||
````````````
|
||||
|
||||
The community.general collection contains several modules for controlling and managing Alibaba Cloud Compute Services (Alicloud). This guide
|
||||
explains how to use the Alicloud Ansible modules together.
|
||||
|
||||
All Alicloud modules require ``footmark`` - install it on your control machine with ``pip install footmark``.
|
||||
|
||||
Cloud modules, including Alicloud modules, are usually executed on your local machine (the control machine) with ``connection: local``, rather than on remote machines defined in your hosts.
|
||||
|
||||
Normally, you'll use the following pattern for plays that provision Alicloud resources:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
- hosts: localhost
|
||||
connection: local
|
||||
vars:
|
||||
- ...
|
||||
tasks:
|
||||
- ...
|
||||
|
||||
Authentication
|
||||
``````````````
|
||||
|
||||
You can specify your Alicloud authentication credentials (access key and secret key) by passing them as
|
||||
environment variables or by storing them in a vars file.
|
||||
|
||||
To pass authentication credentials as environment variables:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
export ALICLOUD_ACCESS_KEY='Alicloud123'
|
||||
export ALICLOUD_SECRET_KEY='AlicloudSecret123'
|
||||
|
||||
To store authentication credentials in a vars file, encrypt them with :ref:`Ansible Vault <vault>` to keep them secure, then list them:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
---
|
||||
alicloud_access_key: "--REMOVED--"
|
||||
alicloud_secret_key: "--REMOVED--"
|
||||
|
||||
Note that if you store your credentials in a vars file, you need to refer to them in each Alicloud module. For example:
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
- community.general.ali_instance:
|
||||
alicloud_access_key: "{{ alicloud_access_key }}"
|
||||
alicloud_secret_key: "{{ alicloud_secret_key }}"
|
||||
image_id: "..."
|
||||
|
||||
Provisioning
|
||||
````````````
|
||||
|
||||
Alicloud modules create Alicloud ECS instances (:ansplugin:`community.general.ali_instance#module`) and retrieve information on these (:ansplugin:`community.general.ali_instance_info#module`).
|
||||
|
||||
You can use the ``count`` parameter to control the number of resources you create or terminate. For example, if you want exactly 5 instances tagged ``NewECS``, set the ``count`` of instances to 5 and the ``count_tag`` to ``NewECS``, as shown in the last task of the example playbook below. If there are no instances with the tag ``NewECS``, the task creates 5 new instances. If there are 2 instances with that tag, the task creates 3 more. If there are 8 instances with that tag, the task terminates 3 of those instances.
|
||||
|
||||
If you do not specify a ``count_tag``, the task creates the number of instances you specify in ``count`` with the ``instance_name`` you provide.
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
# alicloud_setup.yml
|
||||
|
||||
- hosts: localhost
|
||||
connection: local
|
||||
|
||||
tasks:
|
||||
- name: Create a set of instances
|
||||
community.general.ali_instance:
|
||||
instance_type: ecs.n4.small
|
||||
image_id: "{{ ami_id }}"
|
||||
instance_name: "My-new-instance"
|
||||
instance_tags:
|
||||
Name: NewECS
|
||||
Version: 0.0.1
|
||||
count: 5
|
||||
count_tag:
|
||||
Name: NewECS
|
||||
allocate_public_ip: true
|
||||
max_bandwidth_out: 50
|
||||
register: create_instance
|
||||
|
||||
In the example playbook above, data about the instances created by this playbook is saved in the variable defined by the ``register`` keyword in the task.
|
||||
|
||||
Each Alicloud module offers a variety of parameter options. Not all options are demonstrated in the above example. See each individual module for further details and examples.
|
||||
@@ -1,49 +0,0 @@
|
||||
..
|
||||
Copyright (c) Ansible Project
|
||||
GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
.. _ansible_collections.community.general.docsite.guide_online:
|
||||
|
||||
****************
|
||||
Online.net Guide
|
||||
****************
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
Online is a French hosting company mainly known for providing bare-metal servers named Dedibox.
|
||||
Check it out: `https://www.online.net/en <https://www.online.net/en>`_
|
||||
|
||||
Dynamic inventory for Online resources
|
||||
--------------------------------------
|
||||
|
||||
Ansible has a dynamic inventory plugin that can list your resources.
|
||||
|
||||
1. Create a YAML configuration such as ``online_inventory.yml`` with this content:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
plugin: community.general.online
|
||||
|
||||
2. Set your ``ONLINE_TOKEN`` environment variable with your token.
|
||||
|
||||
You need to open an account and log into it before you can get a token.
|
||||
You can find your token at the following page: `https://console.online.net/en/api/access <https://console.online.net/en/api/access>`_
|
||||
|
||||
3. You can test that your inventory is working by running:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ ansible-inventory -v -i online_inventory.yml --list
|
||||
|
||||
|
||||
4. Now you can run your playbook or any other module with this inventory:
|
||||
|
||||
.. code-block:: ansible-output
|
||||
|
||||
$ ansible all -i online_inventory.yml -m ping
|
||||
sd-96735 | SUCCESS => {
|
||||
"changed": false,
|
||||
"ping": "pong"
|
||||
}
|
||||
@@ -1,214 +0,0 @@
|
||||
..
|
||||
Copyright (c) Ansible Project
|
||||
GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
.. _ansible_collections.community.general.docsite.guide_packet:
|
||||
|
||||
**********************************
|
||||
Packet.net Guide
|
||||
**********************************
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
`Packet.net <https://packet.net>`_ is a bare metal infrastructure host that is supported by the community.general collection through six cloud modules. The six modules are:
|
||||
|
||||
- :ansplugin:`community.general.packet_device#module`: manages servers on Packet. You can use this module to create, restart and delete devices.
|
||||
- :ansplugin:`community.general.packet_ip_subnet#module`: assign IP subnet to a bare metal server
|
||||
- :ansplugin:`community.general.packet_project#module`: create/delete a project in Packet host
|
||||
- :ansplugin:`community.general.packet_sshkey#module`: adds a public SSH key from file or value to the Packet infrastructure. Every subsequently-created device will have this public key installed in .ssh/authorized_keys.
|
||||
- :ansplugin:`community.general.packet_volume#module`: create/delete a volume in Packet host
|
||||
- :ansplugin:`community.general.packet_volume_attachment#module`: attach/detach a volume to a device in the Packet host
|
||||
|
||||
Note, this guide assumes you are familiar with Ansible and how it works. If you are not, have a look at their :ref:`docs <ansible_documentation>` before getting started.
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
||||
The Packet modules connect to the Packet API using the `packet-python package <https://pypi.org/project/packet-python/>`_. You can install it with pip:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ pip install packet-python
|
||||
|
||||
In order to check the state of devices created by Ansible on Packet, it is a good idea to install one of the `Packet CLI clients <https://www.packet.net/developers/integrations/>`_. Otherwise you can check them through the `Packet portal <https://app.packet.net/portal>`_.
|
||||
|
||||
To use the modules you will need a Packet API token. You can generate an API token through the Packet portal `here <https://app.packet.net/portal#/api-keys>`__. The simplest way to authenticate yourself is to set the Packet API token in an environment variable:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ export PACKET_API_TOKEN=Bfse9F24SFtfs423Gsd3ifGsd43sSdfs
|
||||
|
||||
If you are not comfortable exporting your API token, you can pass it as a parameter to the modules.
|
||||
|
||||
On Packet, devices and reserved IP addresses belong to `projects <https://www.packet.com/developers/api/#projects>`_. In order to use the packet_device module, you need to specify the UUID of the project in which you want to create or manage devices. You can find a project's UUID in the Packet portal `here <https://app.packet.net/portal#/projects/list/table/>`_ (it is just under the project table) or through one of the available `CLIs <https://www.packet.net/developers/integrations/>`_.
|
||||
|
||||
|
||||
If you want to use a new SSH key pair in this tutorial, you can generate it to ``./id_rsa`` and ``./id_rsa.pub`` as:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ ssh-keygen -t rsa -f ./id_rsa
|
||||
|
||||
If you want to use an existing key pair, just copy the private and public key over to the playbook directory.
|
||||
|
||||
|
||||
Device Creation
|
||||
===============
|
||||
|
||||
The following code block is a simple playbook that creates one `Type 0 <https://www.packet.com/cloud/servers/t1-small/>`_ server (the ``plan`` parameter). You have to supply ``plan`` and ``operating_system``. ``location`` defaults to ``ewr1`` (Parsippany, NJ). You can find all the possible values for the parameters through a `CLI client <https://www.packet.net/developers/integrations/>`_.
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
# playbook_create.yml
|
||||
|
||||
- name: Create Ubuntu device
|
||||
hosts: localhost
|
||||
tasks:
|
||||
|
||||
- community.general.packet_sshkey:
|
||||
key_file: ./id_rsa.pub
|
||||
label: tutorial key
|
||||
|
||||
- community.general.packet_device:
|
||||
project_id: <your_project_id>
|
||||
hostnames: myserver
|
||||
operating_system: ubuntu_16_04
|
||||
plan: baremetal_0
|
||||
facility: sjc1
|
||||
|
||||
After running ``ansible-playbook playbook_create.yml``, you should have a server provisioned on Packet. You can verify through a CLI or in the `Packet portal <https://app.packet.net/portal#/projects/list/table>`__.
|
||||
|
||||
If you get an error with the message "failed to set machine state present, error: Error 404: Not Found", please verify your project UUID.
|
||||
|
||||
|
||||
Updating Devices
|
||||
================
|
||||
|
||||
The two parameters used to uniquely identify Packet devices are: "device_ids" and "hostnames". Both parameters accept either a single string (later converted to a one-element list), or a list of strings.
|
||||
|
||||
The ``device_ids`` and ``hostnames`` parameters are mutually exclusive. The following values are all acceptable:
|
||||
|
||||
- device_ids: ``a27b7a83-fc93-435b-a128-47a5b04f2dcf``
|
||||
|
||||
- hostnames: ``mydev1``
|
||||
|
||||
- device_ids: ``[a27b7a83-fc93-435b-a128-47a5b04f2dcf, 4887130f-0ccd-49a0-99b0-323c1ceb527b]``
|
||||
|
||||
- hostnames: ``[mydev1, mydev2]``
|
||||
|
||||
In addition, hostnames can contain a special ``%d`` formatter along with a ``count`` parameter that lets you easily expand hostnames that follow a simple name and number pattern; in other words, ``hostnames: "mydev%d", count: 2`` will expand to [mydev1, mydev2].
|
||||
|
||||
If your playbook acts on existing Packet devices, you can only pass the ``hostname`` and ``device_ids`` parameters. The following playbook shows how you can reboot a specific Packet device by setting the ``hostname`` parameter:
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
# playbook_reboot.yml
|
||||
|
||||
- name: reboot myserver
|
||||
hosts: localhost
|
||||
tasks:
|
||||
|
||||
- community.general.packet_device:
|
||||
project_id: <your_project_id>
|
||||
hostnames: myserver
|
||||
state: rebooted
|
||||
|
||||
You can also identify specific Packet devices with the ``device_ids`` parameter. The device's UUID can be found in the `Packet Portal <https://app.packet.net/portal>`_ or by using a `CLI <https://www.packet.net/developers/integrations/>`_. The following playbook removes a Packet device using the ``device_ids`` field:
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
# playbook_remove.yml
|
||||
|
||||
- name: remove a device
|
||||
hosts: localhost
|
||||
tasks:
|
||||
|
||||
- community.general.packet_device:
|
||||
project_id: <your_project_id>
|
||||
device_ids: <myserver_device_id>
|
||||
state: absent
|
||||
|
||||
|
||||
More Complex Playbooks
|
||||
======================
|
||||
|
||||
In this example, we will create a CoreOS cluster with `user data <https://packet.com/developers/docs/servers/key-features/user-data/>`_.
|
||||
|
||||
|
||||
The CoreOS cluster will use `etcd <https://etcd.io/>`_ for discovery of other servers in the cluster. Before provisioning your servers, you will need to generate a discovery token for your cluster:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ curl -w "\n" 'https://discovery.etcd.io/new?size=3'
|
||||
|
||||
The following playbook will create an SSH key, 3 Packet servers, and then wait until SSH is ready (or until 5 minutes passed). Make sure to substitute the discovery token URL in ``user_data``, and the ``project_id`` before running ``ansible-playbook``. Also, feel free to change ``plan`` and ``facility``.
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
# playbook_coreos.yml
|
||||
|
||||
- name: Start 3 CoreOS nodes in Packet and wait until SSH is ready
|
||||
hosts: localhost
|
||||
tasks:
|
||||
|
||||
- community.general.packet_sshkey:
|
||||
key_file: ./id_rsa.pub
|
||||
label: new
|
||||
|
||||
- community.general.packet_device:
|
||||
hostnames: [coreos-one, coreos-two, coreos-three]
|
||||
operating_system: coreos_beta
|
||||
plan: baremetal_0
|
||||
facility: ewr1
|
||||
project_id: <your_project_id>
|
||||
wait_for_public_IPv: 4
|
||||
user_data: |
|
||||
#cloud-config
|
||||
coreos:
|
||||
etcd2:
|
||||
discovery: https://discovery.etcd.io/<token>
|
||||
advertise-client-urls: http://$private_ipv4:2379,http://$private_ipv4:4001
|
||||
initial-advertise-peer-urls: http://$private_ipv4:2380
|
||||
listen-client-urls: http://0.0.0.0:2379,http://0.0.0.0:4001
|
||||
listen-peer-urls: http://$private_ipv4:2380
|
||||
fleet:
|
||||
public-ip: $private_ipv4
|
||||
units:
|
||||
- name: etcd2.service
|
||||
command: start
|
||||
- name: fleet.service
|
||||
command: start
|
||||
register: newhosts
|
||||
|
||||
- name: wait for ssh
|
||||
ansible.builtin.wait_for:
|
||||
delay: 1
|
||||
host: "{{ item.public_ipv4 }}"
|
||||
port: 22
|
||||
state: started
|
||||
timeout: 500
|
||||
loop: "{{ newhosts.results[0].devices }}"
|
||||
|
||||
|
||||
As with most Ansible modules, the default states of the Packet modules are idempotent, meaning the resources in your project will remain the same after re-runs of a playbook. Thus, we can keep the ``packet_sshkey`` module call in our playbook. If the public key is already in your Packet account, the call will have no effect.
|
||||
|
||||
The second module call provisions 3 Packet Type 0 (specified using the ``plan`` parameter) servers in the project identified by the ``project_id`` parameter. The servers are all provisioned with CoreOS beta (the ``operating_system`` parameter) and are customized with cloud-config user data passed to the ``user_data`` parameter.
|
||||
|
||||
The ``packet_device`` module has a ``wait_for_public_IPv`` that is used to specify the version of the IP address to wait for (valid values are ``4`` or ``6`` for IPv4 or IPv6). If specified, Ansible will wait until the GET API call for a device contains an Internet-routeable IP address of the specified version. When referring to an IP address of a created device in subsequent module calls, it is wise to use the ``wait_for_public_IPv`` parameter, or ``state: active`` in the packet_device module call.
|
||||
|
||||
Run the playbook:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ ansible-playbook playbook_coreos.yml
|
||||
|
||||
Once the playbook quits, your new devices should be reachable through SSH. Try to connect to one and check if etcd has started properly:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
tomk@work $ ssh -i id_rsa core@$one_of_the_servers_ip
|
||||
core@coreos-one ~ $ etcdctl cluster-health
|
||||
|
||||
If you have any questions or comments let us know! help@packet.net
|
||||
@@ -1,320 +0,0 @@
|
||||
..
|
||||
Copyright (c) Ansible Project
|
||||
GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
.. _ansible_collections.community.general.docsite.guide_scaleway:
|
||||
|
||||
**************
|
||||
Scaleway Guide
|
||||
**************
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
`Scaleway <https://scaleway.com>`_ is a cloud provider supported by the community.general collection through a set of plugins and modules.
|
||||
Those modules are:
|
||||
|
||||
- :ansplugin:`community.general.scaleway_compute#module`: manages servers on Scaleway. You can use this module to create, restart and delete servers.
|
||||
- :ansplugin:`community.general.scaleway_compute_private_network#module`
|
||||
- :ansplugin:`community.general.scaleway_container#module`
|
||||
- :ansplugin:`community.general.scaleway_container_info#module`
|
||||
- :ansplugin:`community.general.scaleway_container_namespace_info#module`
|
||||
- :ansplugin:`community.general.scaleway_container_namespace#module`
|
||||
- :ansplugin:`community.general.scaleway_container_registry_info#module`
|
||||
- :ansplugin:`community.general.scaleway_container_registry#module`
|
||||
- :ansplugin:`community.general.scaleway_database_backup#module`
|
||||
- :ansplugin:`community.general.scaleway_function#module`
|
||||
- :ansplugin:`community.general.scaleway_function_info#module`
|
||||
- :ansplugin:`community.general.scaleway_function_namespace_info#module`
|
||||
- :ansplugin:`community.general.scaleway_function_namespace#module`
|
||||
- :ansplugin:`community.general.scaleway_image_info#module`
|
||||
- :ansplugin:`community.general.scaleway_ip#module`
|
||||
- :ansplugin:`community.general.scaleway_ip_info#module`
|
||||
- :ansplugin:`community.general.scaleway_lb#module`
|
||||
- :ansplugin:`community.general.scaleway_organization_info#module`
|
||||
- :ansplugin:`community.general.scaleway_private_network#module`
|
||||
- :ansplugin:`community.general.scaleway_security_group#module`
|
||||
- :ansplugin:`community.general.scaleway_security_group_info#module`
|
||||
- :ansplugin:`community.general.scaleway_security_group_rule#module`
|
||||
- :ansplugin:`community.general.scaleway_server_info#module`
|
||||
- :ansplugin:`community.general.scaleway_snapshot_info#module`
|
||||
- :ansplugin:`community.general.scaleway_sshkey#module`: adds a public SSH key from a file or value to the Packet infrastructure. Every subsequently-created device will have this public key installed in .ssh/authorized_keys.
|
||||
- :ansplugin:`community.general.scaleway_user_data#module`
|
||||
- :ansplugin:`community.general.scaleway_volume#module`: manages volumes on Scaleway.
|
||||
- :ansplugin:`community.general.scaleway_volume_info#module`
|
||||
|
||||
The plugins are:
|
||||
|
||||
- :ansplugin:`community.general.scaleway#inventory`: inventory plugin
|
||||
|
||||
|
||||
.. note::
|
||||
This guide assumes you are familiar with Ansible and how it works.
|
||||
If you are not, have a look at :ref:`ansible_documentation` before getting started.
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
||||
The Scaleway modules and inventory script connect to the Scaleway API using `Scaleway REST API <https://developer.scaleway.com>`_.
|
||||
To use the modules and inventory script you will need a Scaleway API token.
|
||||
You can generate an API token through the `Scaleway console's credential page <https://cloud.scaleway.com/#/credentials>`__.
|
||||
The simplest way to authenticate yourself is to set the Scaleway API token in an environment variable:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ export SCW_TOKEN=00000000-1111-2222-3333-444444444444
|
||||
|
||||
If you are not comfortable exporting your API token, you can pass it as a parameter to the modules using the ``api_token`` argument.
|
||||
|
||||
If you want to use a new SSH key pair in this tutorial, you can generate it to ``./id_rsa`` and ``./id_rsa.pub`` as:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ ssh-keygen -t rsa -f ./id_rsa
|
||||
|
||||
If you want to use an existing key pair, just copy the private and public key over to the playbook directory.
|
||||
|
||||
How to add an SSH key?
|
||||
======================
|
||||
|
||||
Connection to Scaleway Compute nodes use Secure Shell.
|
||||
SSH keys are stored at the account level, which means that you can reuse the same SSH key in multiple nodes.
|
||||
The first step to configure Scaleway compute resources is to have at least one SSH key configured.
|
||||
|
||||
:ansplugin:`community.general.scaleway_sshkey#module` is a module that manages SSH keys on your Scaleway account.
|
||||
You can add an SSH key to your account by including the following task in a playbook:
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
- name: "Add SSH key"
|
||||
community.general.scaleway_sshkey:
|
||||
ssh_pub_key: "ssh-rsa AAAA..."
|
||||
state: "present"
|
||||
|
||||
The ``ssh_pub_key`` parameter contains your ssh public key as a string. Here is an example inside a playbook:
|
||||
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
- name: Test SSH key lifecycle on a Scaleway account
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
environment:
|
||||
SCW_API_KEY: ""
|
||||
|
||||
tasks:
|
||||
|
||||
- community.general.scaleway_sshkey:
|
||||
ssh_pub_key: "ssh-rsa AAAAB...424242 developer@example.com"
|
||||
state: present
|
||||
register: result
|
||||
|
||||
- ansible.builtin.assert:
|
||||
that:
|
||||
- result is success and result is changed
|
||||
|
||||
How to create a compute instance?
|
||||
=================================
|
||||
|
||||
Now that we have an SSH key configured, the next step is to spin up a server!
|
||||
:ansplugin:`community.general.scaleway_compute#module` is a module that can create, update and delete Scaleway compute instances:
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
- name: Create a server
|
||||
community.general.scaleway_compute:
|
||||
name: foobar
|
||||
state: present
|
||||
image: 00000000-1111-2222-3333-444444444444
|
||||
organization: 00000000-1111-2222-3333-444444444444
|
||||
region: ams1
|
||||
commercial_type: START1-S
|
||||
|
||||
Here are the parameter details for the example shown above:
|
||||
|
||||
- ``name`` is the name of the instance (the one that will show up in your web console).
|
||||
- ``image`` is the UUID of the system image you would like to use.
|
||||
A list of all images is available for each availability zone.
|
||||
- ``organization`` represents the organization that your account is attached to.
|
||||
- ``region`` represents the Availability Zone which your instance is in (for this example, ``par1`` and ``ams1``).
|
||||
- ``commercial_type`` represents the name of the commercial offers.
|
||||
You can check out the Scaleway pricing page to find which instance is right for you.
|
||||
|
||||
Take a look at this short playbook to see a working example using ``scaleway_compute``:
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
- name: Test compute instance lifecycle on a Scaleway account
|
||||
hosts: localhost
|
||||
gather_facts: false
|
||||
environment:
|
||||
SCW_API_KEY: ""
|
||||
|
||||
tasks:
|
||||
|
||||
- name: Create a server
|
||||
register: server_creation_task
|
||||
community.general.scaleway_compute:
|
||||
name: foobar
|
||||
state: present
|
||||
image: 00000000-1111-2222-3333-444444444444
|
||||
organization: 00000000-1111-2222-3333-444444444444
|
||||
region: ams1
|
||||
commercial_type: START1-S
|
||||
wait: true
|
||||
|
||||
- ansible.builtin.debug:
|
||||
var: server_creation_task
|
||||
|
||||
- ansible.builtin.assert:
|
||||
that:
|
||||
- server_creation_task is success
|
||||
- server_creation_task is changed
|
||||
|
||||
- name: Run it
|
||||
community.general.scaleway_compute:
|
||||
name: foobar
|
||||
state: running
|
||||
image: 00000000-1111-2222-3333-444444444444
|
||||
organization: 00000000-1111-2222-3333-444444444444
|
||||
region: ams1
|
||||
commercial_type: START1-S
|
||||
wait: true
|
||||
tags:
|
||||
- web_server
|
||||
register: server_run_task
|
||||
|
||||
- ansible.builtin.debug:
|
||||
var: server_run_task
|
||||
|
||||
- ansible.builtin.assert:
|
||||
that:
|
||||
- server_run_task is success
|
||||
- server_run_task is changed
|
||||
|
||||
Dynamic Inventory Plugin
|
||||
========================
|
||||
|
||||
Ansible ships with :ansplugin:`community.general.scaleway#inventory`.
|
||||
You can now get a complete inventory of your Scaleway resources through this plugin and filter it on
|
||||
different parameters (``regions`` and ``tags`` are currently supported).
|
||||
|
||||
Let us create an example!
|
||||
Suppose that we want to get all hosts that got the tag web_server.
|
||||
Create a file named ``scaleway_inventory.yml`` with the following content:
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
plugin: community.general.scaleway
|
||||
regions:
|
||||
- ams1
|
||||
- par1
|
||||
tags:
|
||||
- web_server
|
||||
|
||||
This inventory means that we want all hosts that got the tag ``web_server`` on the zones ``ams1`` and ``par1``.
|
||||
Once you have configured this file, you can get the information using the following command:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ ansible-inventory --list -i scaleway_inventory.yml
|
||||
|
||||
The output will be:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"_meta": {
|
||||
"hostvars": {
|
||||
"dd8e3ae9-0c7c-459e-bc7b-aba8bfa1bb8d": {
|
||||
"ansible_verbosity": 6,
|
||||
"arch": "x86_64",
|
||||
"commercial_type": "START1-S",
|
||||
"hostname": "foobar",
|
||||
"ipv4": "192.0.2.1",
|
||||
"organization": "00000000-1111-2222-3333-444444444444",
|
||||
"state": "running",
|
||||
"tags": [
|
||||
"web_server"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"all": {
|
||||
"children": [
|
||||
"ams1",
|
||||
"par1",
|
||||
"ungrouped",
|
||||
"web_server"
|
||||
]
|
||||
},
|
||||
"ams1": {},
|
||||
"par1": {
|
||||
"hosts": [
|
||||
"dd8e3ae9-0c7c-459e-bc7b-aba8bfa1bb8d"
|
||||
]
|
||||
},
|
||||
"ungrouped": {},
|
||||
"web_server": {
|
||||
"hosts": [
|
||||
"dd8e3ae9-0c7c-459e-bc7b-aba8bfa1bb8d"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
As you can see, we get different groups of hosts.
|
||||
``par1`` and ``ams1`` are groups based on location.
|
||||
``web_server`` is a group based on a tag.
|
||||
|
||||
In case a filter parameter is not defined, the plugin supposes all values possible are wanted.
|
||||
This means that for each tag that exists on your Scaleway compute nodes, a group based on each tag will be created.
|
||||
|
||||
Scaleway S3 object storage
|
||||
==========================
|
||||
|
||||
`Object Storage <https://www.scaleway.com/object-storage>`_ allows you to store any kind of objects (documents, images, videos, and so on).
|
||||
As the Scaleway API is S3 compatible, Ansible supports it natively through the amazon.aws modules: :ansplugin:`amazon.aws.s3_bucket#module`, :ansplugin:`amazon.aws.s3_object#module`.
|
||||
|
||||
You can find many examples in the `scaleway_s3 integration tests <https://github.com/ansible/ansible-legacy-tests/tree/devel/test/legacy/roles/scaleway_s3>`_.
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
- hosts: myserver
|
||||
vars:
|
||||
scaleway_region: nl-ams
|
||||
s3_url: https://s3.nl-ams.scw.cloud
|
||||
environment:
|
||||
# AWS_ACCESS_KEY matches your scaleway organization id available at https://cloud.scaleway.com/#/account
|
||||
AWS_ACCESS_KEY: 00000000-1111-2222-3333-444444444444
|
||||
# AWS_SECRET_KEY matches a secret token that you can retrieve at https://cloud.scaleway.com/#/credentials
|
||||
AWS_SECRET_KEY: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
|
||||
module_defaults:
|
||||
group/amazon.aws.aws:
|
||||
s3_url: '{{ s3_url }}'
|
||||
region: '{{ scaleway_region }}'
|
||||
tasks:
|
||||
# use a fact instead of a variable, otherwise template is evaluate each time variable is used
|
||||
- ansible.builtin.set_fact:
|
||||
bucket_name: "{{ 99999999 | random | to_uuid }}"
|
||||
|
||||
# "requester_pays:" is mandatory because Scaleway does not implement related API
|
||||
# another way is to use amazon.aws.s3_object and "mode: create" !
|
||||
- amazon.aws.s3_bucket:
|
||||
name: '{{ bucket_name }}'
|
||||
requester_pays:
|
||||
|
||||
- name: Another way to create the bucket
|
||||
amazon.aws.s3_object:
|
||||
bucket: '{{ bucket_name }}'
|
||||
mode: create
|
||||
encrypt: false
|
||||
register: bucket_creation_check
|
||||
|
||||
- name: add something in the bucket
|
||||
amazon.aws.s3_object:
|
||||
mode: put
|
||||
bucket: '{{ bucket_name }}'
|
||||
src: /tmp/test.txt # needs to be created before
|
||||
object: test.txt
|
||||
encrypt: false # server side encryption must be disabled
|
||||
@@ -15,7 +15,7 @@ The :ref:`community.general collection <plugins_in_community.general>` offers cu
|
||||
Feature Tests
|
||||
-------------
|
||||
|
||||
The :ansplugin:`community.general.a_module test <community.general.a_module#test>` allows to check whether a given string refers to an existing module or action plugin. This can be useful in roles, which can use this to ensure that required modules are present ahead of time.
|
||||
The ``a_module`` test allows to check whether a given string refers to an existing module or action plugin. This can be useful in roles, which can use this to ensure that required modules are present ahead of time.
|
||||
|
||||
.. code-block:: yaml+jinja
|
||||
|
||||
|
||||
12
galaxy.yml
12
galaxy.yml
@@ -5,17 +5,17 @@
|
||||
|
||||
namespace: community
|
||||
name: general
|
||||
version: 8.6.11
|
||||
version: 7.0.0
|
||||
readme: README.md
|
||||
authors:
|
||||
- Ansible (https://github.com/ansible)
|
||||
description: >-
|
||||
The community.general collection is a part of the Ansible package and includes many modules and
|
||||
plugins supported by Ansible community which are not part of more specialized community collections.
|
||||
description: null
|
||||
license_file: COPYING
|
||||
tags:
|
||||
- community
|
||||
tags: [community]
|
||||
# NOTE: No dependencies are expected to be added here
|
||||
# dependencies:
|
||||
repository: https://github.com/ansible-collections/community.general
|
||||
documentation: https://docs.ansible.com/ansible/latest/collections/community/general/
|
||||
homepage: https://github.com/ansible-collections/community.general
|
||||
issues: https://github.com/ansible-collections/community.general/issues
|
||||
#type: flatmap
|
||||
|
||||
@@ -3,38 +3,8 @@
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
requires_ansible: '>=2.13.0'
|
||||
action_groups:
|
||||
consul:
|
||||
- consul_auth_method
|
||||
- consul_binding_rule
|
||||
- consul_policy
|
||||
- consul_role
|
||||
- consul_session
|
||||
- consul_token
|
||||
requires_ansible: '>=2.11.0'
|
||||
plugin_routing:
|
||||
callback:
|
||||
actionable:
|
||||
tombstone:
|
||||
removal_version: 2.0.0
|
||||
warning_text: Use the 'default' callback plugin with 'display_skipped_hosts
|
||||
= no' and 'display_ok_hosts = no' options.
|
||||
full_skip:
|
||||
tombstone:
|
||||
removal_version: 2.0.0
|
||||
warning_text: Use the 'default' callback plugin with 'display_skipped_hosts
|
||||
= no' option.
|
||||
hipchat:
|
||||
deprecation:
|
||||
removal_version: 10.0.0
|
||||
warning_text: The hipchat service has been discontinued and the self-hosted variant has been End of Life since 2020.
|
||||
osx_say:
|
||||
redirect: community.general.say
|
||||
stderr:
|
||||
tombstone:
|
||||
removal_version: 2.0.0
|
||||
warning_text: Use the 'default' callback plugin with 'display_failed_stderr
|
||||
= yes' option.
|
||||
connection:
|
||||
docker:
|
||||
redirect: community.docker.docker
|
||||
@@ -52,10 +22,6 @@ plugin_routing:
|
||||
nios_next_network:
|
||||
redirect: infoblox.nios_modules.nios_next_network
|
||||
modules:
|
||||
consul_acl:
|
||||
deprecation:
|
||||
removal_version: 10.0.0
|
||||
warning_text: Use community.general.consul_token and/or community.general.consul_policy instead.
|
||||
rax_cbs_attachments:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
@@ -184,12 +150,6 @@ plugin_routing:
|
||||
warning_text: You are using an internal name to access the community.general.airbrake_deployment
|
||||
modules. This has never been supported or documented, and will stop working
|
||||
in community.general 9.0.0.
|
||||
stackdriver:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on HTTPS APIs that do not exist anymore,
|
||||
and any new development in the direction of providing an alternative should
|
||||
happen in the context of the google.cloud collection.
|
||||
system.aix_devices:
|
||||
redirect: community.general.aix_devices
|
||||
deprecation:
|
||||
@@ -838,11 +798,6 @@ plugin_routing:
|
||||
warning_text: You are using an internal name to access the community.general.flatpak_remote
|
||||
modules. This has never been supported or documented, and will stop working
|
||||
in community.general 9.0.0.
|
||||
flowdock:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on HTTPS APIs that do not exist anymore and
|
||||
there is no clear path to update.
|
||||
notification.flowdock:
|
||||
redirect: community.general.flowdock
|
||||
deprecation:
|
||||
@@ -4478,11 +4433,6 @@ plugin_routing:
|
||||
warning_text: You are using an internal name to access the community.general.wdc_redfish_info
|
||||
modules. This has never been supported or documented, and will stop working
|
||||
in community.general 9.0.0.
|
||||
webfaction_app:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on HTTPS APIs that do not exist anymore and
|
||||
there is no clear path to update.
|
||||
cloud.webfaction.webfaction_app:
|
||||
redirect: community.general.webfaction_app
|
||||
deprecation:
|
||||
@@ -4490,11 +4440,6 @@ plugin_routing:
|
||||
warning_text: You are using an internal name to access the community.general.webfaction_app
|
||||
modules. This has never been supported or documented, and will stop working
|
||||
in community.general 9.0.0.
|
||||
webfaction_db:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on HTTPS APIs that do not exist anymore and
|
||||
there is no clear path to update.
|
||||
cloud.webfaction.webfaction_db:
|
||||
redirect: community.general.webfaction_db
|
||||
deprecation:
|
||||
@@ -4502,11 +4447,6 @@ plugin_routing:
|
||||
warning_text: You are using an internal name to access the community.general.webfaction_db
|
||||
modules. This has never been supported or documented, and will stop working
|
||||
in community.general 9.0.0.
|
||||
webfaction_domain:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on HTTPS APIs that do not exist anymore and
|
||||
there is no clear path to update.
|
||||
cloud.webfaction.webfaction_domain:
|
||||
redirect: community.general.webfaction_domain
|
||||
deprecation:
|
||||
@@ -4514,11 +4454,6 @@ plugin_routing:
|
||||
warning_text: You are using an internal name to access the community.general.webfaction_domain
|
||||
modules. This has never been supported or documented, and will stop working
|
||||
in community.general 9.0.0.
|
||||
webfaction_mailbox:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on HTTPS APIs that do not exist anymore and
|
||||
there is no clear path to update.
|
||||
cloud.webfaction.webfaction_mailbox:
|
||||
redirect: community.general.webfaction_mailbox
|
||||
deprecation:
|
||||
@@ -4526,11 +4461,6 @@ plugin_routing:
|
||||
warning_text: You are using an internal name to access the community.general.webfaction_mailbox
|
||||
modules. This has never been supported or documented, and will stop working
|
||||
in community.general 9.0.0.
|
||||
webfaction_site:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This module relies on HTTPS APIs that do not exist anymore and
|
||||
there is no clear path to update.
|
||||
cloud.webfaction.webfaction_site:
|
||||
redirect: community.general.webfaction_site
|
||||
deprecation:
|
||||
@@ -4686,8 +4616,7 @@ plugin_routing:
|
||||
rackspace:
|
||||
deprecation:
|
||||
removal_version: 9.0.0
|
||||
warning_text: This doc fragment is used by rax modules, that rely on the deprecated
|
||||
package pyrax.
|
||||
warning_text: This doc fragment is used by rax modules, that rely on the deprecated package pyrax.
|
||||
_gcp:
|
||||
redirect: community.google._gcp
|
||||
docker:
|
||||
@@ -4729,6 +4658,24 @@ plugin_routing:
|
||||
redirect: dellemc.openmanage.dellemc_idrac
|
||||
remote_management.dellemc.ome:
|
||||
redirect: dellemc.openmanage.ome
|
||||
callback:
|
||||
actionable:
|
||||
tombstone:
|
||||
removal_version: 2.0.0
|
||||
warning_text: Use the 'default' callback plugin with 'display_skipped_hosts
|
||||
= no' and 'display_ok_hosts = no' options.
|
||||
full_skip:
|
||||
tombstone:
|
||||
removal_version: 2.0.0
|
||||
warning_text: Use the 'default' callback plugin with 'display_skipped_hosts
|
||||
= no' option.
|
||||
osx_say:
|
||||
redirect: community.general.say
|
||||
stderr:
|
||||
tombstone:
|
||||
removal_version: 2.0.0
|
||||
warning_text: Use the 'default' callback plugin with 'display_failed_stderr
|
||||
= yes' option.
|
||||
inventory:
|
||||
docker_machine:
|
||||
redirect: community.docker.docker_machine
|
||||
|
||||
@@ -44,7 +44,7 @@ class ActionModule(ActionBase):
|
||||
|
||||
def _async_result(self, async_status_args, task_vars, timeout):
|
||||
'''
|
||||
Retrieve results of the asynchronous task, and display them in place of
|
||||
Retrieve results of the asynchonous task, and display them in place of
|
||||
the async wrapper results (those with the ansible_job_id key).
|
||||
'''
|
||||
async_status = self._task.copy()
|
||||
@@ -88,10 +88,6 @@ class ActionModule(ActionBase):
|
||||
max_timeout = self._connection._play_context.timeout
|
||||
module_args = self._task.args
|
||||
|
||||
async_status_args = {}
|
||||
starter_cmd = None
|
||||
confirm_cmd = None
|
||||
|
||||
if module_args.get('state', None) == 'restored':
|
||||
if not wrap_async:
|
||||
if not check_mode:
|
||||
|
||||
@@ -45,7 +45,7 @@ class ActionModule(ActionBase):
|
||||
SHUTDOWN_COMMAND_ARGS = {
|
||||
'alpine': '',
|
||||
'void': '-h +{delay_min} "{message}"',
|
||||
'freebsd': '-p +{delay_sec}s "{message}"',
|
||||
'freebsd': '-h +{delay_sec}s "{message}"',
|
||||
'linux': DEFAULT_SHUTDOWN_COMMAND_ARGS,
|
||||
'macosx': '-h +{delay_min} "{message}"',
|
||||
'openbsd': '-h +{delay_min} "{message}"',
|
||||
|
||||
@@ -68,7 +68,7 @@ DOCUMENTATION = '''
|
||||
- section: machinectl_become_plugin
|
||||
key: password
|
||||
notes:
|
||||
- When not using this plugin with user V(root), it only works correctly with a polkit rule which will alter
|
||||
- When not using this plugin with user C(root), it only works correctly with a polkit rule which will alter
|
||||
the behaviour of machinectl. This rule must alter the prompt behaviour to ask directly for the user credentials,
|
||||
if the user is allowed to perform the action (take a look at the examples section).
|
||||
If such a rule is not present the plugin only work if it is used in context with the root user,
|
||||
@@ -102,7 +102,6 @@ class BecomeModule(BecomeBase):
|
||||
prompt = 'Password: '
|
||||
fail = ('==== AUTHENTICATION FAILED ====',)
|
||||
success = ('==== AUTHENTICATION COMPLETE ====',)
|
||||
require_tty = True # see https://github.com/ansible-collections/community.general/issues/6932
|
||||
|
||||
@staticmethod
|
||||
def remove_ansi_codes(line):
|
||||
|
||||
@@ -82,7 +82,7 @@ DOCUMENTATION = '''
|
||||
env:
|
||||
- name: ANSIBLE_PFEXEC_WRAP_EXECUTION
|
||||
notes:
|
||||
- This plugin ignores O(become_user) as pfexec uses it's own C(exec_attr) to figure this out.
|
||||
- This plugin ignores I(become_user) as pfexec uses it's own C(exec_attr) to figure this out.
|
||||
'''
|
||||
|
||||
from ansible.plugins.become import BecomeBase
|
||||
|
||||
8
plugins/cache/redis.py
vendored
8
plugins/cache/redis.py
vendored
@@ -18,9 +18,9 @@ DOCUMENTATION = '''
|
||||
_uri:
|
||||
description:
|
||||
- A colon separated string of connection information for Redis.
|
||||
- The format is V(host:port:db:password), for example V(localhost:6379:0:changeme).
|
||||
- To use encryption in transit, prefix the connection with V(tls://), as in V(tls://localhost:6379:0:changeme).
|
||||
- To use redis sentinel, use separator V(;), for example V(localhost:26379;localhost:26379;0:changeme). Requires redis>=2.9.0.
|
||||
- The format is C(host:port:db:password), for example C(localhost:6379:0:changeme).
|
||||
- To use encryption in transit, prefix the connection with C(tls://), as in C(tls://localhost:6379:0:changeme).
|
||||
- To use redis sentinel, use separator C(;), for example C(localhost:26379;localhost:26379;0:changeme). Requires redis>=2.9.0.
|
||||
required: true
|
||||
env:
|
||||
- name: ANSIBLE_CACHE_PLUGIN_CONNECTION
|
||||
@@ -150,7 +150,7 @@ class CacheModule(BaseCacheModule):
|
||||
# format: "localhost:26379;localhost2:26379;0:changeme"
|
||||
connections = uri.split(';')
|
||||
connection_args = connections.pop(-1)
|
||||
if len(connection_args) > 0: # handle if no db nr is given
|
||||
if len(connection_args) > 0: # hanle if no db nr is given
|
||||
connection_args = connection_args.split(':')
|
||||
kw['db'] = connection_args.pop(0)
|
||||
try:
|
||||
|
||||
@@ -24,7 +24,7 @@ DOCUMENTATION = '''
|
||||
options:
|
||||
max_mem_file:
|
||||
required: true
|
||||
description: Path to cgroups C(memory.max_usage_in_bytes) file. Example V(/sys/fs/cgroup/memory/ansible_profile/memory.max_usage_in_bytes).
|
||||
description: Path to cgroups C(memory.max_usage_in_bytes) file. Example C(/sys/fs/cgroup/memory/ansible_profile/memory.max_usage_in_bytes).
|
||||
env:
|
||||
- name: CGROUP_MAX_MEM_FILE
|
||||
ini:
|
||||
@@ -32,7 +32,7 @@ DOCUMENTATION = '''
|
||||
key: max_mem_file
|
||||
cur_mem_file:
|
||||
required: true
|
||||
description: Path to C(memory.usage_in_bytes) file. Example V(/sys/fs/cgroup/memory/ansible_profile/memory.usage_in_bytes).
|
||||
description: Path to C(memory.usage_in_bytes) file. Example C(/sys/fs/cgroup/memory/ansible_profile/memory.usage_in_bytes).
|
||||
env:
|
||||
- name: CGROUP_CUR_MEM_FILE
|
||||
ini:
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2024, Felix Fontein <felix@fontein.de>
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
name: default_without_diff
|
||||
type: stdout
|
||||
short_description: The default ansible callback without diff output
|
||||
version_added: 8.4.0
|
||||
description:
|
||||
- This is basically the default ansible callback plugin (P(ansible.builtin.default#callback)) without
|
||||
showing diff output. This can be useful when using another callback which sends more detailed information
|
||||
to another service, like the L(ARA, https://ara.recordsansible.org/) callback, and you want diff output
|
||||
sent to that plugin but not shown on the console output.
|
||||
author: Felix Fontein (@felixfontein)
|
||||
extends_documentation_fragment:
|
||||
- ansible.builtin.default_callback
|
||||
- ansible.builtin.result_format_callback
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
# Enable callback in ansible.cfg:
|
||||
ansible_config: |
|
||||
[defaults]
|
||||
stdout_callback = community.general.default_without_diff
|
||||
|
||||
# Enable callback with environment variables:
|
||||
environment_variable: |
|
||||
ANSIBLE_STDOUT_CALLBACK=community.general.default_without_diff
|
||||
'''
|
||||
|
||||
from ansible.plugins.callback.default import CallbackModule as Default
|
||||
|
||||
|
||||
class CallbackModule(Default):
|
||||
CALLBACK_VERSION = 2.0
|
||||
CALLBACK_TYPE = 'stdout'
|
||||
CALLBACK_NAME = 'community.general.default_without_diff'
|
||||
|
||||
def v2_on_file_diff(self, result):
|
||||
pass
|
||||
@@ -18,7 +18,7 @@ DOCUMENTATION = r'''
|
||||
extends_documentation_fragment:
|
||||
- default_callback
|
||||
notes:
|
||||
- Uses the P(ansible.builtin.default#callback) callback plugin output when a custom callback V(message(msg\)) is not provided.
|
||||
- Uses the C(default) callback plugin output when a custom callback message(C(msg)) is not provided.
|
||||
- Makes the callback event data available via the C(ansible_callback_diy) dictionary, which can be used in the templating context for the options.
|
||||
The dictionary is only available in the templating context for the options. It is not a variable that is available via the other
|
||||
various execution contexts, such as playbook, play, task etc.
|
||||
@@ -40,8 +40,8 @@ DOCUMENTATION = r'''
|
||||
if value C(is not None and not omit and length is greater than 0),
|
||||
then the option is being used with output.
|
||||
**Effect**: render value as template and output"
|
||||
- "Valid color values: V(black), V(bright gray), V(blue), V(white), V(green), V(bright blue), V(cyan), V(bright green), V(red), V(bright cyan),
|
||||
V(purple), V(bright red), V(yellow), V(bright purple), V(dark gray), V(bright yellow), V(magenta), V(bright magenta), V(normal)"
|
||||
- "Valid color values: C(black), C(bright gray), C(blue), C(white), C(green), C(bright blue), C(cyan), C(bright green), C(red), C(bright cyan),
|
||||
C(purple), C(bright red), C(yellow), C(bright purple), C(dark gray), C(bright yellow), C(magenta), C(bright magenta), C(normal)"
|
||||
seealso:
|
||||
- name: default – default Ansible screen output
|
||||
description: The official documentation on the B(default) callback plugin.
|
||||
@@ -62,7 +62,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
on_any_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(on_any_msg).
|
||||
- Output color to be used for I(on_any_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -86,7 +86,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
runner_on_failed_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(runner_on_failed_msg).
|
||||
- Output color to be used for I(runner_on_failed_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -110,7 +110,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
runner_on_ok_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(runner_on_ok_msg).
|
||||
- Output color to be used for I(runner_on_ok_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -134,7 +134,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
runner_on_skipped_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(runner_on_skipped_msg).
|
||||
- Output color to be used for I(runner_on_skipped_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -158,7 +158,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
runner_on_unreachable_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(runner_on_unreachable_msg).
|
||||
- Output color to be used for I(runner_on_unreachable_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -182,7 +182,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
playbook_on_start_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(playbook_on_start_msg).
|
||||
- Output color to be used for I(playbook_on_start_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -206,7 +206,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
playbook_on_notify_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(playbook_on_notify_msg).
|
||||
- Output color to be used for I(playbook_on_notify_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -230,7 +230,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
playbook_on_no_hosts_matched_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(playbook_on_no_hosts_matched_msg).
|
||||
- Output color to be used for I(playbook_on_no_hosts_matched_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -254,7 +254,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
playbook_on_no_hosts_remaining_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(playbook_on_no_hosts_remaining_msg).
|
||||
- Output color to be used for I(playbook_on_no_hosts_remaining_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -278,7 +278,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
playbook_on_task_start_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(playbook_on_task_start_msg).
|
||||
- Output color to be used for I(playbook_on_task_start_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -302,7 +302,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
playbook_on_handler_task_start_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(playbook_on_handler_task_start_msg).
|
||||
- Output color to be used for I(playbook_on_handler_task_start_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -326,7 +326,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
playbook_on_vars_prompt_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(playbook_on_vars_prompt_msg).
|
||||
- Output color to be used for I(playbook_on_vars_prompt_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -350,7 +350,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
playbook_on_play_start_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(playbook_on_play_start_msg).
|
||||
- Output color to be used for I(playbook_on_play_start_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -374,7 +374,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
playbook_on_stats_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(playbook_on_stats_msg).
|
||||
- Output color to be used for I(playbook_on_stats_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -398,7 +398,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
on_file_diff_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(on_file_diff_msg).
|
||||
- Output color to be used for I(on_file_diff_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -422,7 +422,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
playbook_on_include_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(playbook_on_include_msg).
|
||||
- Output color to be used for I(playbook_on_include_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -446,7 +446,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
runner_item_on_ok_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(runner_item_on_ok_msg).
|
||||
- Output color to be used for I(runner_item_on_ok_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -470,7 +470,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
runner_item_on_failed_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(runner_item_on_failed_msg).
|
||||
- Output color to be used for I(runner_item_on_failed_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -494,7 +494,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
runner_item_on_skipped_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(runner_item_on_skipped_msg).
|
||||
- Output color to be used for I(runner_item_on_skipped_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -518,7 +518,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
runner_retry_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(runner_retry_msg).
|
||||
- Output color to be used for I(runner_retry_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -542,7 +542,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
runner_on_start_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(runner_on_start_msg).
|
||||
- Output color to be used for I(runner_on_start_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -566,7 +566,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
runner_on_no_hosts_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(runner_on_no_hosts_msg).
|
||||
- Output color to be used for I(runner_on_no_hosts_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
@@ -590,7 +590,7 @@ DOCUMENTATION = r'''
|
||||
|
||||
playbook_on_setup_msg_color:
|
||||
description:
|
||||
- Output color to be used for O(playbook_on_setup_msg).
|
||||
- Output color to be used for I(playbook_on_setup_msg).
|
||||
- Template should render a L(valid color value,#notes).
|
||||
ini:
|
||||
- section: callback_diy
|
||||
|
||||
@@ -84,7 +84,6 @@ import time
|
||||
import uuid
|
||||
|
||||
from collections import OrderedDict
|
||||
from contextlib import closing
|
||||
from os.path import basename
|
||||
|
||||
from ansible.errors import AnsibleError, AnsibleRuntimeError
|
||||
@@ -202,25 +201,24 @@ class ElasticSource(object):
|
||||
|
||||
apm_cli = self.init_apm_client(apm_server_url, apm_service_name, apm_verify_server_cert, apm_secret_token, apm_api_key)
|
||||
if apm_cli:
|
||||
with closing(apm_cli):
|
||||
instrument() # Only call this once, as early as possible.
|
||||
if traceparent:
|
||||
parent = trace_parent_from_string(traceparent)
|
||||
apm_cli.begin_transaction("Session", trace_parent=parent, start=parent_start_time)
|
||||
else:
|
||||
apm_cli.begin_transaction("Session", start=parent_start_time)
|
||||
# Populate trace metadata attributes
|
||||
if self.ansible_version is not None:
|
||||
label(ansible_version=self.ansible_version)
|
||||
label(ansible_session=self.session, ansible_host_name=self.host, ansible_host_user=self.user)
|
||||
if self.ip_address is not None:
|
||||
label(ansible_host_ip=self.ip_address)
|
||||
instrument() # Only call this once, as early as possible.
|
||||
if traceparent:
|
||||
parent = trace_parent_from_string(traceparent)
|
||||
apm_cli.begin_transaction("Session", trace_parent=parent, start=parent_start_time)
|
||||
else:
|
||||
apm_cli.begin_transaction("Session", start=parent_start_time)
|
||||
# Populate trace metadata attributes
|
||||
if self.ansible_version is not None:
|
||||
label(ansible_version=self.ansible_version)
|
||||
label(ansible_session=self.session, ansible_host_name=self.host, ansible_host_user=self.user)
|
||||
if self.ip_address is not None:
|
||||
label(ansible_host_ip=self.ip_address)
|
||||
|
||||
for task_data in tasks:
|
||||
for host_uuid, host_data in task_data.host_data.items():
|
||||
self.create_span_data(apm_cli, task_data, host_data)
|
||||
for task_data in tasks:
|
||||
for host_uuid, host_data in task_data.host_data.items():
|
||||
self.create_span_data(apm_cli, task_data, host_data)
|
||||
|
||||
apm_cli.end_transaction(name=__name__, result=status, duration=end_time - parent_start_time)
|
||||
apm_cli.end_transaction(name=__name__, result=status, duration=end_time - parent_start_time)
|
||||
|
||||
def create_span_data(self, apm_cli, task_data, host_data):
|
||||
""" create the span with the given TaskData and HostData """
|
||||
|
||||
@@ -18,10 +18,6 @@ DOCUMENTATION = '''
|
||||
description:
|
||||
- This callback plugin sends status updates to a HipChat channel during playbook execution.
|
||||
- Before 2.4 only environment variables were available for configuring this plugin.
|
||||
deprecated:
|
||||
removed_in: 10.0.0
|
||||
why: The hipchat service has been discontinued and the self-hosted variant has been End of Life since 2020.
|
||||
alternative: There is none.
|
||||
options:
|
||||
token:
|
||||
description: HipChat API token for v1 or v2 API.
|
||||
|
||||
@@ -59,16 +59,13 @@ import uuid
|
||||
import socket
|
||||
import getpass
|
||||
|
||||
from datetime import datetime
|
||||
from os.path import basename
|
||||
|
||||
from ansible.module_utils.urls import open_url
|
||||
from ansible.parsing.ajson import AnsibleJSONEncoder
|
||||
from ansible.plugins.callback import CallbackBase
|
||||
|
||||
from ansible_collections.community.general.plugins.module_utils.datetime import (
|
||||
now,
|
||||
)
|
||||
|
||||
|
||||
class AzureLogAnalyticsSource(object):
|
||||
def __init__(self):
|
||||
@@ -96,7 +93,7 @@ class AzureLogAnalyticsSource(object):
|
||||
return "https://{0}.ods.opinsights.azure.com/api/logs?api-version=2016-04-01".format(workspace_id)
|
||||
|
||||
def __rfc1123date(self):
|
||||
return now().strftime('%a, %d %b %Y %H:%M:%S GMT')
|
||||
return datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
|
||||
|
||||
def send_event(self, workspace_id, shared_key, state, result, runtime):
|
||||
if result._task_fields['args'].get('_ansible_check_mode') is True:
|
||||
@@ -170,7 +167,7 @@ class CallbackModule(CallbackBase):
|
||||
|
||||
def _seconds_since_start(self, result):
|
||||
return (
|
||||
now() -
|
||||
datetime.utcnow() -
|
||||
self.start_datetimes[result._task._uuid]
|
||||
).total_seconds()
|
||||
|
||||
@@ -188,10 +185,10 @@ class CallbackModule(CallbackBase):
|
||||
self.loganalytics.ansible_playbook = basename(playbook._file_name)
|
||||
|
||||
def v2_playbook_on_task_start(self, task, is_conditional):
|
||||
self.start_datetimes[task._uuid] = now()
|
||||
self.start_datetimes[task._uuid] = datetime.utcnow()
|
||||
|
||||
def v2_playbook_on_handler_task_start(self, task):
|
||||
self.start_datetimes[task._uuid] = now()
|
||||
self.start_datetimes[task._uuid] = datetime.utcnow()
|
||||
|
||||
def v2_runner_on_ok(self, result, **kwargs):
|
||||
self.loganalytics.send_event(
|
||||
|
||||
@@ -18,7 +18,7 @@ DOCUMENTATION = '''
|
||||
requirements:
|
||||
- whitelisting in configuration
|
||||
- certifi (Python library)
|
||||
- flatdict (Python library), if you want to use the O(flatten) option
|
||||
- flatdict (Python library), if you want to use the 'flatten' option
|
||||
options:
|
||||
api:
|
||||
description: URI to the Logentries API.
|
||||
@@ -90,9 +90,9 @@ examples: >
|
||||
api = data.logentries.com
|
||||
port = 10000
|
||||
tls_port = 20000
|
||||
use_tls = true
|
||||
use_tls = no
|
||||
token = dd21fc88-f00a-43ff-b977-e3a4233c53af
|
||||
flatten = false
|
||||
flatten = False
|
||||
'''
|
||||
|
||||
import os
|
||||
@@ -196,11 +196,15 @@ else:
|
||||
class TLSSocketAppender(PlainTextSocketAppender):
|
||||
def open_connection(self):
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
context = ssl.create_default_context(
|
||||
purpose=ssl.Purpose.SERVER_AUTH,
|
||||
cafile=certifi.where(), )
|
||||
sock = context.wrap_socket(
|
||||
sock = ssl.wrap_socket(
|
||||
sock=sock,
|
||||
keyfile=None,
|
||||
certfile=None,
|
||||
server_side=False,
|
||||
cert_reqs=ssl.CERT_REQUIRED,
|
||||
ssl_version=getattr(
|
||||
ssl, 'PROTOCOL_TLSv1_2', ssl.PROTOCOL_TLSv1),
|
||||
ca_certs=certifi.where(),
|
||||
do_handshake_on_connect=True,
|
||||
suppress_ragged_eofs=True, )
|
||||
sock.connect((self.LE_API, self.LE_TLS_PORT))
|
||||
|
||||
@@ -99,6 +99,7 @@ from ansible import context
|
||||
import socket
|
||||
import uuid
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
try:
|
||||
import logstash
|
||||
@@ -108,10 +109,6 @@ except ImportError:
|
||||
|
||||
from ansible.plugins.callback import CallbackBase
|
||||
|
||||
from ansible_collections.community.general.plugins.module_utils.datetime import (
|
||||
now,
|
||||
)
|
||||
|
||||
|
||||
class CallbackModule(CallbackBase):
|
||||
|
||||
@@ -129,7 +126,7 @@ class CallbackModule(CallbackBase):
|
||||
"pip install python-logstash for Python 2"
|
||||
"pip install python3-logstash for Python 3")
|
||||
|
||||
self.start_time = now()
|
||||
self.start_time = datetime.utcnow()
|
||||
|
||||
def _init_plugin(self):
|
||||
if not self.disabled:
|
||||
@@ -188,7 +185,7 @@ class CallbackModule(CallbackBase):
|
||||
self.logger.info("ansible start", extra=data)
|
||||
|
||||
def v2_playbook_on_stats(self, stats):
|
||||
end_time = now()
|
||||
end_time = datetime.utcnow()
|
||||
runtime = end_time - self.start_time
|
||||
summarize_stat = {}
|
||||
for host in stats.processed.keys():
|
||||
|
||||
@@ -71,16 +71,6 @@ options:
|
||||
ini:
|
||||
- section: callback_mail
|
||||
key: bcc
|
||||
message_id_domain:
|
||||
description:
|
||||
- The domain name to use for the L(Message-ID header, https://en.wikipedia.org/wiki/Message-ID).
|
||||
- The default is the hostname of the control node.
|
||||
type: str
|
||||
ini:
|
||||
- section: callback_mail
|
||||
key: message_id_domain
|
||||
version_added: 8.2.0
|
||||
|
||||
'''
|
||||
|
||||
import json
|
||||
@@ -141,7 +131,7 @@ class CallbackModule(CallbackBase):
|
||||
content += 'To: %s\n' % ', '.join([email.utils.formataddr(pair) for pair in to_addresses])
|
||||
if self.cc:
|
||||
content += 'Cc: %s\n' % ', '.join([email.utils.formataddr(pair) for pair in cc_addresses])
|
||||
content += 'Message-ID: %s\n' % email.utils.make_msgid(domain=self.get_option('message_id_domain'))
|
||||
content += 'Message-ID: %s\n' % email.utils.make_msgid()
|
||||
content += 'Subject: %s\n\n' % subject.strip()
|
||||
content += body
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ DOCUMENTATION = '''
|
||||
short_description: Post task results to a Nagios server through nrdp
|
||||
description:
|
||||
- This callback send playbook result to Nagios.
|
||||
- Nagios shall use NRDP to receive passive events.
|
||||
- Nagios shall use NRDP to recive passive events.
|
||||
- The passive check is sent to a dedicated host/service for Ansible.
|
||||
options:
|
||||
url:
|
||||
|
||||
@@ -15,7 +15,7 @@ DOCUMENTATION = '''
|
||||
- set as main display callback
|
||||
short_description: Don't display stuff to screen
|
||||
description:
|
||||
- This callback prevents outputting events to screen.
|
||||
- This callback prevents outputing events to screen.
|
||||
'''
|
||||
|
||||
from ansible.plugins.callback import CallbackBase
|
||||
@@ -24,7 +24,7 @@ from ansible.plugins.callback import CallbackBase
|
||||
class CallbackModule(CallbackBase):
|
||||
|
||||
'''
|
||||
This callback won't print messages to stdout when new callback events are received.
|
||||
This callback wont print messages to stdout when new callback events are received.
|
||||
'''
|
||||
|
||||
CALLBACK_VERSION = 2.0
|
||||
|
||||
@@ -32,10 +32,10 @@ DOCUMENTATION = '''
|
||||
enable_from_environment:
|
||||
type: str
|
||||
description:
|
||||
- Whether to enable this callback only if the given environment variable exists and it is set to V(true).
|
||||
- Whether to enable this callback only if the given environment variable exists and it is set to C(true).
|
||||
- This is handy when you use Configuration as Code and want to send distributed traces
|
||||
if running in the CI rather when running Ansible locally.
|
||||
- For such, it evaluates the given O(enable_from_environment) value as environment variable
|
||||
- For such, it evaluates the given I(enable_from_environment) value as environment variable
|
||||
and if set to true this plugin will be enabled.
|
||||
env:
|
||||
- name: ANSIBLE_OPENTELEMETRY_ENABLE_FROM_ENVIRONMENT
|
||||
@@ -73,17 +73,6 @@ DOCUMENTATION = '''
|
||||
- section: callback_opentelemetry
|
||||
key: disable_logs
|
||||
version_added: 5.8.0
|
||||
disable_attributes_in_logs:
|
||||
default: false
|
||||
type: bool
|
||||
description:
|
||||
- Disable populating span attributes to the logs.
|
||||
env:
|
||||
- name: ANSIBLE_OPENTELEMETRY_DISABLE_ATTRIBUTES_IN_LOGS
|
||||
ini:
|
||||
- section: callback_opentelemetry
|
||||
key: disable_attributes_in_logs
|
||||
version_added: 7.1.0
|
||||
requirements:
|
||||
- opentelemetry-api (Python library)
|
||||
- opentelemetry-exporter-otlp (Python library)
|
||||
@@ -255,7 +244,7 @@ class OpenTelemetrySource(object):
|
||||
task.dump = dump
|
||||
task.add_host(HostData(host_uuid, host_name, status, result))
|
||||
|
||||
def generate_distributed_traces(self, otel_service_name, ansible_playbook, tasks_data, status, traceparent, disable_logs, disable_attributes_in_logs):
|
||||
def generate_distributed_traces(self, otel_service_name, ansible_playbook, tasks_data, status, traceparent, disable_logs):
|
||||
""" generate distributed traces from the collected TaskData and HostData """
|
||||
|
||||
tasks = []
|
||||
@@ -291,9 +280,9 @@ class OpenTelemetrySource(object):
|
||||
for task in tasks:
|
||||
for host_uuid, host_data in task.host_data.items():
|
||||
with tracer.start_as_current_span(task.name, start_time=task.start, end_on_exit=False) as span:
|
||||
self.update_span_data(task, host_data, span, disable_logs, disable_attributes_in_logs)
|
||||
self.update_span_data(task, host_data, span, disable_logs)
|
||||
|
||||
def update_span_data(self, task_data, host_data, span, disable_logs, disable_attributes_in_logs):
|
||||
def update_span_data(self, task_data, host_data, span, disable_logs):
|
||||
""" update the span with the given TaskData and HostData """
|
||||
|
||||
name = '[%s] %s: %s' % (host_data.name, task_data.play, task_data.name)
|
||||
@@ -304,7 +293,6 @@ class OpenTelemetrySource(object):
|
||||
status = Status(status_code=StatusCode.OK)
|
||||
if host_data.status != 'included':
|
||||
# Support loops
|
||||
enriched_error_message = None
|
||||
if 'results' in host_data.result._result:
|
||||
if host_data.status == 'failed':
|
||||
message = self.get_error_message_from_results(host_data.result._result['results'], task_data.action)
|
||||
@@ -327,48 +315,39 @@ class OpenTelemetrySource(object):
|
||||
status = Status(status_code=StatusCode.UNSET)
|
||||
|
||||
span.set_status(status)
|
||||
|
||||
# Create the span and log attributes
|
||||
attributes = {
|
||||
"ansible.task.module": task_data.action,
|
||||
"ansible.task.message": message,
|
||||
"ansible.task.name": name,
|
||||
"ansible.task.result": rc,
|
||||
"ansible.task.host.name": host_data.name,
|
||||
"ansible.task.host.status": host_data.status
|
||||
}
|
||||
if isinstance(task_data.args, dict) and "gather_facts" not in task_data.action:
|
||||
names = tuple(self.transform_ansible_unicode_to_str(k) for k in task_data.args.keys())
|
||||
values = tuple(self.transform_ansible_unicode_to_str(k) for k in task_data.args.values())
|
||||
attributes[("ansible.task.args.name")] = names
|
||||
attributes[("ansible.task.args.value")] = values
|
||||
|
||||
self.set_span_attributes(span, attributes)
|
||||
|
||||
self.set_span_attribute(span, ("ansible.task.args.name"), names)
|
||||
self.set_span_attribute(span, ("ansible.task.args.value"), values)
|
||||
self.set_span_attribute(span, "ansible.task.module", task_data.action)
|
||||
self.set_span_attribute(span, "ansible.task.message", message)
|
||||
self.set_span_attribute(span, "ansible.task.name", name)
|
||||
self.set_span_attribute(span, "ansible.task.result", rc)
|
||||
self.set_span_attribute(span, "ansible.task.host.name", host_data.name)
|
||||
self.set_span_attribute(span, "ansible.task.host.status", host_data.status)
|
||||
# This will allow to enrich the service map
|
||||
self.add_attributes_for_service_map_if_possible(span, task_data)
|
||||
# Send logs
|
||||
if not disable_logs:
|
||||
# This will avoid populating span attributes to the logs
|
||||
span.add_event(task_data.dump, attributes={} if disable_attributes_in_logs else attributes)
|
||||
# Close span always
|
||||
span.add_event(task_data.dump)
|
||||
span.end(end_time=host_data.finish)
|
||||
|
||||
def set_span_attributes(self, span, attributes):
|
||||
""" update the span attributes with the given attributes if not None """
|
||||
def set_span_attribute(self, span, attributeName, attributeValue):
|
||||
""" update the span attribute with the given attribute and value if not None """
|
||||
|
||||
if span is None and self._display is not None:
|
||||
self._display.warning('span object is None. Please double check if that is expected.')
|
||||
else:
|
||||
if attributes is not None:
|
||||
span.set_attributes(attributes)
|
||||
if attributeValue is not None:
|
||||
span.set_attribute(attributeName, attributeValue)
|
||||
|
||||
def add_attributes_for_service_map_if_possible(self, span, task_data):
|
||||
"""Update the span attributes with the service that the task interacted with, if possible."""
|
||||
|
||||
redacted_url = self.parse_and_redact_url_if_possible(task_data.args)
|
||||
if redacted_url:
|
||||
span.set_attribute("http.url", redacted_url.geturl())
|
||||
self.set_span_attribute(span, "http.url", redacted_url.geturl())
|
||||
|
||||
@staticmethod
|
||||
def parse_and_redact_url_if_possible(args):
|
||||
@@ -455,7 +434,6 @@ class CallbackModule(CallbackBase):
|
||||
def __init__(self, display=None):
|
||||
super(CallbackModule, self).__init__(display=display)
|
||||
self.hide_task_arguments = None
|
||||
self.disable_attributes_in_logs = None
|
||||
self.disable_logs = None
|
||||
self.otel_service_name = None
|
||||
self.ansible_playbook = None
|
||||
@@ -487,8 +465,6 @@ class CallbackModule(CallbackBase):
|
||||
|
||||
self.hide_task_arguments = self.get_option('hide_task_arguments')
|
||||
|
||||
self.disable_attributes_in_logs = self.get_option('disable_attributes_in_logs')
|
||||
|
||||
self.disable_logs = self.get_option('disable_logs')
|
||||
|
||||
self.otel_service_name = self.get_option('otel_service_name')
|
||||
@@ -499,20 +475,6 @@ class CallbackModule(CallbackBase):
|
||||
# See https://github.com/open-telemetry/opentelemetry-specification/issues/740
|
||||
self.traceparent = self.get_option('traceparent')
|
||||
|
||||
def dump_results(self, task, result):
|
||||
""" dump the results if disable_logs is not enabled """
|
||||
if self.disable_logs:
|
||||
return ""
|
||||
# ansible.builtin.uri contains the response in the json field
|
||||
save = dict(result._result)
|
||||
|
||||
if "json" in save and task.action in ("ansible.builtin.uri", "ansible.legacy.uri", "uri"):
|
||||
save.pop("json")
|
||||
# ansible.builtin.slurp contains the response in the content field
|
||||
if "content" in save and task.action in ("ansible.builtin.slurp", "ansible.legacy.slurp", "slurp"):
|
||||
save.pop("content")
|
||||
return self._dump_results(save)
|
||||
|
||||
def v2_playbook_on_start(self, playbook):
|
||||
self.ansible_playbook = basename(playbook._file_name)
|
||||
|
||||
@@ -562,7 +524,7 @@ class CallbackModule(CallbackBase):
|
||||
self.tasks_data,
|
||||
status,
|
||||
result,
|
||||
self.dump_results(self.tasks_data[result._task._uuid], result)
|
||||
self._dump_results(result._result)
|
||||
)
|
||||
|
||||
def v2_runner_on_ok(self, result):
|
||||
@@ -570,7 +532,7 @@ class CallbackModule(CallbackBase):
|
||||
self.tasks_data,
|
||||
'ok',
|
||||
result,
|
||||
self.dump_results(self.tasks_data[result._task._uuid], result)
|
||||
self._dump_results(result._result)
|
||||
)
|
||||
|
||||
def v2_runner_on_skipped(self, result):
|
||||
@@ -578,7 +540,7 @@ class CallbackModule(CallbackBase):
|
||||
self.tasks_data,
|
||||
'skipped',
|
||||
result,
|
||||
self.dump_results(self.tasks_data[result._task._uuid], result)
|
||||
self._dump_results(result._result)
|
||||
)
|
||||
|
||||
def v2_playbook_on_include(self, included_file):
|
||||
@@ -600,8 +562,7 @@ class CallbackModule(CallbackBase):
|
||||
self.tasks_data,
|
||||
status,
|
||||
self.traceparent,
|
||||
self.disable_logs,
|
||||
self.disable_attributes_in_logs
|
||||
self.disable_logs
|
||||
)
|
||||
|
||||
def v2_runner_on_async_failed(self, result, **kwargs):
|
||||
|
||||
@@ -18,6 +18,8 @@ DOCUMENTATION = '''
|
||||
short_description: notify using software speech synthesizer
|
||||
description:
|
||||
- This plugin will use the C(say) or C(espeak) program to "speak" about play events.
|
||||
notes:
|
||||
- In Ansible 2.8, this callback has been renamed from C(osx_say) into M(community.general.say).
|
||||
'''
|
||||
|
||||
import platform
|
||||
|
||||
@@ -44,17 +44,26 @@ from ansible import constants as C
|
||||
from ansible.plugins.callback import CallbackBase
|
||||
from ansible.module_utils.common.text.converters import to_text
|
||||
|
||||
try:
|
||||
codeCodes = C.COLOR_CODES
|
||||
except AttributeError:
|
||||
# This constant was moved to ansible.constants in
|
||||
# https://github.com/ansible/ansible/commit/1202dd000f10b0e8959019484f1c3b3f9628fc67
|
||||
# (will be included in ansible-core 2.11.0). For older Ansible/ansible-base versions,
|
||||
# we include from the original location.
|
||||
from ansible.utils.color import codeCodes
|
||||
|
||||
|
||||
DONT_COLORIZE = False
|
||||
COLORS = {
|
||||
'normal': '\033[0m',
|
||||
'ok': '\033[{0}m'.format(C.COLOR_CODES[C.COLOR_OK]),
|
||||
'ok': '\033[{0}m'.format(codeCodes[C.COLOR_OK]),
|
||||
'bold': '\033[1m',
|
||||
'not_so_bold': '\033[1m\033[34m',
|
||||
'changed': '\033[{0}m'.format(C.COLOR_CODES[C.COLOR_CHANGED]),
|
||||
'failed': '\033[{0}m'.format(C.COLOR_CODES[C.COLOR_ERROR]),
|
||||
'changed': '\033[{0}m'.format(codeCodes[C.COLOR_CHANGED]),
|
||||
'failed': '\033[{0}m'.format(codeCodes[C.COLOR_ERROR]),
|
||||
'endc': '\033[0m',
|
||||
'skipped': '\033[{0}m'.format(C.COLOR_CODES[C.COLOR_SKIP]),
|
||||
'skipped': '\033[{0}m'.format(codeCodes[C.COLOR_SKIP]),
|
||||
}
|
||||
|
||||
|
||||
@@ -106,8 +115,8 @@ class CallbackModule(CallbackBase):
|
||||
line_length = 120
|
||||
if self.last_skipped:
|
||||
print()
|
||||
line = "# {0} ".format(task_name)
|
||||
msg = colorize("{0}{1}".format(line, '*' * (line_length - len(line))), 'bold')
|
||||
msg = colorize("# {0} {1}".format(task_name,
|
||||
'*' * (line_length - len(task_name))), 'bold')
|
||||
print(msg)
|
||||
|
||||
def _indent_text(self, text, indent_level):
|
||||
|
||||
@@ -18,6 +18,7 @@ DOCUMENTATION = '''
|
||||
short_description: Sends play events to a Slack channel
|
||||
description:
|
||||
- This is an ansible callback plugin that sends status updates to a Slack channel during playbook execution.
|
||||
- Before Ansible 2.4 only environment variables were available for configuring this plugin.
|
||||
options:
|
||||
webhook_url:
|
||||
required: true
|
||||
|
||||
@@ -36,8 +36,8 @@ DOCUMENTATION = '''
|
||||
key: authtoken
|
||||
validate_certs:
|
||||
description: Whether to validate certificates for connections to HEC. It is not recommended to set to
|
||||
V(false) except when you are sure that nobody can intercept the connection
|
||||
between this plugin and HEC, as setting it to V(false) allows man-in-the-middle attacks!
|
||||
C(false) except when you are sure that nobody can intercept the connection
|
||||
between this plugin and HEC, as setting it to C(false) allows man-in-the-middle attacks!
|
||||
env:
|
||||
- name: SPLUNK_VALIDATE_CERTS
|
||||
ini:
|
||||
@@ -88,16 +88,13 @@ import uuid
|
||||
import socket
|
||||
import getpass
|
||||
|
||||
from datetime import datetime
|
||||
from os.path import basename
|
||||
|
||||
from ansible.module_utils.urls import open_url
|
||||
from ansible.parsing.ajson import AnsibleJSONEncoder
|
||||
from ansible.plugins.callback import CallbackBase
|
||||
|
||||
from ansible_collections.community.general.plugins.module_utils.datetime import (
|
||||
now,
|
||||
)
|
||||
|
||||
|
||||
class SplunkHTTPCollectorSource(object):
|
||||
def __init__(self):
|
||||
@@ -137,7 +134,7 @@ class SplunkHTTPCollectorSource(object):
|
||||
else:
|
||||
time_format = '%Y-%m-%d %H:%M:%S +0000'
|
||||
|
||||
data['timestamp'] = now().strftime(time_format)
|
||||
data['timestamp'] = datetime.utcnow().strftime(time_format)
|
||||
data['host'] = self.host
|
||||
data['ip_address'] = self.ip_address
|
||||
data['user'] = self.user
|
||||
@@ -184,7 +181,7 @@ class CallbackModule(CallbackBase):
|
||||
|
||||
def _runtime(self, result):
|
||||
return (
|
||||
now() -
|
||||
datetime.utcnow() -
|
||||
self.start_datetimes[result._task._uuid]
|
||||
).total_seconds()
|
||||
|
||||
@@ -223,10 +220,10 @@ class CallbackModule(CallbackBase):
|
||||
self.splunk.ansible_playbook = basename(playbook._file_name)
|
||||
|
||||
def v2_playbook_on_task_start(self, task, is_conditional):
|
||||
self.start_datetimes[task._uuid] = now()
|
||||
self.start_datetimes[task._uuid] = datetime.utcnow()
|
||||
|
||||
def v2_playbook_on_handler_task_start(self, task):
|
||||
self.start_datetimes[task._uuid] = now()
|
||||
self.start_datetimes[task._uuid] = datetime.utcnow()
|
||||
|
||||
def v2_runner_on_ok(self, result, **kwargs):
|
||||
self.splunk.send_event(
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
DOCUMENTATION = '''
|
||||
name: sumologic
|
||||
type: notification
|
||||
short_description: Sends task result events to Sumologic
|
||||
@@ -15,8 +15,8 @@ description:
|
||||
- This callback plugin will send task results as JSON formatted events to a Sumologic HTTP collector source.
|
||||
requirements:
|
||||
- Whitelisting this callback plugin
|
||||
- 'Create a HTTP collector source in Sumologic and specify a custom timestamp format of V(yyyy-MM-dd HH:mm:ss ZZZZ) and a custom timestamp locator
|
||||
of V("timestamp": "(.*\)")'
|
||||
- 'Create a HTTP collector source in Sumologic and specify a custom timestamp format of C(yyyy-MM-dd HH:mm:ss ZZZZ) and a custom timestamp locator
|
||||
of C("timestamp": "(.*)")'
|
||||
options:
|
||||
url:
|
||||
description: URL to the Sumologic HTTP collector source.
|
||||
@@ -46,16 +46,13 @@ import uuid
|
||||
import socket
|
||||
import getpass
|
||||
|
||||
from datetime import datetime
|
||||
from os.path import basename
|
||||
|
||||
from ansible.module_utils.urls import open_url
|
||||
from ansible.parsing.ajson import AnsibleJSONEncoder
|
||||
from ansible.plugins.callback import CallbackBase
|
||||
|
||||
from ansible_collections.community.general.plugins.module_utils.datetime import (
|
||||
now,
|
||||
)
|
||||
|
||||
|
||||
class SumologicHTTPCollectorSource(object):
|
||||
def __init__(self):
|
||||
@@ -87,7 +84,8 @@ class SumologicHTTPCollectorSource(object):
|
||||
data['uuid'] = result._task._uuid
|
||||
data['session'] = self.session
|
||||
data['status'] = state
|
||||
data['timestamp'] = now().strftime('%Y-%m-%d %H:%M:%S +0000')
|
||||
data['timestamp'] = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S '
|
||||
'+0000')
|
||||
data['host'] = self.host
|
||||
data['ip_address'] = self.ip_address
|
||||
data['user'] = self.user
|
||||
@@ -125,7 +123,7 @@ class CallbackModule(CallbackBase):
|
||||
|
||||
def _runtime(self, result):
|
||||
return (
|
||||
now() -
|
||||
datetime.utcnow() -
|
||||
self.start_datetimes[result._task._uuid]
|
||||
).total_seconds()
|
||||
|
||||
@@ -146,10 +144,10 @@ class CallbackModule(CallbackBase):
|
||||
self.sumologic.ansible_playbook = basename(playbook._file_name)
|
||||
|
||||
def v2_playbook_on_task_start(self, task, is_conditional):
|
||||
self.start_datetimes[task._uuid] = now()
|
||||
self.start_datetimes[task._uuid] = datetime.utcnow()
|
||||
|
||||
def v2_playbook_on_handler_task_start(self, task):
|
||||
self.start_datetimes[task._uuid] = now()
|
||||
self.start_datetimes[task._uuid] = datetime.utcnow()
|
||||
|
||||
def v2_runner_on_ok(self, result, **kwargs):
|
||||
self.sumologic.send_event(
|
||||
|
||||
@@ -16,6 +16,7 @@ DOCUMENTATION = '''
|
||||
short_description: sends JSON events to syslog
|
||||
description:
|
||||
- This plugin logs ansible-playbook and ansible runs to a syslog server in JSON format.
|
||||
- Before Ansible 2.9 only environment variables were available for configuration.
|
||||
options:
|
||||
server:
|
||||
description: Syslog server that will receive the event.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2023, Al Bowles <@akatch>
|
||||
# Copyright (c) 2017, Allyson Bowles <@akatch>
|
||||
# Copyright (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
@@ -11,7 +11,7 @@ __metaclass__ = type
|
||||
DOCUMENTATION = '''
|
||||
name: unixy
|
||||
type: stdout
|
||||
author: Al Bowles (@akatch)
|
||||
author: Allyson Bowles (@akatch)
|
||||
short_description: condensed Ansible output
|
||||
description:
|
||||
- Consolidated Ansible output in the style of LINUX/UNIX startup logs.
|
||||
@@ -40,6 +40,7 @@ class CallbackModule(CallbackModule_default):
|
||||
- Only display task names if the task runs on at least one host
|
||||
- Add option to display all hostnames on a single line in the appropriate result color (failures may have a separate line)
|
||||
- Consolidate stats display
|
||||
- Display whether run is in --check mode
|
||||
- Don't show play name if no hosts found
|
||||
'''
|
||||
|
||||
@@ -91,31 +92,19 @@ class CallbackModule(CallbackModule_default):
|
||||
def v2_playbook_on_task_start(self, task, is_conditional):
|
||||
self._get_task_display_name(task)
|
||||
if self.task_display_name is not None:
|
||||
if task.check_mode and self.get_option('check_mode_markers'):
|
||||
self._display.display("%s (check mode)..." % self.task_display_name)
|
||||
else:
|
||||
self._display.display("%s..." % self.task_display_name)
|
||||
self._display.display("%s..." % self.task_display_name)
|
||||
|
||||
def v2_playbook_on_handler_task_start(self, task):
|
||||
self._get_task_display_name(task)
|
||||
if self.task_display_name is not None:
|
||||
if task.check_mode and self.get_option('check_mode_markers'):
|
||||
self._display.display("%s (via handler in check mode)... " % self.task_display_name)
|
||||
else:
|
||||
self._display.display("%s (via handler)... " % self.task_display_name)
|
||||
self._display.display("%s (via handler)... " % self.task_display_name)
|
||||
|
||||
def v2_playbook_on_play_start(self, play):
|
||||
name = play.get_name().strip()
|
||||
if play.check_mode and self.get_option('check_mode_markers'):
|
||||
if name and play.hosts:
|
||||
msg = u"\n- %s (in check mode) on hosts: %s -" % (name, ",".join(play.hosts))
|
||||
else:
|
||||
msg = u"- check mode -"
|
||||
if name and play.hosts:
|
||||
msg = u"\n- %s on hosts: %s -" % (name, ",".join(play.hosts))
|
||||
else:
|
||||
if name and play.hosts:
|
||||
msg = u"\n- %s on hosts: %s -" % (name, ",".join(play.hosts))
|
||||
else:
|
||||
msg = u"---"
|
||||
msg = u"---"
|
||||
|
||||
self._display.display(msg)
|
||||
|
||||
@@ -238,10 +227,8 @@ class CallbackModule(CallbackModule_default):
|
||||
self._display.display(" Ran out of hosts!", color=C.COLOR_ERROR)
|
||||
|
||||
def v2_playbook_on_start(self, playbook):
|
||||
if context.CLIARGS['check'] and self.get_option('check_mode_markers'):
|
||||
self._display.display("Executing playbook %s in check mode" % basename(playbook._file_name))
|
||||
else:
|
||||
self._display.display("Executing playbook %s" % basename(playbook._file_name))
|
||||
# TODO display whether this run is happening in check mode
|
||||
self._display.display("Executing playbook %s" % basename(playbook._file_name))
|
||||
|
||||
# show CLI arguments
|
||||
if self._display.verbosity > 3:
|
||||
|
||||
@@ -19,16 +19,6 @@ DOCUMENTATION = '''
|
||||
- default_callback
|
||||
requirements:
|
||||
- set as stdout in configuration
|
||||
seealso:
|
||||
- plugin: ansible.builtin.default
|
||||
plugin_type: callback
|
||||
description: >
|
||||
There is a parameter O(ansible.builtin.default#callback:result_format) in P(ansible.builtin.default#callback)
|
||||
that allows you to change the output format to YAML.
|
||||
notes:
|
||||
- >
|
||||
With ansible-core 2.13 or newer, you can instead specify V(yaml) for the parameter O(ansible.builtin.default#callback:result_format)
|
||||
in P(ansible.builtin.default#callback).
|
||||
'''
|
||||
|
||||
import yaml
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user