Compare commits

..

4 Commits
2.5.2 ... 0.2.1

Author SHA1 Message Date
Felix Fontein
c8a4c0315a Add changelog. 2020-07-06 09:01:14 +02:00
Felix Fontein
d5db1c6894 Bump version in galaxy.yml. 2020-07-06 09:00:21 +02:00
Felix Fontein
4853667405 Add release summary 2020-07-06 08:59:29 +02:00
Felix Fontein
ccbcdfa883 master -> main 2020-07-06 08:58:12 +02:00
2237 changed files with 127544 additions and 51571 deletions

View File

@@ -1,3 +0,0 @@
## Azure Pipelines Configuration
Please see the [Documentation](https://github.com/ansible/community/wiki/Testing:-Azure-Pipelines) for more information.

View File

@@ -1,409 +0,0 @@
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-2
- stable-3
- cron: 0 11 * * 0
displayName: Weekly (old stable branches)
always: true
branches:
include:
- stable-1
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:1.9.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_11
displayName: Sanity 2.11
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Test {0}
testFormat: 2.11/sanity/{0}
targets:
- test: 1
- test: 2
- test: 3
- test: 4
- stage: Sanity_2_10
displayName: Sanity 2.10
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Test {0}
testFormat: 2.10/sanity/{0}
targets:
- test: 1
- test: 2
- test: 3
- test: 4
- stage: Sanity_2_9
displayName: Sanity 2.9
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Test {0}
testFormat: 2.9/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.6
- test: 2.7
- test: 3.5
- test: 3.6
- test: 3.7
- test: 3.8
- test: 3.9
- stage: Units_2_11
displayName: Units 2.11
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.11/units/{0}/1
targets:
- test: 2.6
- test: 2.7
- test: 3.5
- test: 3.6
- test: 3.7
- test: 3.8
- test: 3.9
- stage: Units_2_10
displayName: Units 2.10
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.10/units/{0}/1
targets:
- test: 2.6
- test: 2.7
- test: 3.5
- test: 3.6
- test: 3.7
- test: 3.8
- test: 3.9
- stage: Units_2_9
displayName: Units 2.9
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.9/units/{0}/1
targets:
- test: 2.6
- test: 2.7
- test: 3.5
- test: 3.6
- test: 3.7
- test: 3.8
## Remote
- stage: Remote_devel
displayName: Remote devel
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: devel/{0}
targets:
- name: macOS 11.1
test: macos/11.1
- name: RHEL 7.9
test: rhel/7.9
- name: RHEL 8.3
test: rhel/8.3
- name: FreeBSD 12.2
test: freebsd/12.2
- name: FreeBSD 13.0
test: freebsd/13.0
groups:
- 1
- 2
- 3
- stage: Remote_2_11
displayName: Remote 2.11
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.11/{0}
targets:
- name: macOS 11.1
test: macos/11.1
- name: RHEL 7.9
test: rhel/7.9
- name: RHEL 8.3
test: rhel/8.3
- name: FreeBSD 12.2
test: freebsd/12.2
groups:
- 1
- 2
- stage: Remote_2_10
displayName: Remote 2.10
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.10/{0}
targets:
- name: OS X 10.11
test: osx/10.11
- name: macOS 10.15
test: macos/10.15
- name: macOS 11.1
test: macos/11.1
- name: RHEL 7.8
test: rhel/7.8
- name: RHEL 8.2
test: rhel/8.2
- name: FreeBSD 12.1
test: freebsd/12.1
groups:
- 1
- 2
- stage: Remote_2_9
displayName: Remote 2.9
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.9/{0}
targets:
- name: RHEL 8.2
test: rhel/8.2
- name: FreeBSD 12.0
test: freebsd/12.0
groups:
- 1
- 2
### Docker
- stage: Docker_devel
displayName: Docker devel
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: devel/linux/{0}
targets:
- name: CentOS 6
test: centos6
- name: CentOS 7
test: centos7
- name: CentOS 8
test: centos8
- name: Fedora 33
test: fedora33
- name: Fedora 34
test: fedora34
- name: openSUSE 15 py2
test: opensuse15py2
- name: openSUSE 15 py3
test: opensuse15
- name: Ubuntu 18.04
test: ubuntu1804
- name: Ubuntu 20.04
test: ubuntu2004
groups:
- 1
- 2
- 3
- stage: Docker_2_11
displayName: Docker 2.11
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.11/linux/{0}
targets:
- name: CentOS 8
test: centos8
- name: Fedora 33
test: fedora33
- name: openSUSE 15 py3
test: opensuse15
- name: Ubuntu 20.04
test: ubuntu2004
groups:
- 2
- 3
- stage: Docker_2_10
displayName: Docker 2.10
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.10/linux/{0}
targets:
- name: CentOS 8
test: centos8
- name: Fedora 32
test: fedora32
- name: openSUSE 15 py3
test: opensuse15
- name: Ubuntu 16.04
test: ubuntu1604
groups:
- 2
- 3
- stage: Docker_2_9
displayName: Docker 2.9
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
testFormat: 2.9/linux/{0}
targets:
- name: CentOS 8
test: centos8
- name: Fedora 31
test: fedora31
- name: openSUSE 15 py3
test: opensuse15
groups:
- 2
- 3
### Cloud
- stage: Cloud_devel
displayName: Cloud devel
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: devel/cloud/{0}/1
targets:
- test: 3.8
- stage: Cloud_2_11
displayName: Cloud 2.11
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.11/cloud/{0}/1
targets:
- test: 2.7
- test: 3.6
- stage: Cloud_2_10
displayName: Cloud 2.10
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.10/cloud/{0}/1
targets:
- test: 3.6
- stage: Cloud_2_9
displayName: Cloud 2.9
dependsOn: []
jobs:
- template: templates/matrix.yml
parameters:
nameFormat: Python {0}
testFormat: 2.9/cloud/{0}/1
targets:
- test: 3.6
- stage: Summary
condition: succeededOrFailed()
dependsOn:
- Sanity_devel
- Sanity_2_9
- Sanity_2_10
- Sanity_2_11
- Units_devel
- Units_2_9
- Units_2_10
- Units_2_11
- Remote_devel
- Remote_2_9
- Remote_2_10
- Remote_2_11
- Docker_devel
- Docker_2_9
- Docker_2_10
- Docker_2_11
- Cloud_devel
- Cloud_2_9
- Cloud_2_10
- Cloud_2_11
jobs:
- template: templates/coverage.yml

View File

@@ -1,20 +0,0 @@
#!/usr/bin/env bash
# Aggregate code coverage results for later processing.
set -o pipefail -eu
agent_temp_directory="$1"
PATH="${PWD}/bin:${PATH}"
mkdir "${agent_temp_directory}/coverage/"
options=(--venv --venv-system-site-packages --color -v)
ansible-test coverage combine --export "${agent_temp_directory}/coverage/" "${options[@]}"
if ansible-test coverage analyze targets generate --help >/dev/null 2>&1; then
# Only analyze coverage if the installed version of ansible-test supports it.
# Doing so allows this script to work unmodified for multiple Ansible versions.
ansible-test coverage analyze targets generate "${agent_temp_directory}/coverage/coverage-analyze-targets.json" "${options[@]}"
fi

View File

@@ -1,60 +0,0 @@
#!/usr/bin/env python
"""
Combine coverage data from multiple jobs, keeping the data only from the most recent attempt from each job.
Coverage artifacts must be named using the format: "Coverage $(System.JobAttempt) {StableUniqueNameForEachJob}"
The recommended coverage artifact name format is: Coverage $(System.JobAttempt) $(System.StageDisplayName) $(System.JobDisplayName)
Keep in mind that Azure Pipelines does not enforce unique job display names (only names).
It is up to pipeline authors to avoid name collisions when deviating from the recommended format.
"""
from __future__ import (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()

View File

@@ -1,24 +0,0 @@
#!/usr/bin/env bash
# Check the test results and set variables for use in later steps.
set -o pipefail -eu
if [[ "$PWD" =~ /ansible_collections/ ]]; then
output_path="tests/output"
else
output_path="test/results"
fi
echo "##vso[task.setVariable variable=outputPath]${output_path}"
if compgen -G "${output_path}"'/junit/*.xml' > /dev/null; then
echo "##vso[task.setVariable variable=haveTestResults]true"
fi
if compgen -G "${output_path}"'/bot/ansible-test-*' > /dev/null; then
echo "##vso[task.setVariable variable=haveBotResults]true"
fi
if compgen -G "${output_path}"'/coverage/*' > /dev/null; then
echo "##vso[task.setVariable variable=haveCoverageData]true"
fi

View File

@@ -1,27 +0,0 @@
#!/usr/bin/env bash
# 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.
set -o pipefail -eu
output_path="$1"
curl --silent --show-error https://ansible-ci-files.s3.us-east-1.amazonaws.com/codecov/codecov.sh > codecov.sh
for file in "${output_path}"/reports/coverage*.xml; do
name="${file}"
name="${name##*/}" # remove path
name="${name##coverage=}" # remove 'coverage=' prefix if present
name="${name%.xml}" # remove '.xml' suffix
bash codecov.sh \
-f "${file}" \
-n "${name}" \
-X coveragepy \
-X gcov \
-X fix \
-X search \
-X xcode \
|| echo "Failed to upload code coverage report to codecov.io: ${file}"
done

View File

@@ -1,15 +0,0 @@
#!/usr/bin/env bash
# Generate code coverage reports for uploading to Azure Pipelines and codecov.io.
set -o pipefail -eu
PATH="${PWD}/bin:${PATH}"
if ! ansible-test --help >/dev/null 2>&1; then
# Install the devel version of ansible-test for generating code coverage reports.
# This is only used by Ansible Collections, which are typically tested against multiple Ansible versions (in separate jobs).
# Since a version of ansible-test is required that can work the output from multiple older releases, the devel version is used.
pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check
fi
ansible-test coverage xml --stub --venv --venv-system-site-packages --color -v

View File

@@ -1,34 +0,0 @@
#!/usr/bin/env bash
# Configure the test environment and run the tests.
set -o pipefail -eu
entry_point="$1"
test="$2"
read -r -a coverage_branches <<< "$3" # space separated list of branches to run code coverage on for scheduled builds
export COMMIT_MESSAGE
export COMPLETE
export COVERAGE
export IS_PULL_REQUEST
if [ "${SYSTEM_PULLREQUEST_TARGETBRANCH:-}" ]; then
IS_PULL_REQUEST=true
COMMIT_MESSAGE=$(git log --format=%B -n 1 HEAD^2)
else
IS_PULL_REQUEST=
COMMIT_MESSAGE=$(git log --format=%B -n 1 HEAD)
fi
COMPLETE=
COVERAGE=
if [ "${BUILD_REASON}" = "Schedule" ]; then
COMPLETE=yes
if printf '%s\n' "${coverage_branches[@]}" | grep -q "^${BUILD_SOURCEBRANCHNAME}$"; then
COVERAGE=yes
fi
fi
"${entry_point}" "${test}" 2>&1 | "$(dirname "$0")/time-command.py"

View File

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

View File

@@ -1,39 +0,0 @@
# This template adds a job for processing code coverage data.
# It will upload results to Azure Pipelines and codecov.io.
# Use it from a job stage that completes after all other jobs have completed.
# This can be done by placing it in a separate summary stage that runs after the test stage(s) have completed.
jobs:
- job: Coverage
displayName: Code Coverage
container: 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.sh "$(outputPath)"
displayName: Publish to codecov.io
condition: gt(variables.coverageFileCount, 0)
continueOnError: true

View File

@@ -1,55 +0,0 @@
# This template uses the provided targets and optional groups to generate a matrix which is then passed to the test template.
# If this matrix template does not provide the required functionality, consider using the test template directly instead.
parameters:
# A required list of dictionaries, one per test target.
# Each item in the list must contain a "test" or "name" key.
# Both may be provided. If one is omitted, the other will be used.
- name: targets
type: object
# An optional list of values which will be used to multiply the targets list into a matrix.
# Values can be strings or numbers.
- name: groups
type: object
default: []
# An optional format string used to generate the job name.
# - {0} is the name of an item in the targets list.
- name: nameFormat
type: string
default: "{0}"
# An optional format string used to generate the test name.
# - {0} is the name of an item in the targets list.
- name: testFormat
type: string
default: "{0}"
# An optional format string used to add the group to the job name.
# {0} is the formatted name of an item in the targets list.
# {{1}} is the group -- be sure to include the double "{{" and "}}".
- name: nameGroupFormat
type: string
default: "{0} - {{1}}"
# An optional format string used to add the group to the test name.
# {0} is the formatted test of an item in the targets list.
# {{1}} is the group -- be sure to include the double "{{" and "}}".
- name: testGroupFormat
type: string
default: "{0}/{{1}}"
jobs:
- template: test.yml
parameters:
jobs:
- ${{ if eq(length(parameters.groups), 0) }}:
- ${{ each target in parameters.targets }}:
- name: ${{ format(parameters.nameFormat, coalesce(target.name, target.test)) }}
test: ${{ format(parameters.testFormat, coalesce(target.test, target.name)) }}
- ${{ if not(eq(length(parameters.groups), 0)) }}:
- ${{ each group in parameters.groups }}:
- ${{ each target in parameters.targets }}:
- name: ${{ format(format(parameters.nameGroupFormat, parameters.nameFormat), coalesce(target.name, target.test), group) }}
test: ${{ format(format(parameters.testGroupFormat, parameters.testFormat), coalesce(target.test, target.name), group) }}

View File

@@ -1,45 +0,0 @@
# This template uses the provided list of jobs to create test one or more test jobs.
# It can be used directly if needed, or through the matrix template.
parameters:
# A required list of dictionaries, one per test job.
# Each item in the list must contain a "job" and "name" key.
- name: jobs
type: object
jobs:
- ${{ each job in parameters.jobs }}:
- job: test_${{ replace(replace(replace(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)"

1198
.github/BOTMETA.yml vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +0,0 @@
---
backport_branch_prefix: patchback/backports/
backport_label_prefix: backport-
target_branch_prefix: stable-
...

View File

@@ -1,49 +0,0 @@
name: "Code scanning - action"
on:
schedule:
- cron: '26 19 * * 1'
jobs:
CodeQL-Build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
# Override language selection by uncommenting this and choosing your languages
# with:
# languages: go, javascript, csharp, python, cpp, java
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

File diff suppressed because it is too large Load Diff

View File

@@ -1,27 +1,15 @@
# Community General Collection
[![Build Status](https://dev.azure.com/ansible/community.general/_apis/build/status/CI?branchName=stable-2)](https://dev.azure.com/ansible/community.general/_build?definitionId=31)
[![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/community.general)](https://codecov.io/gh/ansible-collections/community.general)
[![Run Status](https://api.shippable.com/projects/5e664a167c32620006c9fa50/badge?branch=main)](https://app.shippable.com/github/ansible-collections/community.general/dashboard) [![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/community.general)](https://codecov.io/gh/ansible-collections/community.general)
This repo contains the `community.general` Ansible Collection. The collection includes many modules and plugins supported by Ansible community which are not part of more specialized community collections.
This repo contains the `community.general` Ansible Collection.
You can find [documentation for this collection on the Ansible docs site](https://docs.ansible.com/ansible/latest/collections/community/general/).
The collection includes the modules and plugins supported by Ansible community.
Please note that this collection does **not** support Windows targets. Only connection plugins included in this collection might support Windows targets, and will explicitly mention that in their documentation if they do so.
## Tested with Ansible
## Installation and Usage
Tested with the current Ansible 2.9, ansible-base 2.10 and ansible-core 2.11 releases and the current development version of ansible-core. Ansible versions before 2.9.10 are not supported.
## External requirements
Some modules and plugins require external libraries. Please check the requirements for each plugin or module you use in the documentation to find out which requirements are needed.
## Included content
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
### Installing the Collection from Ansible Galaxy
Before using the General community collection, you need to install the collection with the `ansible-galaxy` CLI:
@@ -34,27 +22,34 @@ collections:
- name: community.general
```
See [Ansible Using collections](https://docs.ansible.com/ansible/latest/user_guide/collections_using.html) for more details.
## Testing and Development
## Contributing to this collection
If you want to develop new content for this collection or improve what is already here, the easiest way to work on the collection is to clone it into one of the configured [`COLLECTIONS_PATHS`](https://docs.ansible.com/ansible/latest/reference_appendices/config.html#collections-paths), and work on it there.
If you want to develop new content for this collection or improve what is already here, the easiest way to work on the collection is to clone it into one of the configured [`COLLECTIONS_PATH`](https://docs.ansible.com/ansible/latest/reference_appendices/config.html#collections-paths), and work on it there.
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)
For example, if you are working in the `~/dev` directory:
```
cd ~/dev
git clone git@github.com:ansible-collections/community.general.git collections/ansible_collections/community/general
export COLLECTIONS_PATH=$(pwd)/collections:$COLLECTIONS_PATH
```
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).
### Running tests
### Testing with `ansible-test`
See [here](https://docs.ansible.com/ansible/devel/dev_guide/developing_collections.html#testing-collections).
### Communication
## Release notes
See [here](https://github.com/ansible-collections/community.general/tree/main/CHANGELOG.rst).
## Publishing New Version
Basic instructions without release branches:
1. Create `changelogs/fragments/<version>.yml` with `release_summary:` section (which must be a string, not a list).
2. Run `antsibull-changelog release --collection-flatmap yes`
3. Make sure `CHANGELOG.rst` and `changelogs/changelog.yaml` are added to git, and the deleted fragments have been removed.
4. Tag the commit with `<version>`. Push changes and tag to the main repository.
## More Information
TBD
## Communication
We have a dedicated Working Group for Ansible development.
@@ -67,34 +62,8 @@ For more information about communities, meetings and agendas see [Community Wiki
For more information about [communication](https://docs.ansible.com/ansible/latest/community/communication.html)
### Publishing New Version
## License
Basic instructions without release branches:
GNU General Public License v3.0 or later
1. Create `changelogs/fragments/<version>.yml` with `release_summary:` section (which must be a string, not a list).
2. Run `antsibull-changelog release --collection-flatmap yes`
3. Make sure `CHANGELOG.rst` and `changelogs/changelog.yaml` are added to git, and the deleted fragments have been removed.
4. Tag the commit with `<version>`. Push changes and tag to the main repository.
## Release notes
See the [changelog](https://github.com/ansible-collections/community.general/blob/stable-2/CHANGELOG.rst).
## Roadmap
See [this issue](https://github.com/ansible-collections/community.general/issues/582) for information on releasing, versioning and deprecation.
In general, we plan to release a major version every six months, and minor versions every two months. Major versions can contain breaking changes, while minor versions only contain new features and bugfixes.
## More information
- [Ansible Collection overview](https://github.com/ansible-collections/overview)
- [Ansible User guide](https://docs.ansible.com/ansible/latest/user_guide/index.html)
- [Ansible Developer guide](https://docs.ansible.com/ansible/latest/dev_guide/index.html)
- [Ansible Community code of conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html)
## Licensing
GNU General Public License v3.0 or later.
See [COPYING](https://www.gnu.org/licenses/gpl-3.0.txt) to see the full text.
See [LICENSE](COPYING) to see the full text.

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,6 @@ changes_file: changelog.yaml
changes_format: combined
keep_fragments: false
mention_ancestor: true
flatmap: true
new_plugins_after_name: removed_features
notesdir: fragments
prelude_section_name: release_summary

View File

@@ -1,72 +0,0 @@
Committers Guidelines for community.general
===========================================
This document is based on the [Ansible committer guidelines](https://github.com/ansible/ansible/blob/b57444af14062ec96e0af75fdfc2098c74fe2d9a/docs/docsite/rst/community/committer_guidelines.rst) ([latest version](https://docs.ansible.com/ansible/devel/community/committer_guidelines.html)).
These are the guidelines for people with commit privileges on the Ansible Community General Collection GitHub repository. Please read the guidelines before you commit.
These guidelines apply to everyone. At the same time, this is NOT a process document. So just use good judgment. You have been given commit access because we trust your judgment.
That said, use the trust wisely.
If you abuse the trust and break components and builds, and so on, the trust level falls and you may be asked not to commit or you may lose your commit privileges.
Our workflow on GitHub
----------------------
As a committer, you may already know this, but our workflow forms a lot of our team policies. Please ensure you are aware of the following workflow steps:
* Fork the repository upon which you want to do some work to your own personal repository
* Work on the specific branch upon which you need to commit
* Create a Pull Request back to the collection repository and await reviews
* Adjust code as necessary based on the Comments provided
* Ask someone from the other committers to do a final review and merge
Sometimes, committers merge their own pull requests. This section is a set of guidelines. If you are changing a comma in a doc or making a very minor change, you can use your best judgement. This is another trust thing. The process is critical for any major change, but for little things or getting something done quickly, use your best judgement and make sure people on the team are aware of your work.
Roles
-----
* Release managers: Merge pull requests to `stable-X` branches, create tags to do releases.
* Committers: Fine to do PRs for most things, but we should have a timebox. Hanging PRs may merge on the judgement of these devs.
* Module maintainers: Module maintainers own specific modules and have indirect commit access through the current module PR mechanisms. This is primary [ansibullbot](https://github.com/ansibullbot)'s `shipit` mechanism.
General rules
-------------
Individuals with direct commit access to this collection repository are entrusted with powers that allow them to do a broad variety of things--probably more than we can write down. Rather than rules, treat these as general *guidelines*, individuals with this power are expected to use their best judgement.
* Do NOTs:
- Do not commit directly.
- Do not merge your own PRs. Someone else should have a chance to review and approve the PR merge. You have a small amount of leeway here for very minor changes.
- Do not forget about non-standard / alternate environments. Consider the alternatives. Yes, people have bad/unusual/strange environments (like binaries from multiple init systems installed), but they are the ones who need us the most.
- Do not drag your community team members down. Discuss the technical merits of any pull requests you review. Avoid negativity and personal comments. For more guidance on being a good community member, read the [Ansible Community Code of Conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html).
- Do not forget about the maintenance burden. High-maintenance features may not be worth adding.
- Do not break playbooks. Always keep backwards compatibility in mind.
- Do not forget to keep it simple. Complexity breeds all kinds of problems.
- Do not merge to branches other than `main`, especially not to `stable-X`, if you do not have explicit permission to do so.
- Do not create tags. Tags are used in the release process, and should only be created by the people responsible for managing the stable branches.
* Do:
- Squash, avoid merges whenever possible, use GitHub's squash commits or cherry pick if needed (bisect thanks you).
- Be active. Committers who have no activity on the project (through merges, triage, commits, and so on) will have their permissions suspended.
- Consider backwards compatibility (goes back to "do not break existing playbooks").
- Write tests. PRs with tests are looked at with more priority than PRs without tests that should have them included. While not all changes require tests, be sure to add them for bug fixes or functionality changes.
- Discuss with other committers, specially when you are unsure of something.
- Document! If your PR is a new feature or a change to behavior, make sure you've updated all associated documentation or have notified the right people to do so.
- Consider scope, sometimes a fix can be generalized.
- Keep it simple, then things are maintainable, debuggable and intelligible.
Committers are expected to continue to follow the same community and contribution guidelines followed by the rest of the Ansible community.
People
------
Individuals who have been asked to become a part of this group have generally been contributing in significant ways to the community.general collection for some time. Should they agree, they are requested to add their names and GitHub IDs to this file, in the section below, through a pull request. Doing so indicates that these individuals agree to act in the ways that their fellow committers trust that they will act.
| Name | GitHub ID | IRC Nick | Other |
| ------------------- | -------------------- | ------------------ | -------------------- |
| Andrew Klychkov | andersson007 | andersson007_ | |
| Felix Fontein | felixfontein | felixfontein | |
| John R Barker | gundalow | gundalow | |

View File

@@ -1,16 +1,20 @@
namespace: community
name: general
version: 2.5.2
version: 0.2.1
readme: README.md
authors:
- Ansible (https://github.com/ansible)
description: null
license_file: COPYING
tags: [community]
# NOTE: No dependencies are expected to be added here
# dependencies:
tags: null
# NOTE: No more dependencies can be added to this list
dependencies:
ansible.netcommon: '>=0.0.2'
ansible.posix: '>=0.1.0'
community.kubernetes: '>=0.1.0'
google.cloud: '>=0.0.9'
repository: https://github.com/ansible-collections/community.general
documentation: https://docs.ansible.com/ansible/latest/collections/community/general/
#documentation: https://github.com/ansible-collection-migration/community.general/tree/main/docs
homepage: https://github.com/ansible-collections/community.general
issues: https://github.com/ansible-collections/community.general/issues
#type: flatmap

View File

@@ -1,6 +1,36 @@
---
requires_ansible: '>=2.9.10'
action_groups:
docker:
- docker_swarm
- docker_image_facts
- docker_service
- docker_compose
- docker_config
- docker_container
- docker_container_info
- docker_host_info
- docker_image
- docker_image_info
- docker_login
- docker_network
- docker_network_info
- docker_node
- docker_node_info
- docker_prune
- docker_secret
- docker_swarm
- docker_swarm_info
- docker_swarm_service
- docker_swarm_service_info
- docker_volume
- docker_volume_info
k8s:
- kubevirt_cdi_upload
- kubevirt_preset
- kubevirt_pvc
- kubevirt_rs
- kubevirt_template
- kubevirt_vm
ovirt:
- ovirt_affinity_label_facts
- ovirt_api_facts
@@ -26,585 +56,406 @@ action_groups:
- ovirt_user_facts
- ovirt_vm_facts
- ovirt_vmpool_facts
plugin_routing:
connection:
docker:
redirect: community.docker.docker
oc:
redirect: community.okd.oc
lookup:
gcp_storage_file:
redirect: community.google.gcp_storage_file
hashi_vault:
redirect: community.hashi_vault.hashi_vault
modules:
ali_instance_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.ali_instance_info instead.
docker_compose:
redirect: community.docker.docker_compose
docker_config:
redirect: community.docker.docker_config
docker_container:
redirect: community.docker.docker_container
docker_container_info:
redirect: community.docker.docker_container_info
docker_host_info:
redirect: community.docker.docker_host_info
docker_image:
redirect: community.docker.docker_image
warning_text: see plugin documentation for details
digital_ocean:
deprecation:
removal_version: 2.0.0
warning_text: see plugin documentation for details
digital_ocean_account_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
digital_ocean_certificate_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
digital_ocean_domain_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
digital_ocean_firewall_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
digital_ocean_floating_ip_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
digital_ocean_image_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
digital_ocean_load_balancer_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
digital_ocean_region_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
digital_ocean_size_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
digital_ocean_snapshot_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
digital_ocean_sshkey_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
digital_ocean_tag_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
digital_ocean_volume_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
docker_image_facts:
tombstone:
deprecation:
removal_version: 2.0.0
warning_text: Use community.docker.docker_image_info instead.
docker_image_info:
redirect: community.docker.docker_image_info
docker_login:
redirect: community.docker.docker_login
docker_network:
redirect: community.docker.docker_network
docker_network_info:
redirect: community.docker.docker_network_info
docker_node:
redirect: community.docker.docker_node
docker_node_info:
redirect: community.docker.docker_node_info
docker_prune:
redirect: community.docker.docker_prune
docker_secret:
redirect: community.docker.docker_secret
warning_text: see plugin documentation for details
docker_service:
tombstone:
deprecation:
removal_version: 2.0.0
warning_text: Use community.docker.docker_compose instead.
docker_stack:
redirect: community.docker.docker_stack
docker_stack_info:
redirect: community.docker.docker_stack_info
docker_stack_task_info:
redirect: community.docker.docker_stack_task_info
docker_swarm:
redirect: community.docker.docker_swarm
docker_swarm_info:
redirect: community.docker.docker_swarm_info
docker_swarm_service:
redirect: community.docker.docker_swarm_service
docker_swarm_service_info:
redirect: community.docker.docker_swarm_service_info
docker_volume:
redirect: community.docker.docker_volume
docker_volume_info:
redirect: community.docker.docker_volume_info
foreman:
tombstone:
removal_version: 2.0.0
warning_text: Use the modules from the theforeman.foreman collection instead.
gc_storage:
redirect: community.google.gc_storage
warning_text: see plugin documentation for details
gcdns_record:
tombstone:
deprecation:
removal_version: 2.0.0
warning_text: Use google.cloud.gcp_dns_resource_record_set instead.
warning_text: see plugin documentation for details
gcdns_zone:
tombstone:
deprecation:
removal_version: 2.0.0
warning_text: Use google.cloud.gcp_dns_managed_zone instead.
warning_text: see plugin documentation for details
gce:
tombstone:
deprecation:
removal_version: 2.0.0
warning_text: Use google.cloud.gcp_compute_instance instead.
gce_eip:
redirect: community.google.gce_eip
gce_img:
redirect: community.google.gce_img
gce_instance_template:
redirect: community.google.gce_instance_template
gce_labels:
redirect: community.google.gce_labels
gce_lb:
redirect: community.google.gce_lb
gce_mig:
redirect: community.google.gce_mig
gce_net:
redirect: community.google.gce_net
gce_pd:
redirect: community.google.gce_pd
gce_snapshot:
redirect: community.google.gce_snapshot
gce_tag:
redirect: community.google.gce_tag
gcp_backend_service:
tombstone:
removal_version: 2.0.0
warning_text: Use google.cloud.gcp_compute_backend_service instead.
gcp_forwarding_rule:
tombstone:
removal_version: 2.0.0
warning_text: Use google.cloud.gcp_compute_forwarding_rule or google.cloud.gcp_compute_global_forwarding_rule instead.
gcp_healthcheck:
tombstone:
removal_version: 2.0.0
warning_text: Use google.cloud.gcp_compute_health_check, google.cloud.gcp_compute_http_health_check or google.cloud.gcp_compute_https_health_check instead.
warning_text: see plugin documentation for details
gcp_target_proxy:
tombstone:
deprecation:
removal_version: 2.0.0
warning_text: Use google.cloud.gcp_compute_target_http_proxy instead.
warning_text: see plugin documentation for details
gcp_url_map:
tombstone:
deprecation:
removal_version: 2.0.0
warning_text: Use google.cloud.gcp_compute_url_map instead.
gcpubsub:
redirect: community.google.gcpubsub
gcpubsub_info:
redirect: community.google.gcpubsub_info
warning_text: see plugin documentation for details
gcpubsub_facts:
redirect: community.google.gcpubsub_info
deprecation:
removal_version: 3.0.0
warning_text: Use community.google.gcpubsub_info instead.
warning_text: see plugin documentation for details
gcspanner:
tombstone:
deprecation:
removal_version: 2.0.0
warning_text: Use google.cloud.gcp_spanner_database and/or google.cloud.gcp_spanner_instance instead.
github_hooks:
tombstone:
removal_version: 2.0.0
warning_text: Use community.general.github_webhook and community.general.github_webhook_info instead.
gluster_heal_info:
deprecation:
removal_version: 3.0.0
warning_text: The gluster modules have migrated to the gluster.gluster collection. Use gluster.gluster.gluster_heal_info instead.
gluster_peer:
deprecation:
removal_version: 3.0.0
warning_text: The gluster modules have migrated to the gluster.gluster collection. Use gluster.gluster.gluster_peer instead.
gluster_volume:
deprecation:
removal_version: 3.0.0
warning_text: The gluster modules have migrated to the gluster.gluster collection. Use gluster.gluster.gluster_volume instead.
warning_text: see plugin documentation for details
helm:
deprecation:
removal_version: 3.0.0
warning_text: The helm module in community.general has been deprecated. Use community.kubernetes.helm instead.
hetzner_failover_ip:
redirect: community.hrobot.failover_ip
hetzner_failover_ip_info:
redirect: community.hrobot.failover_ip_info
hetzner_firewall:
redirect: community.hrobot.firewall
hetzner_firewall_info:
redirect: community.hrobot.firewall_info
hpilo_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.hpilo_info instead.
idrac_redfish_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.idrac_redfish_info instead.
jenkins_job_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.jenkins_job_info instead.
katello:
tombstone:
removal_version: 2.0.0
warning_text: Use the modules from the theforeman.foreman collection instead.
kubevirt_cdi_upload:
redirect: community.kubevirt.kubevirt_cdi_upload
kubevirt_preset:
redirect: community.kubevirt.kubevirt_preset
kubevirt_pvc:
redirect: community.kubevirt.kubevirt_pvc
kubevirt_rs:
redirect: community.kubevirt.kubevirt_rs
kubevirt_template:
redirect: community.kubevirt.kubevirt_template
kubevirt_vm:
redirect: community.kubevirt.kubevirt_vm
ldap_attr:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.ldap_attrs instead.
logicmonitor:
tombstone:
removal_version: 1.0.0
warning_text: The logicmonitor_facts module is no longer maintained and the API used has been disabled in 2017.
logicmonitor_facts:
tombstone:
removal_version: 1.0.0
warning_text: The logicmonitor_facts module is no longer maintained and the API used has been disabled in 2017.
memset_memstore_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.memset_memstore_info instead.
warning_text: see plugin documentation for details
memset_server_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.memset_server_info instead.
na_cdot_aggregate:
tombstone:
removal_version: 2.0.0
warning_text: Use netapp.ontap.na_ontap_aggregate instead.
na_cdot_license:
tombstone:
removal_version: 2.0.0
warning_text: Use netapp.ontap.na_ontap_license instead.
na_cdot_lun:
tombstone:
removal_version: 2.0.0
warning_text: Use netapp.ontap.na_ontap_lun instead.
na_cdot_qtree:
tombstone:
removal_version: 2.0.0
warning_text: Use netapp.ontap.na_ontap_qtree instead.
na_cdot_svm:
tombstone:
removal_version: 2.0.0
warning_text: Use netapp.ontap.na_ontap_svm instead.
na_cdot_user:
tombstone:
removal_version: 2.0.0
warning_text: Use netapp.ontap.na_ontap_user instead.
na_cdot_user_role:
tombstone:
removal_version: 2.0.0
warning_text: Use netapp.ontap.na_ontap_user_role instead.
na_cdot_volume:
tombstone:
removal_version: 2.0.0
warning_text: Use netapp.ontap.na_ontap_volume instead.
na_ontap_gather_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use netapp.ontap.na_ontap_info instead.
nginx_status_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.nginx_status_info instead.
one_image_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.one_image_info instead.
onepassword_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.onepassword_info instead.
oneview_datacenter_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.oneview_datacenter_info instead.
oneview_enclosure_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.oneview_enclosure_info instead.
oneview_ethernet_network_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.oneview_ethernet_network_info instead.
oneview_fc_network_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.oneview_fc_network_info instead.
oneview_fcoe_network_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.oneview_fcoe_network_info instead.
oneview_logical_interconnect_group_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.oneview_logical_interconnect_group_info instead.
oneview_network_set_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.oneview_network_set_info instead.
oneview_san_manager_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.oneview_san_manager_info instead.
online_server_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.online_server_info instead.
online_user_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.online_user_info instead.
warning_text: see plugin documentation for details
ovirt:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_vm instead.
warning_text: see plugin documentation for details
online_server_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
online_user_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
one_image_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
ovirt_affinity_label_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_affinity_label_info instead.
warning_text: see plugin documentation for details
ovirt_api_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_api_info instead.
warning_text: see plugin documentation for details
ovirt_cluster_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_cluster_info instead.
warning_text: see plugin documentation for details
ovirt_datacenter_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_datacenter_info instead.
warning_text: see plugin documentation for details
ovirt_disk_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_disk_info instead.
warning_text: see plugin documentation for details
ovirt_event_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_event_info instead.
warning_text: see plugin documentation for details
ovirt_external_provider_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_external_provider_info instead.
warning_text: see plugin documentation for details
ovirt_group_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_group_info instead.
warning_text: see plugin documentation for details
ovirt_host_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_host_info instead.
warning_text: see plugin documentation for details
ovirt_host_storage_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_host_storage_info instead.
warning_text: see plugin documentation for details
ovirt_network_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_network_info instead.
warning_text: see plugin documentation for details
ovirt_nic_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_nic_info instead.
warning_text: see plugin documentation for details
ovirt_permission_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_permission_info instead.
warning_text: see plugin documentation for details
ovirt_quota_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_quota_info instead.
warning_text: see plugin documentation for details
ovirt_scheduling_policy_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_scheduling_policy_info instead.
warning_text: see plugin documentation for details
ovirt_snapshot_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_snapshot_info instead.
warning_text: see plugin documentation for details
ovirt_storage_domain_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_storage_domain_info instead.
warning_text: see plugin documentation for details
ovirt_storage_template_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_storage_template_info instead.
warning_text: see plugin documentation for details
ovirt_storage_vm_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_storage_vm_info instead.
warning_text: see plugin documentation for details
ovirt_tag_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_tag_info instead.
warning_text: see plugin documentation for details
ovirt_template_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_template_info instead.
warning_text: see plugin documentation for details
ovirt_user_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_user_info instead.
warning_text: see plugin documentation for details
ovirt_vm_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_vm_info instead.
warning_text: see plugin documentation for details
ovirt_vmpool_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use ovirt.ovirt.ovirt_vmpool_info instead.
postgresql_copy:
redirect: community.postgresql.postgresql_copy
postgresql_db:
redirect: community.postgresql.postgresql_db
postgresql_ext:
redirect: community.postgresql.postgresql_ext
postgresql_idx:
redirect: community.postgresql.postgresql_idx
postgresql_info:
redirect: community.postgresql.postgresql_info
postgresql_lang:
redirect: community.postgresql.postgresql_lang
postgresql_membership:
redirect: community.postgresql.postgresql_membership
postgresql_owner:
redirect: community.postgresql.postgresql_owner
postgresql_pg_hba:
redirect: community.postgresql.postgresql_pg_hba
postgresql_ping:
redirect: community.postgresql.postgresql_ping
postgresql_privs:
redirect: community.postgresql.postgresql_privs
postgresql_publication:
redirect: community.postgresql.postgresql_publication
postgresql_query:
redirect: community.postgresql.postgresql_query
postgresql_schema:
redirect: community.postgresql.postgresql_schema
postgresql_sequence:
redirect: community.postgresql.postgresql_sequence
postgresql_set:
redirect: community.postgresql.postgresql_set
postgresql_slot:
redirect: community.postgresql.postgresql_slot
postgresql_subscription:
redirect: community.postgresql.postgresql_subscription
postgresql_table:
redirect: community.postgresql.postgresql_table
postgresql_tablespace:
redirect: community.postgresql.postgresql_tablespace
postgresql_user_obj_stat_info:
redirect: community.postgresql.postgresql_user_obj_stat_info
postgresql_user:
redirect: community.postgresql.postgresql_user
purefa_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use purestorage.flasharray.purefa_info instead.
purefb_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use purestorage.flashblade.purefb_info instead.
python_requirements_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.python_requirements_info instead.
redfish_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.redfish_info instead.
warning_text: see plugin documentation for details
scaleway_image_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.scaleway_image_info instead.
warning_text: see plugin documentation for details
scaleway_ip_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.scaleway_ip_info instead.
warning_text: see plugin documentation for details
scaleway_organization_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.scaleway_organization_info instead.
warning_text: see plugin documentation for details
scaleway_security_group_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.scaleway_security_group_info instead.
warning_text: see plugin documentation for details
scaleway_server_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.scaleway_server_info instead.
warning_text: see plugin documentation for details
scaleway_snapshot_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.scaleway_snapshot_info instead.
warning_text: see plugin documentation for details
scaleway_volume_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.scaleway_volume_info instead.
sf_account_manager:
tombstone:
removal_version: 2.0.0
warning_text: Use netapp.elementsw.na_elementsw_account instead.
sf_check_connections:
tombstone:
removal_version: 2.0.0
warning_text: Use netapp.elementsw.na_elementsw_check_connections instead.
sf_snapshot_schedule_manager:
tombstone:
removal_version: 2.0.0
warning_text: Use netapp.elementsw.na_elementsw_snapshot_schedule instead.
sf_volume_access_group_manager:
tombstone:
removal_version: 2.0.0
warning_text: Use netapp.elementsw.na_elementsw_access_group instead.
sf_volume_manager:
tombstone:
removal_version: 2.0.0
warning_text: Use netapp.elementsw.na_elementsw_volume instead.
warning_text: see plugin documentation for details
smartos_image_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.smartos_image_info instead.
vertica_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.vertica_info instead.
warning_text: see plugin documentation for details
xenserver_guest_facts:
deprecation:
removal_version: 3.0.0
warning_text: Use community.general.xenserver_guest_info instead.
doc_fragments:
_gcp:
redirect: community.google._gcp
docker:
redirect: community.docker.docker
hetzner:
redirect: community.hrobot.robot
kubevirt_common_options:
redirect: community.kubevirt.kubevirt_common_options
kubevirt_vm_options:
redirect: community.kubevirt.kubevirt_vm_options
postgresql:
redirect: community.postgresql.postgresql
module_utils:
docker.common:
redirect: community.docker.common
docker.swarm:
redirect: community.docker.swarm
gcdns:
redirect: community.google.gcdns
gce:
redirect: community.google.gce
gcp:
redirect: community.google.gcp
hetzner:
redirect: community.hrobot.robot
kubevirt:
redirect: community.kubevirt.kubevirt
postgresql:
redirect: community.postgresql.postgresql
callback:
actionable:
tombstone:
warning_text: see plugin documentation for details
vertica_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
onepassword_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
ldap_attr:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
foreman:
deprecation:
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:
warning_text: see plugin documentation for details
katello:
deprecation:
removal_version: 2.0.0
warning_text: Use the 'default' callback plugin with 'display_skipped_hosts = no' option.
stderr:
tombstone:
warning_text: see plugin documentation for details
hpilo_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
oneview_datacenter_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
oneview_enclosure_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
oneview_ethernet_network_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
oneview_fc_network_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
oneview_fcoe_network_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
oneview_logical_interconnect_group_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
oneview_network_set_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
oneview_san_manager_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
idrac_redfish_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
redfish_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
github_hooks:
deprecation:
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
docker_swarm:
redirect: community.docker.docker_swarm
kubevirt:
redirect: community.kubevirt.kubevirt
filter:
path_join:
# The ansible.builtin.path_join filter has been added in ansible-base 2.10.
# Since plugin routing is only available since ansible-base 2.10, this
# redirect will be used for ansible-base 2.10 or later, and the included
# path_join filter will be used for Ansible 2.9 or earlier.
redirect: ansible.builtin.path_join
warning_text: see plugin documentation for details
na_cdot_aggregate:
deprecation:
removal_version: 2.0.0
warning_text: see plugin documentation for details
na_cdot_license:
deprecation:
removal_version: 2.0.0
warning_text: see plugin documentation for details
na_cdot_lun:
deprecation:
removal_version: 2.0.0
warning_text: see plugin documentation for details
na_cdot_qtree:
deprecation:
removal_version: 2.0.0
warning_text: see plugin documentation for details
na_cdot_svm:
deprecation:
removal_version: 2.0.0
warning_text: see plugin documentation for details
na_cdot_user:
deprecation:
removal_version: 2.0.0
warning_text: see plugin documentation for details
na_cdot_user_role:
deprecation:
removal_version: 2.0.0
warning_text: see plugin documentation for details
na_cdot_volume:
deprecation:
removal_version: 2.0.0
warning_text: see plugin documentation for details
na_ontap_gather_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
sf_account_manager:
deprecation:
removal_version: 2.0.0
warning_text: see plugin documentation for details
sf_check_connections:
deprecation:
removal_version: 2.0.0
warning_text: see plugin documentation for details
sf_snapshot_schedule_manager:
deprecation:
removal_version: 2.0.0
warning_text: see plugin documentation for details
sf_volume_access_group_manager:
deprecation:
removal_version: 2.0.0
warning_text: see plugin documentation for details
sf_volume_manager:
deprecation:
removal_version: 2.0.0
warning_text: see plugin documentation for details
purefa_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
purefb_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
python_requirements_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
jenkins_job_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details
nginx_status_facts:
deprecation:
removal_version: 3.0.0
warning_text: see plugin documentation for details

View File

@@ -1 +0,0 @@
./system/iptables_state.py

View File

@@ -1 +0,0 @@
./system/shutdown.py

View File

@@ -1,182 +0,0 @@
# Copyright: (c) 2020, quidame <quidame@poivron.org>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import time
from ansible.plugins.action import ActionBase
from ansible.errors import AnsibleError, AnsibleActionFail, AnsibleConnectionFailure
from ansible.utils.vars import merge_hash
from ansible.utils.display import Display
display = Display()
class ActionModule(ActionBase):
# Keep internal params away from user interactions
_VALID_ARGS = frozenset(('path', 'state', 'table', 'noflush', 'counters', 'modprobe', 'ip_version', 'wait'))
DEFAULT_SUDOABLE = True
MSG_ERROR__ASYNC_AND_POLL_NOT_ZERO = (
"This module doesn't support async>0 and poll>0 when its 'state' param "
"is set to 'restored'. To enable its rollback feature (that needs the "
"module to run asynchronously on the remote), please set task attribute "
"'poll' (=%s) to 0, and 'async' (=%s) to a value >2 and not greater than "
"'ansible_timeout' (=%s) (recommended).")
MSG_WARNING__NO_ASYNC_IS_NO_ROLLBACK = (
"Attempts to restore iptables state without rollback in case of mistake "
"may lead the ansible controller to loose access to the hosts and never "
"regain it before fixing firewall rules through a serial console, or any "
"other way except SSH. Please set task attribute 'poll' (=%s) to 0, and "
"'async' (=%s) to a value >2 and not greater than 'ansible_timeout' (=%s) "
"(recommended).")
MSG_WARNING__ASYNC_GREATER_THAN_TIMEOUT = (
"You attempt to restore iptables state with rollback in case of mistake, "
"but with settings that will lead this rollback to happen AFTER that the "
"controller will reach its own timeout. Please set task attribute 'poll' "
"(=%s) to 0, and 'async' (=%s) to a value >2 and not greater than "
"'ansible_timeout' (=%s) (recommended).")
def _async_result(self, module_args, task_vars, timeout):
'''
Retrieve results of the asynchonous task, and display them in place of
the async wrapper results (those with the ansible_job_id key).
'''
# At least one iteration is required, even if timeout is 0.
for i in range(max(1, timeout)):
async_result = self._execute_module(
module_name='ansible.builtin.async_status',
module_args=module_args,
task_vars=task_vars,
wrap_async=False)
if async_result['finished'] == 1:
break
time.sleep(min(1, timeout))
return async_result
def run(self, tmp=None, task_vars=None):
self._supports_check_mode = True
self._supports_async = True
result = super(ActionModule, self).run(tmp, task_vars)
del tmp # tmp no longer has any effect
if not result.get('skipped'):
# FUTURE: better to let _execute_module calculate this internally?
wrap_async = self._task.async_val and not self._connection.has_native_async
# Set short names for values we'll have to compare or reuse
task_poll = self._task.poll
task_async = self._task.async_val
check_mode = self._play_context.check_mode
max_timeout = self._connection._play_context.timeout
module_name = self._task.action
module_args = self._task.args
if module_args.get('state', None) == 'restored':
if not wrap_async:
if not check_mode:
display.warning(self.MSG_WARNING__NO_ASYNC_IS_NO_ROLLBACK % (
task_poll,
task_async,
max_timeout))
elif task_poll:
raise AnsibleActionFail(self.MSG_ERROR__ASYNC_AND_POLL_NOT_ZERO % (
task_poll,
task_async,
max_timeout))
else:
if task_async > max_timeout and not check_mode:
display.warning(self.MSG_WARNING__ASYNC_GREATER_THAN_TIMEOUT % (
task_poll,
task_async,
max_timeout))
# inject the async directory based on the shell option into the
# module args
async_dir = self.get_shell_option('async_dir', default="~/.ansible_async")
# Bind the loop max duration to consistent values on both
# remote and local sides (if not the same, make the loop
# longer on the controller); and set a backup file path.
module_args['_timeout'] = task_async
module_args['_back'] = '%s/iptables.state' % async_dir
async_status_args = dict(_async_dir=async_dir)
confirm_cmd = 'rm -f %s' % module_args['_back']
starter_cmd = 'touch %s.starter' % module_args['_back']
remaining_time = max(task_async, max_timeout)
# do work!
result = merge_hash(result, self._execute_module(module_args=module_args, task_vars=task_vars, wrap_async=wrap_async))
# Then the 3-steps "go ahead or rollback":
# 1. Catch early errors of the module (in asynchronous task) if any.
# Touch a file on the target to signal the module to process now.
# 2. Reset connection to ensure a persistent one will not be reused.
# 3. Confirm the restored state by removing the backup on the remote.
# Retrieve the results of the asynchronous task to return them.
if '_back' in module_args:
async_status_args['jid'] = result.get('ansible_job_id', None)
if async_status_args['jid'] is None:
raise AnsibleActionFail("Unable to get 'ansible_job_id'.")
# Catch early errors due to missing mandatory option, bad
# option type/value, missing required system command, etc.
result = merge_hash(result, self._async_result(async_status_args, task_vars, 0))
# The module is aware to not process the main iptables-restore
# command before finding (and deleting) the 'starter' cookie on
# the host, so the previous query will not reach ssh timeout.
garbage = self._low_level_execute_command(starter_cmd, sudoable=self.DEFAULT_SUDOABLE)
# As the main command is not yet executed on the target, here
# 'finished' means 'failed before main command be executed'.
if not result['finished']:
try:
self._connection.reset()
except AttributeError:
pass
for x in range(max_timeout):
time.sleep(1)
remaining_time -= 1
# - AnsibleConnectionFailure covers rejected requests (i.e.
# by rules with '--jump REJECT')
# - ansible_timeout is able to cover dropped requests (due
# to a rule or policy DROP) if not lower than async_val.
try:
garbage = self._low_level_execute_command(confirm_cmd, sudoable=self.DEFAULT_SUDOABLE)
break
except AnsibleConnectionFailure:
continue
result = merge_hash(result, self._async_result(async_status_args, task_vars, remaining_time))
# Cleanup async related stuff and internal params
for key in ('ansible_job_id', 'results_file', 'started', 'finished'):
if result.get(key):
del result[key]
if result.get('invocation', {}).get('module_args'):
if '_timeout' in result['invocation']['module_args']:
del result['invocation']['module_args']['_back']
del result['invocation']['module_args']['_timeout']
async_status_args['mode'] = 'cleanup'
garbage = self._execute_module(
module_name='ansible.builtin.async_status',
module_args=async_status_args,
task_vars=task_vars,
wrap_async=False)
if not wrap_async:
# remove a temporary path we created
self._remove_tmp_path(self._connection._shell.tmpdir)
return result

View File

@@ -1,211 +0,0 @@
# Copyright: (c) 2020, Amin Vakil <info@aminvakil.com>
# Copyright: (c) 2016-2018, Matt Davis <mdavis@ansible.com>
# Copyright: (c) 2018, Sam Doran <sdoran@redhat.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible.errors import AnsibleError, AnsibleConnectionFailure
from ansible.module_utils._text import to_native, to_text
from ansible.module_utils.common.collections import is_string
from ansible.plugins.action import ActionBase
from ansible.utils.display import Display
display = Display()
class TimedOutException(Exception):
pass
class ActionModule(ActionBase):
TRANSFERS_FILES = False
_VALID_ARGS = frozenset((
'msg',
'delay',
'search_paths'
))
DEFAULT_CONNECT_TIMEOUT = None
DEFAULT_PRE_SHUTDOWN_DELAY = 0
DEFAULT_SHUTDOWN_MESSAGE = 'Shut down initiated by Ansible'
DEFAULT_SHUTDOWN_COMMAND = 'shutdown'
DEFAULT_SHUTDOWN_COMMAND_ARGS = '-h {delay_min} "{message}"'
DEFAULT_SUDOABLE = True
SHUTDOWN_COMMANDS = {
'alpine': 'poweroff',
'vmkernel': 'halt',
}
SHUTDOWN_COMMAND_ARGS = {
'alpine': '',
'void': '-h +{delay_min} "{message}"',
'freebsd': '-h +{delay_sec}s "{message}"',
'linux': DEFAULT_SHUTDOWN_COMMAND_ARGS,
'macosx': '-h +{delay_min} "{message}"',
'openbsd': '-h +{delay_min} "{message}"',
'solaris': '-y -g {delay_sec} -i 5 "{message}"',
'sunos': '-y -g {delay_sec} -i 5 "{message}"',
'vmkernel': '-d {delay_sec}',
'aix': '-Fh',
}
def __init__(self, *args, **kwargs):
super(ActionModule, self).__init__(*args, **kwargs)
@property
def delay(self):
return self._check_delay('delay', self.DEFAULT_PRE_SHUTDOWN_DELAY)
def _check_delay(self, key, default):
"""Ensure that the value is positive or zero"""
value = int(self._task.args.get(key, default))
if value < 0:
value = 0
return value
def _get_value_from_facts(self, variable_name, distribution, default_value):
"""Get dist+version specific args first, then distribution, then family, lastly use default"""
attr = getattr(self, variable_name)
value = attr.get(
distribution['name'] + distribution['version'],
attr.get(
distribution['name'],
attr.get(
distribution['family'],
getattr(self, default_value))))
return value
def get_shutdown_command_args(self, distribution):
args = self._get_value_from_facts('SHUTDOWN_COMMAND_ARGS', distribution, 'DEFAULT_SHUTDOWN_COMMAND_ARGS')
# Convert seconds to minutes. If less that 60, set it to 0.
delay_sec = self.delay
shutdown_message = self._task.args.get('msg', self.DEFAULT_SHUTDOWN_MESSAGE)
return args.format(delay_sec=delay_sec, delay_min=delay_sec // 60, message=shutdown_message)
def get_distribution(self, task_vars):
# FIXME: only execute the module if we don't already have the facts we need
distribution = {}
display.debug('{action}: running setup module to get distribution'.format(action=self._task.action))
module_output = self._execute_module(
task_vars=task_vars,
module_name='ansible.legacy.setup',
module_args={'gather_subset': 'min'})
try:
if module_output.get('failed', False):
raise AnsibleError('Failed to determine system distribution. {0}, {1}'.format(
to_native(module_output['module_stdout']).strip(),
to_native(module_output['module_stderr']).strip()))
distribution['name'] = module_output['ansible_facts']['ansible_distribution'].lower()
distribution['version'] = to_text(module_output['ansible_facts']['ansible_distribution_version'].split('.')[0])
distribution['family'] = to_text(module_output['ansible_facts']['ansible_os_family'].lower())
display.debug("{action}: distribution: {dist}".format(action=self._task.action, dist=distribution))
return distribution
except KeyError as ke:
raise AnsibleError('Failed to get distribution information. Missing "{0}" in output.'.format(ke.args[0]))
def get_shutdown_command(self, task_vars, distribution):
shutdown_bin = self._get_value_from_facts('SHUTDOWN_COMMANDS', distribution, 'DEFAULT_SHUTDOWN_COMMAND')
default_search_paths = ['/sbin', '/usr/sbin', '/usr/local/sbin']
search_paths = self._task.args.get('search_paths', default_search_paths)
# FIXME: switch all this to user arg spec validation methods when they are available
# Convert bare strings to a list
if is_string(search_paths):
search_paths = [search_paths]
# Error if we didn't get a list
err_msg = "'search_paths' must be a string or flat list of strings, got {0}"
try:
incorrect_type = any(not is_string(x) for x in search_paths)
if not isinstance(search_paths, list) or incorrect_type:
raise TypeError
except TypeError:
raise AnsibleError(err_msg.format(search_paths))
display.debug('{action}: running find module looking in {paths} to get path for "{command}"'.format(
action=self._task.action,
command=shutdown_bin,
paths=search_paths))
find_result = self._execute_module(
task_vars=task_vars,
# prevent collection search by calling with ansible.legacy (still allows library/ override of find)
module_name='ansible.legacy.find',
module_args={
'paths': search_paths,
'patterns': [shutdown_bin],
'file_type': 'any'
}
)
full_path = [x['path'] for x in find_result['files']]
if not full_path:
raise AnsibleError('Unable to find command "{0}" in search paths: {1}'.format(shutdown_bin, search_paths))
self._shutdown_command = full_path[0]
return self._shutdown_command
def perform_shutdown(self, task_vars, distribution):
result = {}
shutdown_result = {}
shutdown_command = self.get_shutdown_command(task_vars, distribution)
shutdown_command_args = self.get_shutdown_command_args(distribution)
shutdown_command_exec = '{0} {1}'.format(shutdown_command, shutdown_command_args)
self.cleanup(force=True)
try:
display.vvv("{action}: shutting down server...".format(action=self._task.action))
display.debug("{action}: shutting down server with command '{command}'".format(action=self._task.action, command=shutdown_command_exec))
if self._play_context.check_mode:
shutdown_result['rc'] = 0
else:
shutdown_result = self._low_level_execute_command(shutdown_command_exec, sudoable=self.DEFAULT_SUDOABLE)
except AnsibleConnectionFailure as e:
# If the connection is closed too quickly due to the system being shutdown, carry on
display.debug('{action}: AnsibleConnectionFailure caught and handled: {error}'.format(action=self._task.action, error=to_text(e)))
shutdown_result['rc'] = 0
if shutdown_result['rc'] != 0:
result['failed'] = True
result['shutdown'] = False
result['msg'] = "Shutdown command failed. Error was {stdout}, {stderr}".format(
stdout=to_native(shutdown_result['stdout'].strip()),
stderr=to_native(shutdown_result['stderr'].strip()))
return result
result['failed'] = False
result['shutdown_command'] = shutdown_command_exec
return result
def run(self, tmp=None, task_vars=None):
self._supports_check_mode = True
self._supports_async = True
# If running with local connection, fail so we don't shutdown ourself
if self._connection.transport == 'local' and (not self._play_context.check_mode):
msg = 'Running {0} with local connection would shutdown the control node.'.format(self._task.action)
return {'changed': False, 'elapsed': 0, 'shutdown': False, 'failed': True, 'msg': msg}
if task_vars is None:
task_vars = {}
result = super(ActionModule, self).run(tmp, task_vars)
if result.get('skipped', False) or result.get('failed', False):
return result
distribution = self.get_distribution(task_vars)
# Initiate shutdown
shutdown_result = self.perform_shutdown(task_vars, distribution)
if shutdown_result['failed']:
result = shutdown_result
return result
result['shutdown'] = True
result['changed'] = True
result['shutdown_command'] = shutdown_result['shutdown_command']
return result

View File

@@ -5,7 +5,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
name: doas
become: doas
short_description: Do As user
description:
- This become plugins allows your remote/login user to execute commands as another user via the doas utility.
@@ -40,7 +40,7 @@ DOCUMENTATION = '''
- name: ANSIBLE_DOAS_EXE
become_flags:
description: Options to pass to doas
default: ''
default:
ini:
- section: privilege_escalation
key: become_flags
@@ -117,8 +117,9 @@ class BecomeModule(BecomeBase):
if not self.get_option('become_pass') and '-n' not in flags:
flags += ' -n'
become_user = self.get_option('become_user')
user = '-u %s' % (become_user) if become_user else ''
user = self.get_option('become_user')
if user:
user = '-u %s' % (user)
success_cmd = self._build_success_command(cmd, shell, noexe=True)
executable = getattr(shell, 'executable', shell.SHELL_FAMILY)

View File

@@ -4,7 +4,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
name: dzdo
become: dzdo
short_description: Centrify's Direct Authorize
description:
- This become plugins allows your remote/login user to execute commands as another user via the dzdo utility.
@@ -89,7 +89,8 @@ class BecomeModule(BecomeBase):
self.prompt = '[dzdo via ansible, key=%s] password:' % self._id
flags = '%s -p "%s"' % (flags.replace('-n', ''), self.prompt)
become_user = self.get_option('become_user')
user = '-u %s' % (become_user) if become_user else ''
user = self.get_option('become_user')
if user:
user = '-u %s' % (user)
return ' '.join([becomecmd, flags, user, self._build_success_command(cmd, shell)])

View File

@@ -5,7 +5,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
name: ksu
become: ksu
short_description: Kerberos substitute user
description:
- This become plugins allows your remote/login user to execute commands as another user via the ksu utility.
@@ -13,6 +13,7 @@ DOCUMENTATION = '''
options:
become_user:
description: User you 'become' to execute the task
default: ''
ini:
- section: privilege_escalation
key: become_user

View File

@@ -5,7 +5,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
name: machinectl
become: machinectl
short_description: Systemd's machinectl privilege escalation
description:
- This become plugins allows your remote/login user to execute commands as another user via the machinectl utility.

View File

@@ -5,7 +5,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
name: pbrun
become: pbrun
short_description: PowerBroker run
description:
- This become plugins allows your remote/login user to execute commands as another user via the pbrun utility.
@@ -97,8 +97,9 @@ class BecomeModule(BecomeBase):
become_exe = self.get_option('become_exe')
flags = self.get_option('become_flags')
become_user = self.get_option('become_user')
user = '-u %s' % (become_user) if become_user else ''
user = self.get_option('become_user')
if user:
user = '-u %s' % (user)
noexe = not self.get_option('wrap_exe')
return ' '.join([become_exe, flags, user, self._build_success_command(cmd, shell, noexe=noexe)])

View File

@@ -5,7 +5,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
name: pfexec
become: pfexec
short_description: profile based execution
description:
- This become plugins allows your remote/login user to execute commands as another user via the pfexec utility.
@@ -14,7 +14,7 @@ DOCUMENTATION = '''
become_user:
description:
- User you 'become' to execute the task
- This plugin ignores this setting as pfexec uses it's own C(exec_attr) to figure this out,
- This plugin ignores this setting as pfexec uses it's own ``exec_attr`` to figure this out,
but it is supplied here for Ansible to make decisions needed for the task execution, like file permissions.
default: root
ini:
@@ -80,8 +80,8 @@ DOCUMENTATION = '''
- name: ansible_pfexec_wrap_execution
env:
- name: ANSIBLE_PFEXEC_WRAP_EXECUTION
notes:
- This plugin ignores I(become_user) as pfexec uses it's own C(exec_attr) to figure this out.
note:
- This plugin ignores ``become_user`` as pfexec uses it's own ``exec_attr`` to figure this out.
'''
from ansible.plugins.become import BecomeBase

View File

@@ -5,7 +5,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
name: pmrun
become: pmrun
short_description: Privilege Manager run
description:
- This become plugins allows your remote/login user to execute commands as another user via the pmrun utility.

View File

@@ -5,7 +5,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
name: sesu
become: sesu
short_description: CA Privileged Access Manager
description:
- This become plugins allows your remote/login user to execute commands as another user via the sesu utility.

View File

@@ -1,91 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = """
name: sudosu
short_description: Run tasks using sudo su -
description:
- This become plugins allows your remote/login user to execute commands as another user via the C(sudo) and C(su) utilities combined.
author:
- Dag Wieers (@dagwieers)
version_added: 2.4.0
options:
become_user:
description: User you 'become' to execute the task.
default: root
ini:
- section: privilege_escalation
key: become_user
- section: sudo_become_plugin
key: user
vars:
- name: ansible_become_user
- name: ansible_sudo_user
env:
- name: ANSIBLE_BECOME_USER
- name: ANSIBLE_SUDO_USER
become_flags:
description: Options to pass to C(sudo).
default: -H -S -n
ini:
- section: privilege_escalation
key: become_flags
- section: sudo_become_plugin
key: flags
vars:
- name: ansible_become_flags
- name: ansible_sudo_flags
env:
- name: ANSIBLE_BECOME_FLAGS
- name: ANSIBLE_SUDO_FLAGS
become_pass:
description: Password to pass to C(sudo).
required: false
vars:
- name: ansible_become_password
- name: ansible_become_pass
- name: ansible_sudo_pass
env:
- name: ANSIBLE_BECOME_PASS
- name: ANSIBLE_SUDO_PASS
ini:
- section: sudo_become_plugin
key: password
"""
from ansible.plugins.become import BecomeBase
class BecomeModule(BecomeBase):
name = 'community.general.sudosu'
# messages for detecting prompted password issues
fail = ('Sorry, try again.',)
missing = ('Sorry, a password is required to run sudo', 'sudo: a password is required')
def build_become_command(self, cmd, shell):
super(BecomeModule, self).build_become_command(cmd, shell)
if not cmd:
return cmd
becomecmd = 'sudo'
flags = self.get_option('become_flags') or ''
prompt = ''
if self.get_option('become_pass'):
self.prompt = '[sudo via ansible, key=%s] password:' % self._id
if flags: # this could be simplified, but kept as is for now for backwards string matching
flags = flags.replace('-n', '')
prompt = '-p "%s"' % (self.prompt)
user = self.get_option('become_user') or ''
if user:
user = '%s' % (user)
return ' '.join([becomecmd, flags, prompt, 'su -l', user, self._build_success_command(cmd, shell)])

View File

@@ -6,8 +6,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: memcached
cache: memcached
short_description: Use memcached DB for cache
description:
- This cache uses JSON formatted, per host records saved in memcached.
@@ -53,14 +52,12 @@ from ansible import constants as C
from ansible.errors import AnsibleError
from ansible.module_utils.common._collections_compat import MutableSet
from ansible.plugins.cache import BaseCacheModule
from ansible.release import __version__ as ansible_base_version
from ansible.utils.display import Display
try:
import memcache
HAS_MEMCACHE = True
except ImportError:
HAS_MEMCACHE = False
raise AnsibleError("python-memcached is required for the memcached fact cache")
display = Display()
@@ -162,7 +159,7 @@ class CacheModuleKeys(MutableSet):
self._cache.set(self.PREFIX, self._keyset)
def remove_by_timerange(self, s_min, s_max):
for k in list(self._keyset.keys()):
for k in self._keyset.keys():
t = self._keyset[k]
if s_min < t < s_max:
del self._keyset[k]
@@ -181,17 +178,14 @@ class CacheModule(BaseCacheModule):
self._timeout = self.get_option('_timeout')
self._prefix = self.get_option('_prefix')
except KeyError:
# TODO: remove once we no longer support Ansible 2.9
if not ansible_base_version.startswith('2.9.'):
raise AnsibleError("Do not import CacheModules directly. Use ansible.plugins.loader.cache_loader instead.")
display.deprecated('Rather than importing CacheModules directly, '
'use ansible.plugins.loader.cache_loader',
version='2.0.0', collection_name='community.general') # was Ansible 2.12
if C.CACHE_PLUGIN_CONNECTION:
connection = C.CACHE_PLUGIN_CONNECTION.split(',')
self._timeout = C.CACHE_PLUGIN_TIMEOUT
self._prefix = C.CACHE_PLUGIN_PREFIX
if not HAS_MEMCACHE:
raise AnsibleError("python-memcached is required for the memcached fact cache")
self._cache = {}
self._db = ProxyClientPool(connection, debug=0)
self._keys = CacheModuleKeys(self._db, self._db.get(CacheModuleKeys.PREFIX) or [])

View File

@@ -7,7 +7,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
name: pickle
cache: pickle
short_description: Pickle formatted files.
description:
- This cache uses Python's pickle serialization format, in per host files, saved to the filesystem.

View File

@@ -5,8 +5,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: redis
cache: redis
short_description: Use Redis DB for cache
description:
- This cache uses JSON formatted, per host records saved in Redis.
@@ -18,7 +17,6 @@ DOCUMENTATION = '''
- A colon separated string of connection information for Redis.
- 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
@@ -33,23 +31,6 @@ DOCUMENTATION = '''
ini:
- key: fact_caching_prefix
section: defaults
_keyset_name:
description: User defined name for cache keyset name.
default: ansible_cache_keys
env:
- name: ANSIBLE_CACHE_REDIS_KEYSET_NAME
ini:
- key: fact_caching_redis_keyset_name
section: defaults
version_added: 1.3.0
_sentinel_service_name:
description: The redis sentinel service name (or referenced as cluster name).
env:
- name: ANSIBLE_CACHE_REDIS_SENTINEL
ini:
- key: fact_caching_redis_sentinel
section: defaults
version_added: 1.3.0
_timeout:
default: 86400
description: Expiration timeout in seconds for the cache plugin data. Set to 0 to never expire
@@ -66,17 +47,14 @@ import json
from ansible import constants as C
from ansible.errors import AnsibleError
from ansible.module_utils._text import to_native
from ansible.parsing.ajson import AnsibleJSONEncoder, AnsibleJSONDecoder
from ansible.plugins.cache import BaseCacheModule
from ansible.release import __version__ as ansible_base_version
from ansible.utils.display import Display
try:
from redis import StrictRedis, VERSION
HAS_REDIS = True
except ImportError:
HAS_REDIS = False
raise AnsibleError("The 'redis' python module (version 2.4.5 or newer) is required for the redis fact cache, 'pip install redis'")
display = Display()
@@ -90,8 +68,6 @@ class CacheModule(BaseCacheModule):
to expire keys. This mechanism is used or a pattern matched 'scan' for
performance.
"""
_sentinel_service_name = None
def __init__(self, *args, **kwargs):
uri = ''
@@ -101,70 +77,25 @@ class CacheModule(BaseCacheModule):
uri = self.get_option('_uri')
self._timeout = float(self.get_option('_timeout'))
self._prefix = self.get_option('_prefix')
self._keys_set = self.get_option('_keyset_name')
self._sentinel_service_name = self.get_option('_sentinel_service_name')
except KeyError:
# TODO: remove once we no longer support Ansible 2.9
if not ansible_base_version.startswith('2.9.'):
raise AnsibleError("Do not import CacheModules directly. Use ansible.plugins.loader.cache_loader instead.")
display.deprecated('Rather than importing CacheModules directly, '
'use ansible.plugins.loader.cache_loader',
version='2.0.0', collection_name='community.general') # was Ansible 2.12
if C.CACHE_PLUGIN_CONNECTION:
uri = C.CACHE_PLUGIN_CONNECTION
self._timeout = float(C.CACHE_PLUGIN_TIMEOUT)
self._prefix = C.CACHE_PLUGIN_PREFIX
self._keys_set = 'ansible_cache_keys'
if not HAS_REDIS:
raise AnsibleError("The 'redis' python module (version 2.4.5 or newer) is required for the redis fact cache, 'pip install redis'")
self._cache = {}
kw = {}
# tls connection
tlsprefix = 'tls://'
if uri.startswith(tlsprefix):
kw['ssl'] = True
uri = uri[len(tlsprefix):]
# redis sentinel connection
if self._sentinel_service_name:
self._db = self._get_sentinel_connection(uri, kw)
# normal connection
else:
connection = uri.split(':')
self._db = StrictRedis(*connection, **kw)
display.vv('Redis connection: %s' % self._db)
def _get_sentinel_connection(self, uri, kw):
"""
get sentinel connection details from _uri
"""
try:
from redis.sentinel import Sentinel
except ImportError:
raise AnsibleError("The 'redis' python module (version 2.9.0 or newer) is required to use redis sentinel.")
if ';' not in uri:
raise AnsibleError('_uri does not have sentinel syntax.')
# format: "localhost:26379;localhost2:26379;0:changeme"
connections = uri.split(';')
connection_args = connections.pop(-1)
if len(connection_args) > 0: # hanle if no db nr is given
connection_args = connection_args.split(':')
kw['db'] = connection_args.pop(0)
try:
kw['password'] = connection_args.pop(0)
except IndexError:
pass # password is optional
sentinels = [tuple(shost.split(':')) for shost in connections]
display.vv('\nUsing redis sentinels: %s' % sentinels)
scon = Sentinel(sentinels, **kw)
try:
return scon.master_for(self._sentinel_service_name, socket_timeout=0.2)
except Exception as exc:
raise AnsibleError('Could not connect to redis sentinel: %s' % to_native(exc))
connection = uri.split(':')
self._db = StrictRedis(*connection, **kw)
self._keys_set = 'ansible_cache_keys'
def _make_key(self, key):
return self._prefix + key
@@ -217,12 +148,14 @@ class CacheModule(BaseCacheModule):
self._db.zrem(self._keys_set, key)
def flush(self):
for key in list(self.keys()):
for key in self.keys():
self.delete(key)
def copy(self):
# TODO: there is probably a better way to do this in redis
ret = dict([(k, self.get(k)) for k in self.keys()])
ret = dict()
for key in self.keys():
ret[key] = self.get(key)
return ret
def __getstate__(self):

View File

@@ -7,7 +7,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
name: yaml
cache: yaml
short_description: YAML formatted files.
description:
- This cache uses YAML formatted, per host, files saved to the filesystem.

View File

@@ -0,0 +1,60 @@
# (c) 2015, Andrew Gaffney <andrew@agaffney.org>
# (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
callback: actionable
type: stdout
short_description: shows only items that need attention
description:
- Use this callback when you dont care about OK nor Skipped.
- This callback suppresses any non Failed or Changed status.
deprecated:
why: The 'default' callback plugin now supports this functionality
removed_in: '2.0.0' # was Ansible 2.11
alternative: "'default' callback plugin with 'display_skipped_hosts = no' and 'display_ok_hosts = no' options"
extends_documentation_fragment:
- default_callback
requirements:
- set as stdout callback in configuration
# Override defaults from 'default' callback plugin
options:
display_skipped_hosts:
name: Show skipped hosts
description: "Toggle to control displaying skipped task/host results in a task"
type: bool
default: no
env:
- name: DISPLAY_SKIPPED_HOSTS
deprecated:
why: environment variables without "ANSIBLE_" prefix are deprecated
version: "2.0.0" # was Ansible 2.12
alternatives: the "ANSIBLE_DISPLAY_SKIPPED_HOSTS" environment variable
- name: ANSIBLE_DISPLAY_SKIPPED_HOSTS
ini:
- key: display_skipped_hosts
section: defaults
display_ok_hosts:
name: Show 'ok' hosts
description: "Toggle to control displaying 'ok' task/host results in a task"
type: bool
default: no
env:
- name: ANSIBLE_DISPLAY_OK_HOSTS
ini:
- key: display_ok_hosts
section: defaults
'''
from ansible.plugins.callback.default import CallbackModule as CallbackModule_default
class CallbackModule(CallbackModule_default):
CALLBACK_VERSION = 2.0
CALLBACK_TYPE = 'stdout'
CALLBACK_NAME = 'community.general.actionable'

View File

@@ -7,9 +7,8 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: cgroup_memory_recap
type: aggregate
callback: cgroup_memory_recap
callback_type: aggregate
requirements:
- whitelist in configuration
- cgroups

View File

@@ -6,8 +6,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: context_demo
callback: context_demo
type: aggregate
short_description: demo callback that adds play/task context
description:

View File

@@ -6,10 +6,14 @@
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible import constants as C
from ansible.plugins.callback import CallbackBase
from ansible.utils.color import colorize, hostcolor
from ansible.template import Templar
from ansible.playbook.task_include import TaskInclude
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: counter_enabled
callback: counter_enabled
type: stdout
short_description: adds counters to the output items (tasks and hosts/task)
description:
@@ -22,12 +26,6 @@ DOCUMENTATION = '''
- set as stdout callback in ansible.cfg (stdout_callback = counter_enabled)
'''
from ansible import constants as C
from ansible.plugins.callback import CallbackBase
from ansible.utils.color import colorize, hostcolor
from ansible.template import Templar
from ansible.playbook.task_include import TaskInclude
class CallbackModule(CallbackBase):

View File

@@ -6,7 +6,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
name: dense
callback: dense
type: stdout
short_description: minimal stdout output
extends_documentation_fragment:

View File

@@ -7,8 +7,8 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r'''
name: diy
type: stdout
callback: diy
callback_type: stdout
short_description: Customize the output
version_added: 0.2.0
description:
@@ -629,7 +629,7 @@ playbook.yml: >
gather_facts: no
tasks:
- name: Default plugin output
ansible.builtin.debug:
debug:
msg: default plugin output
- name: Override from play vars
@@ -687,11 +687,11 @@ playbook.yml: >
tasks:
- name: Custom banner with default plugin result output
ansible.builtin.debug:
debug:
msg: "default plugin output: result example"
- name: Override from task vars
ansible.builtin.debug:
debug:
msg: "example {{ two }}"
changed_when: true
vars:
@@ -703,14 +703,14 @@ playbook.yml: >
ansible_callback_diy_runner_on_ok_msg_color: "{{ 'yellow' if ansible_callback_diy.result.is_changed else 'bright green' }}"
- name: Suppress output
ansible.builtin.debug:
debug:
msg: i should not be displayed
vars:
ansible_callback_diy_playbook_on_task_start_msg: ""
ansible_callback_diy_runner_on_ok_msg: ""
- name: Using alias vars (see ansible.cfg)
ansible.builtin.debug:
debug:
msg:
when: False
vars:
@@ -719,13 +719,13 @@ playbook.yml: >
on_skipped_msg_color: white
- name: Just stdout
ansible.builtin.command: echo some stdout
command: echo some stdout
vars:
ansible_callback_diy_playbook_on_task_start_msg: "\n"
ansible_callback_diy_runner_on_ok_msg: "{{ ansible_callback_diy.result.output.stdout }}\n"
- name: Multiline output
ansible.builtin.debug:
debug:
msg: "{{ multiline }}"
vars:
ansible_callback_diy_playbook_on_task_start_msg: "\nDIY output(via task vars): task example: {{ ansible_callback_diy.task.name }}"
@@ -738,7 +738,7 @@ playbook.yml: >
ansible_callback_diy_playbook_on_task_start_msg_color: bright blue
- name: Indentation
ansible.builtin.debug:
debug:
msg: "{{ item.msg }}"
with_items:
- { indent: 1, msg: one., color: red }
@@ -751,14 +751,14 @@ playbook.yml: >
ansible_callback_diy_runner_on_ok_msg_color: bright green
- name: Using lookup and template as file
ansible.builtin.shell: "echo {% raw %}'output from {{ file_name }}'{% endraw %} > {{ file_name }}"
shell: "echo {% raw %}'output from {{ file_name }}'{% endraw %} > {{ file_name }}"
vars:
ansible_callback_diy_playbook_on_task_start_msg: "\nDIY output(via task vars): task example: {{ ansible_callback_diy.task.name }}"
file_name: diy_file_template_example
ansible_callback_diy_runner_on_ok_msg: "{{ lookup('template', file_name) }}"
- name: 'Look at top level vars available to the "runner_on_ok" callback'
ansible.builtin.debug:
debug:
msg: ''
vars:
ansible_callback_diy_playbook_on_task_start_msg: "\nDIY output(via task vars): task example: {{ ansible_callback_diy.task.name }}"
@@ -771,7 +771,7 @@ playbook.yml: >
ansible_callback_diy_runner_on_ok_msg_color: white
- name: 'Look at event data available to the "runner_on_ok" callback'
ansible.builtin.debug:
debug:
msg: ''
vars:
ansible_callback_diy_playbook_on_task_start_msg: "\nDIY output(via task vars): task example: {{ ansible_callback_diy.task.name }}"
@@ -1013,7 +1013,7 @@ class CallbackModule(Default):
for attr in _stats_attributes:
_ret[self.DIY_NS]['stats'].update({attr: _get_value(obj=stats, attr=attr)})
_ret[self.DIY_NS].update({'top_level_var_names': list(_ret.keys())})
_ret[self.DIY_NS].update({'top_level_var_names': _ret.keys()})
return _ret

View File

@@ -0,0 +1,75 @@
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
# (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
callback: full_skip
type: stdout
short_description: suppresses tasks if all hosts skipped
description:
- Use this plugin when you do not care about any output for tasks that were completely skipped
deprecated:
why: The 'default' callback plugin now supports this functionality
removed_in: '2.0.0' # was Ansible 2.11
alternative: "'default' callback plugin with 'display_skipped_hosts = no' option"
extends_documentation_fragment:
- default_callback
requirements:
- set as stdout in configuration
'''
from ansible.plugins.callback.default import CallbackModule as CallbackModule_default
class CallbackModule(CallbackModule_default):
'''
This is the default callback interface, which simply prints messages
to stdout when new callback events are received.
'''
CALLBACK_VERSION = 2.0
CALLBACK_TYPE = 'stdout'
CALLBACK_NAME = 'community.general.full_skip'
def v2_runner_on_skipped(self, result):
self.outlines = []
def v2_playbook_item_on_skipped(self, result):
self.outlines = []
def v2_runner_item_on_skipped(self, result):
self.outlines = []
def v2_runner_on_failed(self, result, ignore_errors=False):
self.display()
super(CallbackModule, self).v2_runner_on_failed(result, ignore_errors)
def v2_playbook_on_task_start(self, task, is_conditional):
self.outlines = []
self.outlines.append("TASK [%s]" % task.get_name().strip())
if self._display.verbosity >= 2:
path = task.get_path()
if path:
self.outlines.append("task path: %s" % path)
def v2_playbook_item_on_ok(self, result):
self.display()
super(CallbackModule, self).v2_playbook_item_on_ok(result)
def v2_runner_on_ok(self, result):
self.display()
super(CallbackModule, self).v2_runner_on_ok(result)
def display(self):
if len(self.outlines) == 0:
return
(first, rest) = self.outlines[0], self.outlines[1:]
self._display.banner(first)
for line in rest:
self._display.display(line)
self.outlines = []

View File

@@ -6,9 +6,8 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: hipchat
type: notification
callback: hipchat
callback_type: notification
requirements:
- whitelist in configuration.
- prettytable (python lib)
@@ -173,7 +172,8 @@ class CallbackModule(CallbackBase):
# Displays info about playbook being started by a person on an
# inventory, as well as Tags, Skip Tags and Limits
if not self.printed_playbook:
self.playbook_name, dummy = os.path.splitext(os.path.basename(self.play.playbook.filename))
self.playbook_name, _ = os.path.splitext(
os.path.basename(self.play.playbook.filename))
host_list = self.play.playbook.inventory.host_list
inventory = os.path.basename(os.path.realpath(host_list))
self.send_msg("%s: Playbook initiated by %s against %s" %

View File

@@ -6,8 +6,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: jabber
callback: jabber
type: notification
short_description: post task events to a jabber server
description:

View File

@@ -6,8 +6,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: log_plays
callback: log_plays
type: notification
short_description: write playbook output to log file
description:
@@ -54,7 +53,7 @@ class CallbackModule(CallbackBase):
CALLBACK_NEEDS_WHITELIST = True
TIME_FORMAT = "%b %d %Y %H:%M:%S"
MSG_FORMAT = "%(now)s - %(playbook)s - %(task_name)s - %(task_action)s - %(category)s - %(data)s\n\n"
MSG_FORMAT = "%(now)s - %(category)s - %(data)s\n\n"
def __init__(self):
@@ -68,8 +67,7 @@ class CallbackModule(CallbackBase):
if not os.path.exists(self.log_folder):
makedirs_safe(self.log_folder)
def log(self, result, category):
data = result._result
def log(self, host, category, data):
if isinstance(data, MutableMapping):
if '_ansible_verbose_override' in data:
# avoid logging extraneous data
@@ -81,43 +79,30 @@ class CallbackModule(CallbackBase):
if invocation is not None:
data = json.dumps(invocation) + " => %s " % data
path = os.path.join(self.log_folder, result._host.get_name())
path = os.path.join(self.log_folder, host)
now = time.strftime(self.TIME_FORMAT, time.localtime())
msg = to_bytes(
self.MSG_FORMAT
% dict(
now=now,
playbook=self.playbook,
task_name=result._task.name,
task_action=result._task.action,
category=category,
data=data,
)
)
msg = to_bytes(self.MSG_FORMAT % dict(now=now, category=category, data=data))
with open(path, "ab") as fd:
fd.write(msg)
def v2_runner_on_failed(self, result, ignore_errors=False):
self.log(result, 'FAILED')
def runner_on_failed(self, host, res, ignore_errors=False):
self.log(host, 'FAILED', res)
def v2_runner_on_ok(self, result):
self.log(result, 'OK')
def runner_on_ok(self, host, res):
self.log(host, 'OK', res)
def v2_runner_on_skipped(self, result):
self.log(result, 'SKIPPED')
def runner_on_skipped(self, host, item=None):
self.log(host, 'SKIPPED', '...')
def v2_runner_on_unreachable(self, result):
self.log(result, 'UNREACHABLE')
def runner_on_unreachable(self, host, res):
self.log(host, 'UNREACHABLE', res)
def v2_runner_on_async_failed(self, result):
self.log(result, 'ASYNC_FAILED')
def runner_on_async_failed(self, host, res, jid):
self.log(host, 'ASYNC_FAILED', res)
def v2_playbook_on_start(self, playbook):
self.playbook = playbook._file_name
def playbook_on_import_for_host(self, host, imported_file):
self.log(host, 'IMPORTED', imported_file)
def v2_playbook_on_import_for_host(self, result, imported_file):
self.log(result, 'IMPORTED', imported_file)
def v2_playbook_on_not_import_for_host(self, result, missing_file):
self.log(result, 'NOTIMPORTED', missing_file)
def playbook_on_not_import_for_host(self, host, missing_file):
self.log(host, 'NOTIMPORTED', missing_file)

View File

@@ -1,234 +0,0 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
name: loganalytics
type: aggregate
short_description: Posts task results to Azure Log Analytics
author: "Cyrus Li (@zhcli) <cyrus1006@gmail.com>"
description:
- This callback plugin will post task results in JSON formatted to an Azure Log Analytics workspace.
- Credits to authors of splunk callback plugin.
version_added: "2.4.0"
requirements:
- Whitelisting this callback plugin.
- An Azure log analytics work space has been established.
options:
workspace_id:
description: Workspace ID of the Azure log analytics workspace.
required: true
env:
- name: WORKSPACE_ID
ini:
- section: callback_loganalytics
key: workspace_id
shared_key:
description: Shared key to connect to Azure log analytics workspace.
required: true
env:
- name: WORKSPACE_SHARED_KEY
ini:
- section: callback_loganalytics
key: shared_key
'''
EXAMPLES = '''
examples: |
Whitelist the plugin in ansible.cfg:
[defaults]
callback_whitelist = community.general.loganalytics
Set the environment variable:
export WORKSPACE_ID=01234567-0123-0123-0123-01234567890a
export WORKSPACE_SHARED_KEY=dZD0kCbKl3ehZG6LHFMuhtE0yHiFCmetzFMc2u+roXIUQuatqU924SsAAAAPemhjbGlAemhjbGktTUJQAQIDBA==
Or configure the plugin in ansible.cfg in the callback_loganalytics block:
[callback_loganalytics]
workspace_id = 01234567-0123-0123-0123-01234567890a
shared_key = dZD0kCbKl3ehZG6LHFMuhtE0yHiFCmetzFMc2u+roXIUQuatqU924SsAAAAPemhjbGlAemhjbGktTUJQAQIDBA==
'''
import hashlib
import hmac
import base64
import logging
import json
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
class AzureLogAnalyticsSource(object):
def __init__(self):
self.ansible_check_mode = False
self.ansible_playbook = ""
self.ansible_version = ""
self.session = str(uuid.uuid4())
self.host = socket.gethostname()
self.user = getpass.getuser()
self.extra_vars = ""
def __build_signature(self, date, workspace_id, shared_key, content_length):
# Build authorisation signature for Azure log analytics API call
sigs = "POST\n{0}\napplication/json\nx-ms-date:{1}\n/api/logs".format(
str(content_length), date)
utf8_sigs = sigs.encode('utf-8')
decoded_shared_key = base64.b64decode(shared_key)
hmac_sha256_sigs = hmac.new(
decoded_shared_key, utf8_sigs, digestmod=hashlib.sha256).digest()
encoded_hash = base64.b64encode(hmac_sha256_sigs).decode('utf-8')
signature = "SharedKey {0}:{1}".format(workspace_id, encoded_hash)
return signature
def __build_workspace_url(self, workspace_id):
return "https://{0}.ods.opinsights.azure.com/api/logs?api-version=2016-04-01".format(workspace_id)
def __rfc1123date(self):
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:
self.ansible_check_mode = True
if result._task_fields['args'].get('_ansible_version'):
self.ansible_version = \
result._task_fields['args'].get('_ansible_version')
if result._task._role:
ansible_role = str(result._task._role)
else:
ansible_role = None
data = {}
data['uuid'] = result._task._uuid
data['session'] = self.session
data['status'] = state
data['timestamp'] = self.__rfc1123date()
data['host'] = self.host
data['user'] = self.user
data['runtime'] = runtime
data['ansible_version'] = self.ansible_version
data['ansible_check_mode'] = self.ansible_check_mode
data['ansible_host'] = result._host.name
data['ansible_playbook'] = self.ansible_playbook
data['ansible_role'] = ansible_role
data['ansible_task'] = result._task_fields
# Removing args since it can contain sensitive data
if 'args' in data['ansible_task']:
data['ansible_task'].pop('args')
data['ansible_result'] = result._result
if 'content' in data['ansible_result']:
data['ansible_result'].pop('content')
# Adding extra vars info
data['extra_vars'] = self.extra_vars
# Preparing the playbook logs as JSON format and send to Azure log analytics
jsondata = json.dumps({'event': data}, cls=AnsibleJSONEncoder, sort_keys=True)
content_length = len(jsondata)
rfc1123date = self.__rfc1123date()
signature = self.__build_signature(rfc1123date, workspace_id, shared_key, content_length)
workspace_url = self.__build_workspace_url(workspace_id)
open_url(
workspace_url,
jsondata,
headers={
'content-type': 'application/json',
'Authorization': signature,
'Log-Type': 'ansible_playbook',
'x-ms-date': rfc1123date
},
method='POST'
)
class CallbackModule(CallbackBase):
CALLBACK_VERSION = 2.0
CALLBACK_TYPE = 'aggregate'
CALLBACK_NAME = 'loganalytics'
CALLBACK_NEEDS_WHITELIST = True
def __init__(self, display=None):
super(CallbackModule, self).__init__(display=display)
self.start_datetimes = {} # Collect task start times
self.workspace_id = None
self.shared_key = None
self.loganalytics = AzureLogAnalyticsSource()
def _seconds_since_start(self, result):
return (
datetime.utcnow() -
self.start_datetimes[result._task._uuid]
).total_seconds()
def set_options(self, task_keys=None, var_options=None, direct=None):
super(CallbackModule, self).set_options(task_keys=task_keys, var_options=var_options, direct=direct)
self.workspace_id = self.get_option('workspace_id')
self.shared_key = self.get_option('shared_key')
def v2_playbook_on_play_start(self, play):
vm = play.get_variable_manager()
extra_vars = vm.extra_vars
self.loganalytics.extra_vars = extra_vars
def v2_playbook_on_start(self, playbook):
self.loganalytics.ansible_playbook = basename(playbook._file_name)
def v2_playbook_on_task_start(self, task, is_conditional):
self.start_datetimes[task._uuid] = datetime.utcnow()
def v2_playbook_on_handler_task_start(self, task):
self.start_datetimes[task._uuid] = datetime.utcnow()
def v2_runner_on_ok(self, result, **kwargs):
self.loganalytics.send_event(
self.workspace_id,
self.shared_key,
'OK',
result,
self._seconds_since_start(result)
)
def v2_runner_on_skipped(self, result, **kwargs):
self.loganalytics.send_event(
self.workspace_id,
self.shared_key,
'SKIPPED',
result,
self._seconds_since_start(result)
)
def v2_runner_on_failed(self, result, **kwargs):
self.loganalytics.send_event(
self.workspace_id,
self.shared_key,
'FAILED',
result,
self._seconds_since_start(result)
)
def runner_on_async_failed(self, result, **kwargs):
self.loganalytics.send_event(
self.workspace_id,
self.shared_key,
'FAILED',
result,
self._seconds_since_start(result)
)
def v2_runner_on_unreachable(self, result, **kwargs):
self.loganalytics.send_event(
self.workspace_id,
self.shared_key,
'UNREACHABLE',
result,
self._seconds_since_start(result)
)

View File

@@ -5,9 +5,8 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: logdna
type: aggregate
callback: logdna
callback_type: aggregate
short_description: Sends playbook logs to LogDNA
description:
- This callback will report logs from playbook actions, tasks, and events to LogDNA (https://app.logdna.com)

View File

@@ -5,8 +5,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: logentries
callback: logentries
type: notification
short_description: Sends events to Logentries
description:
@@ -76,7 +75,7 @@ examples: >
To enable, add this to your ansible.cfg file in the defaults block
[defaults]
callback_whitelist = community.general.logentries
callback_whitelist = logentries
Either set the environment variables
export LOGENTRIES_API=data.logentries.com

View File

@@ -1,13 +1,12 @@
# (C) 2020, Yevhen Khmelenko <ujenmr@gmail.com>
# (C) 2016, Ievgen Khmelenko <ujenmr@gmail.com>
# (C) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = r'''
author: Yevhen Khmelenko (@ujenmr)
name: logstash
DOCUMENTATION = '''
callback: logstash
type: notification
short_description: Sends events to Logstash
description:
@@ -20,84 +19,27 @@ DOCUMENTATION = r'''
description: Address of the Logstash server
env:
- name: LOGSTASH_SERVER
ini:
- section: callback_logstash
key: server
version_added: 1.0.0
default: localhost
port:
description: Port on which logstash is listening
env:
- name: LOGSTASH_PORT
ini:
- section: callback_logstash
key: port
version_added: 1.0.0
default: 5000
type:
description: Message type
env:
- name: LOGSTASH_TYPE
ini:
- section: callback_logstash
key: type
version_added: 1.0.0
default: ansible
pre_command:
description: Executes command before run and result put to ansible_pre_command_output field.
version_added: 2.0.0
ini:
- section: callback_logstash
key: pre_command
env:
- name: LOGSTASH_PRE_COMMAND
format_version:
description: Logging format
type: str
version_added: 2.0.0
ini:
- section: callback_logstash
key: format_version
env:
- name: LOGSTASH_FORMAT_VERSION
default: v1
choices:
- v1
- v2
'''
EXAMPLES = r'''
ansible.cfg: |
# Enable Callback plugin
[defaults]
callback_whitelist = community.general.logstash
[callback_logstash]
server = logstash.example.com
port = 5000
pre_command = git rev-parse HEAD
type = ansible
11-input-tcp.conf: |
# Enable Logstash TCP Input
input {
tcp {
port => 5000
codec => json
add_field => { "[@metadata][beat]" => "notify" }
add_field => { "[@metadata][type]" => "ansible" }
}
}
'''
import os
import json
import socket
import uuid
import logging
from datetime import datetime
import logging
try:
import logstash
HAS_LOGSTASH = True
@@ -108,6 +50,29 @@ from ansible.plugins.callback import CallbackBase
class CallbackModule(CallbackBase):
"""
ansible logstash callback plugin
ansible.cfg:
callback_plugins = <path_to_callback_plugins_folder>
callback_whitelist = logstash
and put the plugin in <path_to_callback_plugins_folder>
logstash config:
input {
tcp {
port => 5000
codec => json
}
}
Requires:
python-logstash
This plugin makes use of the following environment variables:
LOGSTASH_SERVER (optional): defaults to localhost
LOGSTASH_PORT (optional): defaults to 5000
LOGSTASH_TYPE (optional): defaults to ansible
"""
CALLBACK_VERSION = 2.0
CALLBACK_TYPE = 'aggregate'
@@ -119,67 +84,35 @@ class CallbackModule(CallbackBase):
if not HAS_LOGSTASH:
self.disabled = True
self._display.warning("The required python-logstash/python3-logstash is not installed. "
"pip install python-logstash for Python 2"
"pip install python3-logstash for Python 3")
self.start_time = datetime.utcnow()
def _init_plugin(self):
if not self.disabled:
self._display.warning("The required python-logstash is not installed. "
"pip install python-logstash")
else:
self.logger = logging.getLogger('python-logstash-logger')
self.logger.setLevel(logging.DEBUG)
self.handler = logstash.TCPLogstashHandler(
self.ls_server,
self.ls_port,
os.getenv('LOGSTASH_SERVER', 'localhost'),
int(os.getenv('LOGSTASH_PORT', 5000)),
version=1,
message_type=self.ls_type
message_type=os.getenv('LOGSTASH_TYPE', 'ansible')
)
self.logger.addHandler(self.handler)
self.hostname = socket.gethostname()
self.session = str(uuid.uuid4())
self.session = str(uuid.uuid1())
self.errors = 0
self.base_data = {
'session': self.session,
'host': self.hostname
}
if self.ls_pre_command is not None:
self.base_data['ansible_pre_command_output'] = os.popen(
self.ls_pre_command).read()
if self._options is not None:
self.base_data['ansible_checkmode'] = self._options.check
self.base_data['ansible_tags'] = self._options.tags
self.base_data['ansible_skip_tags'] = self._options.skip_tags
self.base_data['inventory'] = self._options.inventory
def set_options(self, task_keys=None, var_options=None, direct=None):
super(CallbackModule, self).set_options(task_keys=task_keys, var_options=var_options, direct=direct)
self.ls_server = self.get_option('server')
self.ls_port = int(self.get_option('port'))
self.ls_type = self.get_option('type')
self.ls_pre_command = self.get_option('pre_command')
self.ls_format_version = self.get_option('format_version')
self._init_plugin()
self.start_time = datetime.utcnow()
def v2_playbook_on_start(self, playbook):
data = self.base_data.copy()
data['ansible_type'] = "start"
data['status'] = "OK"
data['ansible_playbook'] = playbook._file_name
if (self.ls_format_version == "v2"):
self.logger.info(
"START PLAYBOOK | %s", data['ansible_playbook'], extra=data
)
else:
self.logger.info("ansible start", extra=data)
self.playbook = playbook._file_name
data = {
'status': "OK",
'host': self.hostname,
'session': self.session,
'ansible_type': "start",
'ansible_playbook': self.playbook,
}
self.logger.info("ansible start", extra=data)
def v2_playbook_on_stats(self, stats):
end_time = datetime.utcnow()
@@ -193,201 +126,103 @@ class CallbackModule(CallbackBase):
else:
status = "FAILED"
data = self.base_data.copy()
data['ansible_type'] = "finish"
data['status'] = status
data['ansible_playbook_duration'] = runtime.total_seconds()
data['ansible_result'] = json.dumps(summarize_stat) # deprecated field
if (self.ls_format_version == "v2"):
self.logger.info(
"FINISH PLAYBOOK | %s", json.dumps(summarize_stat), extra=data
)
else:
self.logger.info("ansible stats", extra=data)
def v2_playbook_on_play_start(self, play):
self.play_id = str(play._uuid)
if play.name:
self.play_name = play.name
data = self.base_data.copy()
data['ansible_type'] = "start"
data['status'] = "OK"
data['ansible_play_id'] = self.play_id
data['ansible_play_name'] = self.play_name
if (self.ls_format_version == "v2"):
self.logger.info("START PLAY | %s", self.play_name, extra=data)
else:
self.logger.info("ansible play", extra=data)
def v2_playbook_on_task_start(self, task, is_conditional):
self.task_id = str(task._uuid)
'''
Tasks and handler tasks are dealt with here
'''
data = {
'status': status,
'host': self.hostname,
'session': self.session,
'ansible_type': "finish",
'ansible_playbook': self.playbook,
'ansible_playbook_duration': runtime.total_seconds(),
'ansible_result': json.dumps(summarize_stat),
}
self.logger.info("ansible stats", extra=data)
def v2_runner_on_ok(self, result, **kwargs):
task_name = str(result._task).replace('TASK: ', '').replace('HANDLER: ', '')
data = self.base_data.copy()
if task_name == 'setup':
data['ansible_type'] = "setup"
data['status'] = "OK"
data['ansible_host'] = result._host.name
data['ansible_play_id'] = self.play_id
data['ansible_play_name'] = self.play_name
data['ansible_task'] = task_name
data['ansible_facts'] = self._dump_results(result._result)
if (self.ls_format_version == "v2"):
self.logger.info(
"SETUP FACTS | %s", self._dump_results(result._result), extra=data
)
else:
self.logger.info("ansible facts", extra=data)
else:
if 'changed' in result._result.keys():
data['ansible_changed'] = result._result['changed']
else:
data['ansible_changed'] = False
data['ansible_type'] = "task"
data['status'] = "OK"
data['ansible_host'] = result._host.name
data['ansible_play_id'] = self.play_id
data['ansible_play_name'] = self.play_name
data['ansible_task'] = task_name
data['ansible_task_id'] = self.task_id
data['ansible_result'] = self._dump_results(result._result)
if (self.ls_format_version == "v2"):
self.logger.info(
"TASK OK | %s | RESULT | %s",
task_name, self._dump_results(result._result), extra=data
)
else:
self.logger.info("ansible ok", extra=data)
data = {
'status': "OK",
'host': self.hostname,
'session': self.session,
'ansible_type': "task",
'ansible_playbook': self.playbook,
'ansible_host': result._host.name,
'ansible_task': result._task,
'ansible_result': self._dump_results(result._result)
}
self.logger.info("ansible ok", extra=data)
def v2_runner_on_skipped(self, result, **kwargs):
task_name = str(result._task).replace('TASK: ', '').replace('HANDLER: ', '')
data = self.base_data.copy()
data['ansible_type'] = "task"
data['status'] = "SKIPPED"
data['ansible_host'] = result._host.name
data['ansible_play_id'] = self.play_id
data['ansible_play_name'] = self.play_name
data['ansible_task'] = task_name
data['ansible_task_id'] = self.task_id
data['ansible_result'] = self._dump_results(result._result)
if (self.ls_format_version == "v2"):
self.logger.info("TASK SKIPPED | %s", task_name, extra=data)
else:
self.logger.info("ansible skipped", extra=data)
data = {
'status': "SKIPPED",
'host': self.hostname,
'session': self.session,
'ansible_type': "task",
'ansible_playbook': self.playbook,
'ansible_task': result._task,
'ansible_host': result._host.name
}
self.logger.info("ansible skipped", extra=data)
def v2_playbook_on_import_for_host(self, result, imported_file):
data = self.base_data.copy()
data['ansible_type'] = "import"
data['status'] = "IMPORTED"
data['ansible_host'] = result._host.name
data['ansible_play_id'] = self.play_id
data['ansible_play_name'] = self.play_name
data['imported_file'] = imported_file
if (self.ls_format_version == "v2"):
self.logger.info("IMPORT | %s", imported_file, extra=data)
else:
self.logger.info("ansible import", extra=data)
data = {
'status': "IMPORTED",
'host': self.hostname,
'session': self.session,
'ansible_type': "import",
'ansible_playbook': self.playbook,
'ansible_host': result._host.name,
'imported_file': imported_file
}
self.logger.info("ansible import", extra=data)
def v2_playbook_on_not_import_for_host(self, result, missing_file):
data = self.base_data.copy()
data['ansible_type'] = "import"
data['status'] = "NOT IMPORTED"
data['ansible_host'] = result._host.name
data['ansible_play_id'] = self.play_id
data['ansible_play_name'] = self.play_name
data['imported_file'] = missing_file
if (self.ls_format_version == "v2"):
self.logger.info("NOT IMPORTED | %s", missing_file, extra=data)
else:
self.logger.info("ansible import", extra=data)
data = {
'status': "NOT IMPORTED",
'host': self.hostname,
'session': self.session,
'ansible_type': "import",
'ansible_playbook': self.playbook,
'ansible_host': result._host.name,
'missing_file': missing_file
}
self.logger.info("ansible import", extra=data)
def v2_runner_on_failed(self, result, **kwargs):
task_name = str(result._task).replace('TASK: ', '').replace('HANDLER: ', '')
data = self.base_data.copy()
if 'changed' in result._result.keys():
data['ansible_changed'] = result._result['changed']
else:
data['ansible_changed'] = False
data['ansible_type'] = "task"
data['status'] = "FAILED"
data['ansible_host'] = result._host.name
data['ansible_play_id'] = self.play_id
data['ansible_play_name'] = self.play_name
data['ansible_task'] = task_name
data['ansible_task_id'] = self.task_id
data['ansible_result'] = self._dump_results(result._result)
data = {
'status': "FAILED",
'host': self.hostname,
'session': self.session,
'ansible_type': "task",
'ansible_playbook': self.playbook,
'ansible_host': result._host.name,
'ansible_task': result._task,
'ansible_result': self._dump_results(result._result)
}
self.errors += 1
if (self.ls_format_version == "v2"):
self.logger.error(
"TASK FAILED | %s | HOST | %s | RESULT | %s",
task_name, self.hostname,
self._dump_results(result._result), extra=data
)
else:
self.logger.error("ansible failed", extra=data)
self.logger.error("ansible failed", extra=data)
def v2_runner_on_unreachable(self, result, **kwargs):
task_name = str(result._task).replace('TASK: ', '').replace('HANDLER: ', '')
data = self.base_data.copy()
data['ansible_type'] = "task"
data['status'] = "UNREACHABLE"
data['ansible_host'] = result._host.name
data['ansible_play_id'] = self.play_id
data['ansible_play_name'] = self.play_name
data['ansible_task'] = task_name
data['ansible_task_id'] = self.task_id
data['ansible_result'] = self._dump_results(result._result)
self.errors += 1
if (self.ls_format_version == "v2"):
self.logger.error(
"UNREACHABLE | %s | HOST | %s | RESULT | %s",
task_name, self.hostname,
self._dump_results(result._result), extra=data
)
else:
self.logger.error("ansible unreachable", extra=data)
data = {
'status': "UNREACHABLE",
'host': self.hostname,
'session': self.session,
'ansible_type': "task",
'ansible_playbook': self.playbook,
'ansible_host': result._host.name,
'ansible_task': result._task,
'ansible_result': self._dump_results(result._result)
}
self.logger.error("ansible unreachable", extra=data)
def v2_runner_on_async_failed(self, result, **kwargs):
task_name = str(result._task).replace('TASK: ', '').replace('HANDLER: ', '')
data = self.base_data.copy()
data['ansible_type'] = "task"
data['status'] = "FAILED"
data['ansible_host'] = result._host.name
data['ansible_play_id'] = self.play_id
data['ansible_play_name'] = self.play_name
data['ansible_task'] = task_name
data['ansible_task_id'] = self.task_id
data['ansible_result'] = self._dump_results(result._result)
data = {
'status': "FAILED",
'host': self.hostname,
'session': self.session,
'ansible_type': "task",
'ansible_playbook': self.playbook,
'ansible_host': result._host.name,
'ansible_task': result._task,
'ansible_result': self._dump_results(result._result)
}
self.errors += 1
if (self.ls_format_version == "v2"):
self.logger.error(
"ASYNC FAILED | %s | HOST | %s | RESULT | %s",
task_name, self.hostname,
self._dump_results(result._result), extra=data
)
else:
self.logger.error("ansible async", extra=data)
self.logger.error("ansible async", extra=data)

View File

@@ -7,7 +7,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
name: mail
callback: mail
type: notification
short_description: Sends failure events via email
description:
@@ -52,7 +52,7 @@ options:
ini:
- section: callback_mail
key: bcc
notes:
note:
- "TODO: expand configuration options now that plugins can leverage Ansible's configuration"
'''

View File

@@ -7,7 +7,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
name: nrdp
callback: nrdp
type: notification
author: "Remi VERCHERE (@rverchere)"
short_description: post task result to a nagios server through nrdp

View File

@@ -6,9 +6,8 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: 'null'
type: stdout
callback: 'null'
callback_type: stdout
requirements:
- set as main display callback
short_description: Don't display stuff to screen

View File

@@ -7,8 +7,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: say
callback: say
type: notification
requirements:
- whitelisting in configuration
@@ -17,7 +16,7 @@ DOCUMENTATION = '''
description:
- This plugin will use the 'say' or 'espeak' program to "speak" about play events.
notes:
- In 2.8, this callback has been renamed from C(osx_say) into M(community.general.say).
- In 2.8, this callback has been renamed from C(osx_say) into M(say).
'''
import distutils.spawn

View File

@@ -6,9 +6,8 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: selective
type: stdout
callback: selective
callback_type: stdout
requirements:
- set as main display callback
short_description: only print certain tasks
@@ -31,8 +30,8 @@ DOCUMENTATION = '''
'''
EXAMPLES = """
- ansible.builtin.debug: msg="This will not be printed"
- ansible.builtin.debug: msg="But this will"
- debug: msg="This will not be printed"
- debug: msg="But this will"
tags: [print_action]
"""
@@ -41,16 +40,7 @@ import difflib
from ansible import constants as C
from ansible.plugins.callback import CallbackBase
from ansible.module_utils._text 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
from ansible.utils.color import codeCodes
DONT_COLORIZE = False
COLORS = {
@@ -67,7 +57,7 @@ COLORS = {
def dict_diff(prv, nxt):
"""Return a dict of keys that differ with another config object."""
keys = set(list(prv.keys()) + list(nxt.keys()))
keys = set(prv.keys() + nxt.keys())
result = {}
for k in keys:
if prv.get(k) != nxt.get(k):
@@ -211,7 +201,7 @@ class CallbackModule(CallbackBase):
)
if 'results' in result._result:
for r in result._result['results']:
failed = 'failed' in r and r['failed']
failed = 'failed' in r
stderr = [r.get('exception', None), r.get('module_stderr', None)]
stderr = "\n".join([e for e in stderr if e]).strip()

View File

@@ -7,9 +7,8 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: slack
type: notification
callback: slack
callback_type: notification
requirements:
- whitelist in configuration
- prettytable (python library)

View File

@@ -18,10 +18,10 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
name: splunk
callback: splunk
type: aggregate
short_description: Sends task result events to Splunk HTTP Event Collector
author: "Stuart Hirst (!UNKNOWN) <support@convergingdata.com>"
author: "Stuart Hirst <support@convergingdata.com>"
description:
- This callback plugin will send task results as JSON formatted events to a Splunk HTTP collector.
- The companion Splunk Monitoring & Diagnostics App is available here "https://splunkbase.splunk.com/app/4023/"
@@ -45,36 +45,13 @@ DOCUMENTATION = '''
ini:
- section: callback_splunk
key: authtoken
validate_certs:
description: Whether to validate certificates for connections to HEC. It is not recommended to set to
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:
- section: callback_splunk
key: validate_certs
type: bool
default: true
version_added: '1.0.0'
include_milliseconds:
description: Whether to include milliseconds as part of the generated timestamp field in the event
sent to the Splunk HTTP collector
env:
- name: SPLUNK_INCLUDE_MILLISECONDS
ini:
- section: callback_splunk
key: include_milliseconds
type: bool
default: false
version_added: 2.0.0
'''
EXAMPLES = '''
examples: >
To enable, add this to your ansible.cfg file in the defaults block
[defaults]
callback_whitelist = community.general.splunk
callback_whitelist = splunk
Set the environment variable
export SPLUNK_URL=http://mysplunkinstance.datapaas.io:8088/services/collector/event
export SPLUNK_AUTHTOKEN=f23blad6-5965-4537-bf69-5b5a545blabla88
@@ -107,7 +84,7 @@ class SplunkHTTPCollectorSource(object):
self.ip_address = socket.gethostbyname(socket.gethostname())
self.user = getpass.getuser()
def send_event(self, url, authtoken, validate_certs, include_milliseconds, state, result, runtime):
def send_event(self, url, authtoken, state, result, runtime):
if result._task_fields['args'].get('_ansible_check_mode') is True:
self.ansible_check_mode = True
@@ -127,13 +104,8 @@ class SplunkHTTPCollectorSource(object):
data['uuid'] = result._task._uuid
data['session'] = self.session
data['status'] = state
if include_milliseconds:
time_format = '%Y-%m-%d %H:%M:%S.%f +0000'
else:
time_format = '%Y-%m-%d %H:%M:%S +0000'
data['timestamp'] = datetime.utcnow().strftime(time_format)
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
@@ -157,8 +129,7 @@ class SplunkHTTPCollectorSource(object):
'Content-type': 'application/json',
'Authorization': 'Splunk ' + authtoken
},
method='POST',
validate_certs=validate_certs
method='POST'
)
@@ -173,8 +144,6 @@ class CallbackModule(CallbackBase):
self.start_datetimes = {} # Collect task start times
self.url = None
self.authtoken = None
self.validate_certs = None
self.include_milliseconds = None
self.splunk = SplunkHTTPCollectorSource()
def _runtime(self, result):
@@ -184,9 +153,7 @@ class CallbackModule(CallbackBase):
).total_seconds()
def set_options(self, task_keys=None, var_options=None, direct=None):
super(CallbackModule, self).set_options(task_keys=task_keys,
var_options=var_options,
direct=direct)
super(CallbackModule, self).set_options(task_keys=task_keys, var_options=var_options, direct=direct)
self.url = self.get_option('url')
@@ -208,10 +175,6 @@ class CallbackModule(CallbackBase):
'`SPLUNK_AUTHTOKEN` environment variable or '
'in the ansible.cfg file.')
self.validate_certs = self.get_option('validate_certs')
self.include_milliseconds = self.get_option('include_milliseconds')
def v2_playbook_on_start(self, playbook):
self.splunk.ansible_playbook = basename(playbook._file_name)
@@ -225,8 +188,6 @@ class CallbackModule(CallbackBase):
self.splunk.send_event(
self.url,
self.authtoken,
self.validate_certs,
self.include_milliseconds,
'OK',
result,
self._runtime(result)
@@ -236,8 +197,6 @@ class CallbackModule(CallbackBase):
self.splunk.send_event(
self.url,
self.authtoken,
self.validate_certs,
self.include_milliseconds,
'SKIPPED',
result,
self._runtime(result)
@@ -247,8 +206,6 @@ class CallbackModule(CallbackBase):
self.splunk.send_event(
self.url,
self.authtoken,
self.validate_certs,
self.include_milliseconds,
'FAILED',
result,
self._runtime(result)
@@ -258,8 +215,6 @@ class CallbackModule(CallbackBase):
self.splunk.send_event(
self.url,
self.authtoken,
self.validate_certs,
self.include_milliseconds,
'FAILED',
result,
self._runtime(result)
@@ -269,8 +224,6 @@ class CallbackModule(CallbackBase):
self.splunk.send_event(
self.url,
self.authtoken,
self.validate_certs,
self.include_milliseconds,
'UNREACHABLE',
result,
self._runtime(result)

View File

@@ -0,0 +1,70 @@
# (c) 2017, Frederic Van Espen <github@freh.be>
# (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
callback: stderr
callback_type: stdout
requirements:
- set as main display callback
short_description: Splits output, sending failed tasks to stderr
deprecated:
why: The 'default' callback plugin now supports this functionality
removed_in: '2.0.0' # was Ansible 2.11
alternative: "'default' callback plugin with 'display_failed_stderr = yes' option"
extends_documentation_fragment:
- default_callback
description:
- This is the stderr callback plugin, it behaves like the default callback plugin but sends error output to stderr.
- Also it does not output skipped host/task/item status
'''
from ansible import constants as C
from ansible.plugins.callback.default import CallbackModule as CallbackModule_default
class CallbackModule(CallbackModule_default):
'''
This is the stderr callback plugin, which reuses the default
callback plugin but sends error output to stderr.
'''
CALLBACK_VERSION = 2.0
CALLBACK_TYPE = 'stdout'
CALLBACK_NAME = 'community.general.stderr'
def __init__(self):
self.super_ref = super(CallbackModule, self)
self.super_ref.__init__()
def v2_runner_on_failed(self, result, ignore_errors=False):
delegated_vars = result._result.get('_ansible_delegated_vars', None)
self._clean_results(result._result, result._task.action)
if self._play.strategy == 'free' and self._last_task_banner != result._task._uuid:
self._print_task_banner(result._task)
self._handle_exception(result._result, use_stderr=True)
self._handle_warnings(result._result)
if result._task.loop and 'results' in result._result:
self._process_items(result)
else:
if delegated_vars:
self._display.display("fatal: [%s -> %s]: FAILED! => %s" % (result._host.get_name(), delegated_vars['ansible_host'],
self._dump_results(result._result)), color=C.COLOR_ERROR,
stderr=True)
else:
self._display.display("fatal: [%s]: FAILED! => %s" % (result._host.get_name(), self._dump_results(result._result)),
color=C.COLOR_ERROR, stderr=True)
if ignore_errors:
self._display.display("...ignoring", color=C.COLOR_SKIP)

View File

@@ -18,7 +18,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
name: sumologic
callback: sumologic
type: aggregate
short_description: Sends task result events to Sumologic
author: "Ryan Currah (@ryancurrah)"
@@ -42,7 +42,7 @@ EXAMPLES = '''
examples: >
To enable, add this to your ansible.cfg file in the defaults block
[defaults]
callback_whitelist = community.general.sumologic
callback_whitelist = sumologic
Set the environment variable
export SUMOLOGIC_URL=https://endpoint1.collection.us2.sumologic.com/receiver/v1/http/R8moSv1d8EW9LAUFZJ6dbxCFxwLH6kfCdcBfddlfxCbLuL-BN5twcTpMk__pYy_cDmp==

View File

@@ -6,9 +6,8 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: syslog_json
type: notification
callback: syslog_json
callback_type: notification
requirements:
- whitelist in configuration
short_description: sends JSON events to syslog

View File

@@ -7,9 +7,9 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
name: unixy
callback: unixy
type: stdout
author: Allyson Bowles (@akatch)
author: Allyson Bowles <@akatch>
short_description: condensed Ansible output
description:
- Consolidated Ansible output in the style of LINUX/UNIX startup logs.

View File

@@ -6,8 +6,7 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
author: Unknown (!UNKNOWN)
name: yaml
callback: yaml
type: stdout
short_description: yaml-ized Ansible screen output
description:
@@ -50,7 +49,7 @@ def my_represent_scalar(self, tag, value, style=None):
# ...no trailing space
value = value.rstrip()
# ...and non-printable characters
value = ''.join(x for x in value if x in string.printable or ord(x) >= 0xA0)
value = ''.join(x for x in value if x in string.printable)
# ...tabs prevent blocks from expanding
value = value.expandtabs()
# ...and odd bits of whitespace

View File

@@ -9,8 +9,8 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
author: Maykel Moya (!UNKNOWN) <mmoya@speedyrails.com>
name: chroot
author: Maykel Moya <mmoya@speedyrails.com>
connection: chroot
short_description: Interact with local chroot
description:
- Run commands or put/fetch files to an existing chroot on the Ansible controller.

View File

@@ -0,0 +1,364 @@
# Based on the chroot connection plugin by Maykel Moya
#
# (c) 2014, Lorin Hochstein
# (c) 2015, Leendert Brouwer (https://github.com/objectified)
# (c) 2015, Toshio Kuratomi <tkuratomi@ansible.com>
# Copyright (c) 2017 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
author:
- Lorin Hochestein
- Leendert Brouwer
connection: docker
short_description: Run tasks in docker containers
description:
- Run commands or put/fetch files to an existing docker container.
options:
remote_user:
description:
- The user to execute as inside the container
vars:
- name: ansible_user
- name: ansible_docker_user
docker_extra_args:
description:
- Extra arguments to pass to the docker command line
default: ''
remote_addr:
description:
- The name of the container you want to access.
default: inventory_hostname
vars:
- name: ansible_host
- name: ansible_docker_host
'''
import distutils.spawn
import fcntl
import os
import os.path
import subprocess
import re
from distutils.version import LooseVersion
import ansible.constants as C
from ansible.compat import selectors
from ansible.errors import AnsibleError, AnsibleFileNotFound
from ansible.module_utils.six.moves import shlex_quote
from ansible.module_utils._text import to_bytes, to_native, to_text
from ansible.plugins.connection import ConnectionBase, BUFSIZE
from ansible.utils.display import Display
display = Display()
class Connection(ConnectionBase):
''' Local docker based connections '''
transport = 'community.general.docker'
has_pipelining = True
def __init__(self, play_context, new_stdin, *args, **kwargs):
super(Connection, self).__init__(play_context, new_stdin, *args, **kwargs)
# Note: docker supports running as non-root in some configurations.
# (For instance, setting the UNIX socket file to be readable and
# writable by a specific UNIX group and then putting users into that
# group). Therefore we don't check that the user is root when using
# this connection. But if the user is getting a permission denied
# error it probably means that docker on their system is only
# configured to be connected to by root and they are not running as
# root.
# Windows uses Powershell modules
if getattr(self._shell, "_IS_WINDOWS", False):
self.module_implementation_preferences = ('.ps1', '.exe', '')
if 'docker_command' in kwargs:
self.docker_cmd = kwargs['docker_command']
else:
self.docker_cmd = distutils.spawn.find_executable('docker')
if not self.docker_cmd:
raise AnsibleError("docker command not found in PATH")
docker_version = self._get_docker_version()
if docker_version == u'dev':
display.warning(u'Docker version number is "dev". Will assume latest version.')
if docker_version != u'dev' and LooseVersion(docker_version) < LooseVersion(u'1.3'):
raise AnsibleError('docker connection type requires docker 1.3 or higher')
# The remote user we will request from docker (if supported)
self.remote_user = None
# The actual user which will execute commands in docker (if known)
self.actual_user = None
if self._play_context.remote_user is not None:
if docker_version == u'dev' or LooseVersion(docker_version) >= LooseVersion(u'1.7'):
# Support for specifying the exec user was added in docker 1.7
self.remote_user = self._play_context.remote_user
self.actual_user = self.remote_user
else:
self.actual_user = self._get_docker_remote_user()
if self.actual_user != self._play_context.remote_user:
display.warning(u'docker {0} does not support remote_user, using container default: {1}'
.format(docker_version, self.actual_user or u'?'))
elif self._display.verbosity > 2:
# Since we're not setting the actual_user, look it up so we have it for logging later
# Only do this if display verbosity is high enough that we'll need the value
# This saves overhead from calling into docker when we don't need to
self.actual_user = self._get_docker_remote_user()
@staticmethod
def _sanitize_version(version):
return re.sub(u'[^0-9a-zA-Z.]', u'', version)
def _old_docker_version(self):
cmd_args = []
if self._play_context.docker_extra_args:
cmd_args += self._play_context.docker_extra_args.split(' ')
old_version_subcommand = ['version']
old_docker_cmd = [self.docker_cmd] + cmd_args + old_version_subcommand
p = subprocess.Popen(old_docker_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
cmd_output, err = p.communicate()
return old_docker_cmd, to_native(cmd_output), err, p.returncode
def _new_docker_version(self):
# no result yet, must be newer Docker version
cmd_args = []
if self._play_context.docker_extra_args:
cmd_args += self._play_context.docker_extra_args.split(' ')
new_version_subcommand = ['version', '--format', "'{{.Server.Version}}'"]
new_docker_cmd = [self.docker_cmd] + cmd_args + new_version_subcommand
p = subprocess.Popen(new_docker_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
cmd_output, err = p.communicate()
return new_docker_cmd, to_native(cmd_output), err, p.returncode
def _get_docker_version(self):
cmd, cmd_output, err, returncode = self._old_docker_version()
if returncode == 0:
for line in to_text(cmd_output, errors='surrogate_or_strict').split(u'\n'):
if line.startswith(u'Server version:'): # old docker versions
return self._sanitize_version(line.split()[2])
cmd, cmd_output, err, returncode = self._new_docker_version()
if returncode:
raise AnsibleError('Docker version check (%s) failed: %s' % (to_native(cmd), to_native(err)))
return self._sanitize_version(to_text(cmd_output, errors='surrogate_or_strict'))
def _get_docker_remote_user(self):
""" Get the default user configured in the docker container """
p = subprocess.Popen([self.docker_cmd, 'inspect', '--format', '{{.Config.User}}', self._play_context.remote_addr],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
out = to_text(out, errors='surrogate_or_strict')
if p.returncode != 0:
display.warning(u'unable to retrieve default user from docker container: %s %s' % (out, to_text(err)))
return None
# The default exec user is root, unless it was changed in the Dockerfile with USER
return out.strip() or u'root'
def _build_exec_cmd(self, cmd):
""" Build the local docker exec command to run cmd on remote_host
If remote_user is available and is supported by the docker
version we are using, it will be provided to docker exec.
"""
local_cmd = [self.docker_cmd]
if self._play_context.docker_extra_args:
local_cmd += self._play_context.docker_extra_args.split(' ')
local_cmd += [b'exec']
if self.remote_user is not None:
local_cmd += [b'-u', self.remote_user]
# -i is needed to keep stdin open which allows pipelining to work
local_cmd += [b'-i', self._play_context.remote_addr] + cmd
return local_cmd
def _connect(self, port=None):
""" Connect to the container. Nothing to do """
super(Connection, self)._connect()
if not self._connected:
display.vvv(u"ESTABLISH DOCKER CONNECTION FOR USER: {0}".format(
self.actual_user or u'?'), host=self._play_context.remote_addr
)
self._connected = True
def exec_command(self, cmd, in_data=None, sudoable=False):
""" Run a command on the docker host """
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
local_cmd = self._build_exec_cmd([self._play_context.executable, '-c', cmd])
display.vvv(u"EXEC {0}".format(to_text(local_cmd)), host=self._play_context.remote_addr)
display.debug("opening command with Popen()")
local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
p = subprocess.Popen(
local_cmd,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
display.debug("done running command with Popen()")
if self.become and self.become.expect_prompt() and sudoable:
fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) | os.O_NONBLOCK)
fcntl.fcntl(p.stderr, fcntl.F_SETFL, fcntl.fcntl(p.stderr, fcntl.F_GETFL) | os.O_NONBLOCK)
selector = selectors.DefaultSelector()
selector.register(p.stdout, selectors.EVENT_READ)
selector.register(p.stderr, selectors.EVENT_READ)
become_output = b''
try:
while not self.become.check_success(become_output) and not self.become.check_password_prompt(become_output):
events = selector.select(self._play_context.timeout)
if not events:
stdout, stderr = p.communicate()
raise AnsibleError('timeout waiting for privilege escalation password prompt:\n' + to_native(become_output))
for key, event in events:
if key.fileobj == p.stdout:
chunk = p.stdout.read()
elif key.fileobj == p.stderr:
chunk = p.stderr.read()
if not chunk:
stdout, stderr = p.communicate()
raise AnsibleError('privilege output closed while waiting for password prompt:\n' + to_native(become_output))
become_output += chunk
finally:
selector.close()
if not self.become.check_success(become_output):
become_pass = self.become.get_option('become_pass', playcontext=self._play_context)
p.stdin.write(to_bytes(become_pass, errors='surrogate_or_strict') + b'\n')
fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) & ~os.O_NONBLOCK)
fcntl.fcntl(p.stderr, fcntl.F_SETFL, fcntl.fcntl(p.stderr, fcntl.F_GETFL) & ~os.O_NONBLOCK)
display.debug("getting output with communicate()")
stdout, stderr = p.communicate(in_data)
display.debug("done communicating")
display.debug("done with docker.exec_command()")
return (p.returncode, stdout, stderr)
def _prefix_login_path(self, remote_path):
''' Make sure that we put files into a standard path
If a path is relative, then we need to choose where to put it.
ssh chooses $HOME but we aren't guaranteed that a home dir will
exist in any given chroot. So for now we're choosing "/" instead.
This also happens to be the former default.
Can revisit using $HOME instead if it's a problem
'''
if getattr(self._shell, "_IS_WINDOWS", False):
import ntpath
return ntpath.normpath(remote_path)
else:
if not remote_path.startswith(os.path.sep):
remote_path = os.path.join(os.path.sep, remote_path)
return os.path.normpath(remote_path)
def put_file(self, in_path, out_path):
""" Transfer a file from local to docker container """
super(Connection, self).put_file(in_path, out_path)
display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr)
out_path = self._prefix_login_path(out_path)
if not os.path.exists(to_bytes(in_path, errors='surrogate_or_strict')):
raise AnsibleFileNotFound(
"file or module does not exist: %s" % to_native(in_path))
out_path = shlex_quote(out_path)
# Older docker doesn't have native support for copying files into
# running containers, so we use docker exec to implement this
# Although docker version 1.8 and later provide support, the
# owner and group of the files are always set to root
with open(to_bytes(in_path, errors='surrogate_or_strict'), 'rb') as in_file:
if not os.fstat(in_file.fileno()).st_size:
count = ' count=0'
else:
count = ''
args = self._build_exec_cmd([self._play_context.executable, "-c", "dd of=%s bs=%s%s" % (out_path, BUFSIZE, count)])
args = [to_bytes(i, errors='surrogate_or_strict') for i in args]
try:
p = subprocess.Popen(args, stdin=in_file,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except OSError:
raise AnsibleError("docker connection requires dd command in the container to put files")
stdout, stderr = p.communicate()
if p.returncode != 0:
raise AnsibleError("failed to transfer file %s to %s:\n%s\n%s" %
(to_native(in_path), to_native(out_path), to_native(stdout), to_native(stderr)))
def fetch_file(self, in_path, out_path):
""" Fetch a file from container to local. """
super(Connection, self).fetch_file(in_path, out_path)
display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self._play_context.remote_addr)
in_path = self._prefix_login_path(in_path)
# out_path is the final file path, but docker takes a directory, not a
# file path
out_dir = os.path.dirname(out_path)
args = [self.docker_cmd, "cp", "%s:%s" % (self._play_context.remote_addr, in_path), out_dir]
args = [to_bytes(i, errors='surrogate_or_strict') for i in args]
p = subprocess.Popen(args, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.communicate()
if getattr(self._shell, "_IS_WINDOWS", False):
import ntpath
actual_out_path = ntpath.join(out_dir, ntpath.basename(in_path))
else:
actual_out_path = os.path.join(out_dir, os.path.basename(in_path))
if p.returncode != 0:
# Older docker doesn't have native support for fetching files command `cp`
# If `cp` fails, try to use `dd` instead
args = self._build_exec_cmd([self._play_context.executable, "-c", "dd if=%s bs=%s" % (in_path, BUFSIZE)])
args = [to_bytes(i, errors='surrogate_or_strict') for i in args]
with open(to_bytes(actual_out_path, errors='surrogate_or_strict'), 'wb') as out_file:
try:
p = subprocess.Popen(args, stdin=subprocess.PIPE,
stdout=out_file, stderr=subprocess.PIPE)
except OSError:
raise AnsibleError("docker connection requires dd command in the container to put files")
stdout, stderr = p.communicate()
if p.returncode != 0:
raise AnsibleError("failed to fetch file %s to %s:\n%s\n%s" % (in_path, out_path, stdout, stderr))
# Rename if needed
if actual_out_path != out_path:
os.rename(to_bytes(actual_out_path, errors='strict'), to_bytes(out_path, errors='strict'))
def close(self):
""" Terminate the connection. Nothing to do for Docker"""
super(Connection, self).close()
self._connected = False

View File

@@ -9,7 +9,7 @@ __metaclass__ = type
DOCUMENTATION = '''
author: Michael Scherer (@msherer) <misc@zarb.org>
name: funcd
connection: funcd
short_description: Use funcd to connect to target
description:
- This transport permits you to use Ansible over Func.
@@ -37,13 +37,12 @@ import tempfile
import shutil
from ansible.errors import AnsibleError
from ansible.plugins.connection import ConnectionBase
from ansible.utils.display import Display
display = Display()
class Connection(ConnectionBase):
class Connection(object):
''' Func-based connections '''
has_pipelining = False

View File

@@ -9,8 +9,8 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
author: Stephan Lohse (!UNKNOWN) <dev-github@ploek.org>
name: iocage
author: Stephan Lohse <dev-github@ploek.org>
connection: iocage
short_description: Run tasks in iocage jails
description:
- Run commands or put/fetch files to an existing iocage jail

View File

@@ -10,7 +10,7 @@ __metaclass__ = type
DOCUMENTATION = '''
author: Ansible Core Team
name: jail
connection: jail
short_description: Run tasks in jails
description:
- Run commands or put/fetch files to an existing jail

View File

@@ -6,8 +6,8 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
author: Joerg Thalheim (!UNKNOWN) <joerg@higgsboson.tk>
name: lxc
author: Joerg Thalheim <joerg@higgsboson.tk>
connection: lxc
short_description: Run tasks in lxc containers via lxc python library
description:
- Run commands or put/fetch files to an existing lxc container using lxc python library
@@ -86,7 +86,7 @@ class Connection(ConnectionBase):
write_fds = []
while len(read_fds) > 0 or len(write_fds) > 0:
try:
ready_reads, ready_writes, dummy = select.select(read_fds, write_fds, [])
ready_reads, ready_writes, _ = select.select(read_fds, write_fds, [])
except select.error as e:
if e.args[0] == errno.EINTR:
continue

View File

@@ -6,15 +6,15 @@ from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
author: Matt Clay (@mattclay) <matt@mystile.com>
name: lxd
author: Matt Clay <matt@mystile.com>
connection: lxd
short_description: Run tasks in lxc containers via lxc CLI
description:
- Run commands or put/fetch files to an existing lxc container using lxc CLI
options:
remote_addr:
description:
- Container identifier.
- Container identifier
default: inventory_hostname
vars:
- name: ansible_host
@@ -26,19 +26,6 @@ DOCUMENTATION = '''
vars:
- name: ansible_executable
- name: ansible_lxd_executable
remote:
description:
- Name of the LXD remote to use.
default: local
vars:
- name: ansible_lxd_remote
version_added: 2.0.0
project:
description:
- Name of the LXD project to use.
vars:
- name: ansible_lxd_project
version_added: 2.0.0
'''
import os
@@ -83,15 +70,7 @@ class Connection(ConnectionBase):
self._display.vvv(u"EXEC {0}".format(cmd), host=self._host)
local_cmd = [self._lxc_cmd]
if self.get_option("project"):
local_cmd.extend(["--project", self.get_option("project")])
local_cmd.extend([
"exec",
"%s:%s" % (self.get_option("remote"), self._host),
"--",
self._play_context.executable, "-c", cmd
])
local_cmd = [self._lxc_cmd, "exec", self._host, "--", self._play_context.executable, "-c", cmd]
local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
in_data = to_bytes(in_data, errors='surrogate_or_strict', nonstring='passthru')
@@ -119,14 +98,7 @@ class Connection(ConnectionBase):
if not os.path.isfile(to_bytes(in_path, errors='surrogate_or_strict')):
raise AnsibleFileNotFound("input path is not a file: %s" % in_path)
local_cmd = [self._lxc_cmd]
if self.get_option("project"):
local_cmd.extend(["--project", self.get_option("project")])
local_cmd.extend([
"file", "push",
in_path,
"%s:%s/%s" % (self.get_option("remote"), self._host, out_path)
])
local_cmd = [self._lxc_cmd, "file", "push", in_path, self._host + "/" + out_path]
local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]
@@ -139,14 +111,7 @@ class Connection(ConnectionBase):
self._display.vvv(u"FETCH {0} TO {1}".format(in_path, out_path), host=self._host)
local_cmd = [self._lxc_cmd]
if self.get_option("project"):
local_cmd.extend(["--project", self.get_option("project")])
local_cmd.extend([
"file", "pull",
"%s:%s/%s" % (self.get_option("remote"), self._host, in_path),
out_path
])
local_cmd = [self._lxc_cmd, "file", "pull", self._host + "/" + in_path, out_path]
local_cmd = [to_bytes(i, errors='surrogate_or_strict') for i in local_cmd]

173
plugins/connection/oc.py Normal file
View File

@@ -0,0 +1,173 @@
# Based on the docker connection plugin
#
# Connection plugin for configuring kubernetes containers with kubectl
# (c) 2017, XuXinkun <xuxinkun@gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = '''
author:
- xuxinkun
connection: oc
short_description: Execute tasks in pods running on OpenShift.
description:
- Use the oc exec command to run tasks in, or put/fetch files to, pods running on the OpenShift
container platform.
requirements:
- oc (go binary)
options:
oc_pod:
description:
- Pod name. Required when the host name does not match pod name.
default: ''
vars:
- name: ansible_oc_pod
env:
- name: K8S_AUTH_POD
oc_container:
description:
- Container name. Required when a pod contains more than one container.
default: ''
vars:
- name: ansible_oc_container
env:
- name: K8S_AUTH_CONTAINER
oc_namespace:
description:
- The namespace of the pod
default: ''
vars:
- name: ansible_oc_namespace
env:
- name: K8S_AUTH_NAMESPACE
oc_extra_args:
description:
- Extra arguments to pass to the oc command line.
default: ''
vars:
- name: ansible_oc_extra_args
env:
- name: K8S_AUTH_EXTRA_ARGS
oc_kubeconfig:
description:
- Path to a oc config file. Defaults to I(~/.kube/conig)
default: ''
vars:
- name: ansible_oc_kubeconfig
- name: ansible_oc_config
env:
- name: K8S_AUTH_KUBECONFIG
oc_context:
description:
- The name of a context found in the K8s config file.
default: ''
vars:
- name: ansible_oc_context
env:
- name: K8S_AUTH_CONTEXT
oc_host:
description:
- URL for accessing the API.
default: ''
vars:
- name: ansible_oc_host
- name: ansible_oc_server
env:
- name: K8S_AUTH_HOST
- name: K8S_AUTH_SERVER
oc_token:
description:
- API authentication bearer token.
vars:
- name: ansible_oc_token
- name: ansible_oc_api_key
env:
- name: K8S_AUTH_TOKEN
- name: K8S_AUTH_API_KEY
client_cert:
description:
- Path to a certificate used to authenticate with the API.
default: ''
vars:
- name: ansible_oc_cert_file
- name: ansible_oc_client_cert
env:
- name: K8S_AUTH_CERT_FILE
aliases: [ oc_cert_file ]
client_key:
description:
- Path to a key file used to authenticate with the API.
default: ''
vars:
- name: ansible_oc_key_file
- name: ansible_oc_client_key
env:
- name: K8S_AUTH_KEY_FILE
aliases: [ oc_key_file ]
ca_cert:
description:
- Path to a CA certificate used to authenticate with the API.
default: ''
vars:
- name: ansible_oc_ssl_ca_cert
- name: ansible_oc_ca_cert
env:
- name: K8S_AUTH_SSL_CA_CERT
aliases: [ oc_ssl_ca_cert ]
validate_certs:
description:
- Whether or not to verify the API server's SSL certificate. Defaults to I(true).
default: ''
vars:
- name: ansible_oc_verify_ssl
- name: ansible_oc_validate_certs
env:
- name: K8S_AUTH_VERIFY_SSL
aliases: [ oc_verify_ssl ]
'''
from ansible_collections.community.general.plugins.connection.kubectl import Connection as KubectlConnection
CONNECTION_TRANSPORT = 'oc'
CONNECTION_OPTIONS = {
'oc_container': '-c',
'oc_namespace': '-n',
'oc_kubeconfig': '--config',
'oc_context': '--context',
'oc_host': '--server',
'client_cert': '--client-certificate',
'client_key': '--client-key',
'ca_cert': '--certificate-authority',
'validate_certs': '--insecure-skip-tls-verify',
'oc_token': '--token'
}
class Connection(KubectlConnection):
''' Local oc based connections '''
transport = CONNECTION_TRANSPORT
connection_options = CONNECTION_OPTIONS
documentation = DOCUMENTATION

View File

@@ -11,7 +11,7 @@ __metaclass__ = type
DOCUMENTATION = '''
name: qubes
connection: qubes
short_description: Interact with an existing QubesOS AppVM
description:

View File

@@ -10,7 +10,7 @@ __metaclass__ = type
DOCUMENTATION = '''
author: Michael Scherer (@mscherer) <misc@zarb.org>
name: saltstack
connection: saltstack
short_description: Allow ansible to piggyback on salt minions
description:
- This allows you to use existing Saltstack infrastructure to connect to targets.
@@ -19,7 +19,6 @@ DOCUMENTATION = '''
import re
import os
import pty
import codecs
import subprocess
from ansible.module_utils._text import to_bytes, to_text
@@ -86,9 +85,9 @@ class Connection(ConnectionBase):
out_path = self._normalize_path(out_path, '/')
self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self.host)
with open(in_path, 'rb') as in_fh:
with open(in_path) as in_fh:
content = in_fh.read()
self.client.cmd(self.host, 'hashutil.base64_decodefile', [codecs.encode(content, 'base64'), out_path])
self.client.cmd(self.host, 'file.write', [out_path, content])
# TODO test it
def fetch_file(self, in_path, out_path):

View File

@@ -11,7 +11,7 @@ __metaclass__ = type
DOCUMENTATION = '''
author: Ansible Core Team
name: zone
connection: zone
short_description: Run tasks in a zone instance
description:
- Run commands or put/fetch files to an existing zone

View File

@@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2018, Google Inc.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
class ModuleDocFragment(object):
# GCP doc fragment.
DOCUMENTATION = r'''
options:
project:
description:
- The Google Cloud Platform project to use.
type: str
auth_kind:
description:
- The type of credential used.
type: str
required: true
choices: [ application, machineaccount, serviceaccount ]
service_account_contents:
description:
- The contents of a Service Account JSON file, either in a dictionary or as a JSON string that represents it.
type: jsonarg
service_account_file:
description:
- The path of a Service Account JSON file if serviceaccount is selected as type.
type: path
service_account_email:
description:
- An optional service account email address if machineaccount is selected
and the user does not wish to use the default email.
type: str
scopes:
description:
- Array of scopes to be used.
type: list
elements: str
env_type:
description:
- Specifies which Ansible environment you're running this module within.
- This should not be set unless you know what you're doing.
- This only alters the User Agent string for any API requests.
type: str
notes:
- for authentication, you can set service_account_file using the
c(gcp_service_account_file) env variable.
- for authentication, you can set service_account_contents using the
c(GCP_SERVICE_ACCOUNT_CONTENTS) env variable.
- For authentication, you can set service_account_email using the
C(GCP_SERVICE_ACCOUNT_EMAIL) env variable.
- For authentication, you can set auth_kind using the C(GCP_AUTH_KIND) env
variable.
- For authentication, you can set scopes using the C(GCP_SCOPES) env variable.
- Environment variables values will only be used if the playbook values are
not set.
- The I(service_account_email) and I(service_account_file) options are
mutually exclusive.
'''

View File

@@ -3,9 +3,6 @@
# Copyright (c) 2017-present Alibaba Group Holding Limited. He Guimin <heguimin36@163.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
class ModuleDocFragment(object):

View File

@@ -2,9 +2,6 @@
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
class ModuleDocFragment(object):

View File

@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2018, Ansible Project
# Copyright: (c) 2018, Abhijeet Kasurde (akasurde@redhat.com)
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
class ModuleDocFragment(object):
# Parameters for DigitalOcean modules
DOCUMENTATION = r'''
options:
oauth_token:
description:
- DigitalOcean OAuth token.
- "There are several other environment variables which can be used to provide this value."
- "i.e., - 'DO_API_TOKEN', 'DO_API_KEY', 'DO_OAUTH_TOKEN' and 'OAUTH_TOKEN'"
type: str
aliases: [ api_token ]
timeout:
description:
- The timeout in seconds used for polling DigitalOcean's API.
type: int
default: 30
validate_certs:
description:
- If set to C(no), the SSL certificates will not be validated.
- This should only set to C(no) used on personally controlled sites using self-signed certificates.
type: bool
default: yes
'''

View File

@@ -3,9 +3,6 @@
# Copyright: (c) 2016, Dimension Data
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
# Authors:
# - Adam Friedman <tintoy@tintoy.io>
@@ -19,6 +16,7 @@ options:
region:
description:
- The target region.
choices:
- Regions are defined in Apache libcloud project [libcloud/common/dimensiondata.py]
- They are also listed in U(https://libcloud.readthedocs.io/en/latest/compute/drivers/dimensiondata.html)
- Note that the default value "na" stands for "North America".

View File

@@ -3,9 +3,6 @@
# Copyright: (c) 2016, Dimension Data
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
# Authors:
# - Adam Friedman <tintoy@tintoy.io>

View File

@@ -0,0 +1,136 @@
# -*- coding: utf-8 -*-
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
class ModuleDocFragment(object):
# Docker doc fragment
DOCUMENTATION = r'''
options:
docker_host:
description:
- The URL or Unix socket path used to connect to the Docker API. To connect to a remote host, provide the
TCP connection string. For example, C(tcp://192.0.2.23:2376). If TLS is used to encrypt the connection,
the module will automatically replace C(tcp) in the connection URL with C(https).
- If the value is not specified in the task, the value of environment variable C(DOCKER_HOST) will be used
instead. If the environment variable is not set, the default value will be used.
type: str
default: unix://var/run/docker.sock
aliases: [ docker_url ]
tls_hostname:
description:
- When verifying the authenticity of the Docker Host server, provide the expected name of the server.
- If the value is not specified in the task, the value of environment variable C(DOCKER_TLS_HOSTNAME) will
be used instead. If the environment variable is not set, the default value will be used.
type: str
default: localhost
api_version:
description:
- The version of the Docker API running on the Docker Host.
- Defaults to the latest version of the API supported by Docker SDK for Python and the docker daemon.
- If the value is not specified in the task, the value of environment variable C(DOCKER_API_VERSION) will be
used instead. If the environment variable is not set, the default value will be used.
type: str
default: auto
aliases: [ docker_api_version ]
timeout:
description:
- The maximum amount of time in seconds to wait on a response from the API.
- If the value is not specified in the task, the value of environment variable C(DOCKER_TIMEOUT) will be used
instead. If the environment variable is not set, the default value will be used.
type: int
default: 60
ca_cert:
description:
- Use a CA certificate when performing server verification by providing the path to a CA certificate file.
- If the value is not specified in the task and the environment variable C(DOCKER_CERT_PATH) is set,
the file C(ca.pem) from the directory specified in the environment variable C(DOCKER_CERT_PATH) will be used.
type: path
aliases: [ tls_ca_cert, cacert_path ]
client_cert:
description:
- Path to the client's TLS certificate file.
- If the value is not specified in the task and the environment variable C(DOCKER_CERT_PATH) is set,
the file C(cert.pem) from the directory specified in the environment variable C(DOCKER_CERT_PATH) will be used.
type: path
aliases: [ tls_client_cert, cert_path ]
client_key:
description:
- Path to the client's TLS key file.
- If the value is not specified in the task and the environment variable C(DOCKER_CERT_PATH) is set,
the file C(key.pem) from the directory specified in the environment variable C(DOCKER_CERT_PATH) will be used.
type: path
aliases: [ tls_client_key, key_path ]
ssl_version:
description:
- Provide a valid SSL version number. Default value determined by ssl.py module.
- If the value is not specified in the task, the value of environment variable C(DOCKER_SSL_VERSION) will be
used instead.
type: str
tls:
description:
- Secure the connection to the API by using TLS without verifying the authenticity of the Docker host
server. Note that if I(validate_certs) is set to C(yes) as well, it will take precedence.
- If the value is not specified in the task, the value of environment variable C(DOCKER_TLS) will be used
instead. If the environment variable is not set, the default value will be used.
type: bool
default: no
validate_certs:
description:
- Secure the connection to the API by using TLS and verifying the authenticity of the Docker host server.
- If the value is not specified in the task, the value of environment variable C(DOCKER_TLS_VERIFY) will be
used instead. If the environment variable is not set, the default value will be used.
type: bool
default: no
aliases: [ tls_verify ]
debug:
description:
- Debug mode
type: bool
default: no
notes:
- Connect to the Docker daemon by providing parameters with each task or by defining environment variables.
You can define C(DOCKER_HOST), C(DOCKER_TLS_HOSTNAME), C(DOCKER_API_VERSION), C(DOCKER_CERT_PATH), C(DOCKER_SSL_VERSION),
C(DOCKER_TLS), C(DOCKER_TLS_VERIFY) and C(DOCKER_TIMEOUT). If you are using docker machine, run the script shipped
with the product that sets up the environment. It will set these variables for you. See
U(https://docs.docker.com/machine/reference/env/) for more details.
- When connecting to Docker daemon with TLS, you might need to install additional Python packages.
For the Docker SDK for Python, version 2.4 or newer, this can be done by installing C(docker[tls]) with M(pip).
- Note that the Docker SDK for Python only allows to specify the path to the Docker configuration for very few functions.
In general, it will use C($HOME/.docker/config.json) if the C(DOCKER_CONFIG) environment variable is not specified,
and use C($DOCKER_CONFIG/config.json) otherwise.
'''
# Additional, more specific stuff for minimal Docker SDK for Python version < 2.0
DOCKER_PY_1_DOCUMENTATION = r'''
options: {}
requirements:
- "Docker SDK for Python: Please note that the L(docker-py,https://pypi.org/project/docker-py/)
Python module has been superseded by L(docker,https://pypi.org/project/docker/)
(see L(here,https://github.com/docker/docker-py/issues/1310) for details).
For Python 2.6, C(docker-py) must be used. Otherwise, it is recommended to
install the C(docker) Python module. Note that both modules should *not*
be installed at the same time. Also note that when both modules are installed
and one of them is uninstalled, the other might no longer function and a
reinstall of it is required."
'''
# Additional, more specific stuff for minimal Docker SDK for Python version >= 2.0.
# Note that Docker SDK for Python >= 2.0 requires Python 2.7 or newer.
DOCKER_PY_2_DOCUMENTATION = r'''
options: {}
requirements:
- "Python >= 2.7"
- "Docker SDK for Python: Please note that the L(docker-py,https://pypi.org/project/docker-py/)
Python module has been superseded by L(docker,https://pypi.org/project/docker/)
(see L(here,https://github.com/docker/docker-py/issues/1310) for details).
This module does *not* work with docker-py."
'''

View File

@@ -3,9 +3,6 @@
# Copyright: (c) 2018, Luca Lorenzetto (@remix_tj) <lorenzetto.luca@gmail.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
class ModuleDocFragment(object):

View File

@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2019 Felix Fontein <felix@fontein.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
class ModuleDocFragment(object):
# Standard files documentation fragment
DOCUMENTATION = r'''
options:
hetzner_user:
description: The username for the Robot webservice user.
type: str
required: yes
hetzner_password:
description: The password for the Robot webservice user.
type: str
required: yes
'''

View File

@@ -2,9 +2,6 @@
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
class ModuleDocFragment(object):

View File

@@ -2,9 +2,6 @@
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
class ModuleDocFragment(object):

View File

@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2016, Gregory Shulov <gregory.shulov@gmail.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
class ModuleDocFragment(object):
# Standard Infinibox documentation fragment
DOCUMENTATION = r'''
options:
system:
description:
- Infinibox Hostname or IPv4 Address.
type: str
required: true
user:
description:
- Infinibox User username with sufficient priveledges ( see notes ).
required: false
password:
description:
- Infinibox User password.
type: str
notes:
- This module requires infinisdk python library
- You must set INFINIBOX_USER and INFINIBOX_PASSWORD environment variables
if user and password arguments are not passed to the module directly
- Ansible uses the infinisdk configuration file C(~/.infinidat/infinisdk.ini) if no credentials are provided.
See U(http://infinisdk.readthedocs.io/en/latest/getting_started.html)
requirements:
- "python >= 2.7"
- infinisdk
'''

View File

@@ -4,9 +4,6 @@
# Copyright: (c) 2017, Abhijeet Kasurde (akasurde@redhat.com)
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
class ModuleDocFragment(object):
# Parameters for influxdb modules
@@ -40,7 +37,6 @@ options:
path:
description:
- The path on which InfluxDB server is accessible
- Only available when using python-influxdb >= 5.1.0
type: str
version_added: '0.2.0'
validate_certs:
@@ -53,7 +49,6 @@ options:
description:
- Use https instead of http to connect to InfluxDB server.
type: bool
default: false
timeout:
description:
- Number of seconds Requests will wait for client to establish a connection.
@@ -62,14 +57,12 @@ options:
description:
- Number of retries client will try before aborting.
- C(0) indicates try until success.
- Only available when using python-influxdb >= 4.1.0
type: int
default: 3
use_udp:
description:
- Use UDP to connect to InfluxDB server.
type: bool
default: false
udp_port:
description:
- UDP port to connect to InfluxDB server.

View File

@@ -4,9 +4,6 @@
# Copyright: (c) 2017-18, Abhijeet Kasurde (akasurde@redhat.com)
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
class ModuleDocFragment(object):
# Parameters for FreeIPA/IPA modules

View File

@@ -3,9 +3,6 @@
# Copyright: (c) 2017, Eike Frost <ei@kefro.st>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
class ModuleDocFragment(object):

View File

@@ -0,0 +1,130 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2018, KubeVirt Team <@kubevirt>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
class ModuleDocFragment(object):
DOCUMENTATION = r'''
options:
resource_definition:
description:
- "A partial YAML definition of the object being created/updated. Here you can define Kubernetes
resource parameters not covered by this module's parameters."
- "NOTE: I(resource_definition) has lower priority than module parameters. If you try to define e.g.
I(metadata.namespace) here, that value will be ignored and I(namespace) used instead."
aliases:
- definition
- inline
type: dict
wait:
description:
- "I(True) if the module should wait for the resource to get into desired state."
type: bool
default: yes
force:
description:
- If set to C(no), and I(state) is C(present), an existing object will be replaced.
type: bool
default: no
wait_timeout:
description:
- The amount of time in seconds the module should wait for the resource to get into desired state.
type: int
default: 120
wait_sleep:
description:
- Number of seconds to sleep between checks.
default: 5
version_added: '0.2.0'
memory:
description:
- The amount of memory to be requested by virtual machine.
- For example 1024Mi.
type: str
memory_limit:
description:
- The maximum memory to be used by virtual machine.
- For example 1024Mi.
type: str
machine_type:
description:
- QEMU machine type is the actual chipset of the virtual machine.
type: str
merge_type:
description:
- Whether to override the default patch merge approach with a specific type.
- If more than one merge type is given, the merge types will be tried in order.
- "Defaults to C(['strategic-merge', 'merge']), which is ideal for using the same parameters
on resource kinds that combine Custom Resources and built-in resources, as
Custom Resource Definitions typically aren't updatable by the usual strategic merge."
- "See U(https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/#use-a-json-merge-patch-to-update-a-deployment)"
type: list
choices: [ json, merge, strategic-merge ]
cpu_shares:
description:
- "Specify CPU shares."
type: int
cpu_limit:
description:
- "Is converted to its millicore value and multiplied by 100. The resulting value is the total amount of CPU time that a container can use
every 100ms. A virtual machine cannot use more than its share of CPU time during this interval."
type: int
cpu_cores:
description:
- "Number of CPU cores."
type: int
cpu_model:
description:
- "CPU model."
- "You can check list of available models here: U(https://github.com/libvirt/libvirt/blob/master/src/cpu_map/index.xml)."
- "I(Note:) User can define default CPU model via as I(default-cpu-model) in I(kubevirt-config) I(ConfigMap), if not set I(host-model) is used."
- "I(Note:) Be sure that node CPU model where you run a VM, has the same or higher CPU family."
- "I(Note:) If CPU model wasn't defined, the VM will have CPU model closest to one that used on the node where the VM is running."
type: str
bootloader:
description:
- "Specify the bootloader of the virtual machine."
- "All virtual machines use BIOS by default for booting."
type: str
smbios_uuid:
description:
- "In order to provide a consistent view on the virtualized hardware for the guest OS, the SMBIOS UUID can be set."
type: str
cpu_features:
description:
- "List of dictionary to fine-tune features provided by the selected CPU model."
- "I(Note): Policy attribute can either be omitted or contain one of the following policies: force, require, optional, disable, forbid."
- "I(Note): In case a policy is omitted for a feature, it will default to require."
- "More information about policies: U(https://libvirt.org/formatdomain.html#elementsCPU)"
type: list
headless:
description:
- "Specify if the virtual machine should have attached a minimal Video and Graphics device configuration."
- "By default a minimal Video and Graphics device configuration will be applied to the VirtualMachineInstance. The video device is vga
compatible and comes with a memory size of 16 MB."
hugepage_size:
description:
- "Specify huge page size."
type: str
tablets:
description:
- "Specify tablets to be used as input devices"
type: list
hostname:
description:
- "Specifies the hostname of the virtual machine. The hostname will be set either by dhcp, cloud-init if configured or virtual machine
name will be used."
subdomain:
description:
- "If specified, the fully qualified virtual machine hostname will be hostname.subdomain.namespace.svc.cluster_domain. If not specified,
the virtual machine will not have a domain name at all. The DNS entry will resolve to the virtual machine, no matter if the virtual machine
itself can pick up a hostname."
requirements:
- python >= 2.7
- openshift >= 0.8.2
notes:
- "In order to use this module you have to install Openshift Python SDK.
To ensure it's installed with correct version you can create the following task:
I(pip: name=openshift>=0.8.2)"
'''

View File

@@ -0,0 +1,100 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2018, KubeVirt Team <@kubevirt>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
class ModuleDocFragment(object):
# Standard oVirt documentation fragment
DOCUMENTATION = r'''
options:
disks:
description:
- List of dictionaries which specify disks of the virtual machine.
- "A disk can be made accessible via four different types: I(disk), I(lun), I(cdrom), I(floppy)."
- "All possible configuration options are available in U(https://kubevirt.io/api-reference/master/definitions.html#_v1_disk)"
- Each disk must have specified a I(volume) that declares which volume type of the disk
All possible configuration options of volume are available in U(https://kubevirt.io/api-reference/master/definitions.html#_v1_volume).
type: list
labels:
description:
- Labels are key/value pairs that are attached to virtual machines. Labels are intended to be used to
specify identifying attributes of virtual machines that are meaningful and relevant to users, but do not directly
imply semantics to the core system. Labels can be used to organize and to select subsets of virtual machines.
Labels can be attached to virtual machines at creation time and subsequently added and modified at any time.
- More on labels that are used for internal implementation U(https://kubevirt.io/user-guide/#/misc/annotations_and_labels)
type: dict
interfaces:
description:
- An interface defines a virtual network interface of a virtual machine (also called a frontend).
- All possible configuration options interfaces are available in U(https://kubevirt.io/api-reference/master/definitions.html#_v1_interface)
- Each interface must have specified a I(network) that declares which logical or physical device it is connected to (also called as backend).
All possible configuration options of network are available in U(https://kubevirt.io/api-reference/master/definitions.html#_v1_network).
type: list
cloud_init_nocloud:
description:
- "Represents a cloud-init NoCloud user-data source. The NoCloud data will be added
as a disk to the virtual machine. A proper cloud-init installation is required inside the guest.
More information U(https://kubevirt.io/api-reference/master/definitions.html#_v1_cloudinitnocloudsource)"
type: dict
affinity:
description:
- "Describes node affinity scheduling rules for the vm."
type: dict
suboptions:
soft:
description:
- "The scheduler will prefer to schedule vms to nodes that satisfy the affinity expressions specified by this field, but it may choose a
node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for
each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute
a sum by iterating through the elements of this field and adding C(weight) to the sum if the node has vms which matches the corresponding
C(term); the nodes with the highest sum are the most preferred."
type: dict
hard:
description:
- "If the affinity requirements specified by this field are not met at scheduling time, the vm will not be scheduled onto the node. If
the affinity requirements specified by this field cease to be met at some point during vm execution (e.g. due to a vm label update), the
system may or may not try to eventually evict the vm from its node. When there are multiple elements, the lists of nodes corresponding to
each C(term) are intersected, i.e. all terms must be satisfied."
type: dict
node_affinity:
description:
- "Describes vm affinity scheduling rules e.g. co-locate this vm in the same node, zone, etc. as some other vms"
type: dict
suboptions:
soft:
description:
- "The scheduler will prefer to schedule vms to nodes that satisfy the affinity expressions specified by this field, but it may choose
a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e.
for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.),
compute a sum by iterating through the elements of this field and adding C(weight) to the sum if the node matches the corresponding
match_expressions; the nodes with the highest sum are the most preferred."
type: dict
hard:
description:
- "If the affinity requirements specified by this field are not met at scheduling time, the vm will not be scheduled onto the node. If
the affinity requirements specified by this field cease to be met at some point during vm execution (e.g. due to an update), the system
may or may not try to eventually evict the vm from its node."
type: dict
anti_affinity:
description:
- "Describes vm anti-affinity scheduling rules e.g. avoid putting this vm in the same node, zone, etc. as some other vms."
type: dict
suboptions:
soft:
description:
- "The scheduler will prefer to schedule vms to nodes that satisfy the anti-affinity expressions specified by this field, but it may
choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights,
i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions,
etc.), compute a sum by iterating through the elements of this field and adding C(weight) to the sum if the node has vms which matches
the corresponding C(term); the nodes with the highest sum are the most preferred."
type: dict
hard:
description:
- "If the anti-affinity requirements specified by this field are not met at scheduling time, the vm will not be scheduled onto the node.
If the anti-affinity requirements specified by this field cease to be met at some point during vm execution (e.g. due to a vm label
update), the system may or may not try to eventually evict the vm from its node. When there are multiple elements, the lists of nodes
corresponding to each C(term) are intersected, i.e. all terms must be satisfied."
type: dict
'''

View File

@@ -5,9 +5,6 @@
# Copyright: (c) 2017-2018 Keller Fuchs (@KellerFuchs) <kellerfuchs@hashbang.sh>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
class ModuleDocFragment(object):
# Standard LDAP documentation fragment
@@ -15,7 +12,7 @@ class ModuleDocFragment(object):
options:
bind_dn:
description:
- A DN to bind with. If this is omitted, we'll try a SASL bind with the EXTERNAL mechanism as default.
- A DN to bind with. If this is omitted, we'll try a SASL bind with the EXTERNAL mechanism.
- If this is blank, we'll use an anonymous bind.
type: str
bind_pw:
@@ -27,15 +24,6 @@ options:
description:
- The DN of the entry to add or remove.
type: str
referrals_chasing:
choices: [disabled, anonymous]
default: anonymous
type: str
description:
- Set the referrals chasing behavior.
- C(anonymous) follow referrals anonymously. This is the default behavior.
- C(disabled) disable referrals chasing. This sets C(OPT_REFERRALS) to off.
version_added: 2.0.0
server_uri:
description:
- A URI to the LDAP server.
@@ -53,12 +41,4 @@ options:
- This should only be used on sites using self-signed certificates.
type: bool
default: yes
sasl_class:
description:
- The class to use for SASL authentication.
- possible choices are C(external), C(gssapi).
type: str
choices: ['external', 'gssapi']
default: external
version_added: "2.0.0"
'''

View File

@@ -1,10 +1,34 @@
# -*- coding: utf-8 -*-
# This code is part of Ansible, but is an independent component.
# This particular file snippet, and this file snippet only, is BSD licensed.
# Modules you write using this snippet, which is embedded dynamically by
# Ansible still belong to the author of the module, and may assign their
# own license to the complete work.
#
# Copyright (C) 2017 Lenovo, Inc.
# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
class ModuleDocFragment(object):

View File

@@ -3,9 +3,6 @@
# Copyright: (c) 2017, Daniel Korn <korndaniel1@gmail.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
class ModuleDocFragment(object):
@@ -15,14 +12,14 @@ options:
manageiq_connection:
description:
- ManageIQ connection configuration information.
required: false
required: true
type: dict
suboptions:
url:
description:
- ManageIQ environment url. C(MIQ_URL) env var if set. otherwise, it is required to pass it.
type: str
required: false
required: true
username:
description:
- ManageIQ username. C(MIQ_USERNAME) env var if set. otherwise, required if no token is passed in.
@@ -44,7 +41,7 @@ options:
ca_cert:
description:
- The path to a CA bundle file or directory with certificates. defaults to None.
type: str
type: path
aliases: [ ca_bundle_path ]
requirements:

View File

@@ -0,0 +1,79 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2015, Jonathan Mainguy <jon@soh.re>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
class ModuleDocFragment(object):
# Standard mysql documentation fragment
DOCUMENTATION = r'''
options:
login_user:
description:
- The username used to authenticate with.
type: str
login_password:
description:
- The password used to authenticate with.
type: str
login_host:
description:
- Host running the database.
- In some cases for local connections the I(login_unix_socket=/path/to/mysqld/socket),
that is usually C(/var/run/mysqld/mysqld.sock), needs to be used instead of I(login_host=localhost).
type: str
default: localhost
login_port:
description:
- Port of the MySQL server. Requires I(login_host) be defined as other than localhost if login_port is used.
type: int
default: 3306
login_unix_socket:
description:
- The path to a Unix domain socket for local connections.
type: str
connect_timeout:
description:
- The connection timeout when connecting to the MySQL server.
type: int
default: 30
config_file:
description:
- Specify a config file from which user and password are to be read.
type: path
default: '~/.my.cnf'
ca_cert:
description:
- The path to a Certificate Authority (CA) certificate. This option, if used, must specify the same certificate
as used by the server.
type: path
aliases: [ ssl_ca ]
client_cert:
description:
- The path to a client public key certificate.
type: path
aliases: [ ssl_cert ]
client_key:
description:
- The path to the client private key.
type: path
aliases: [ ssl_key ]
requirements:
- PyMySQL (Python 2.7 and Python 3.X), or
- MySQLdb (Python 2.x)
notes:
- Requires the PyMySQL (Python 2.7 and Python 3.X) or MySQL-python (Python 2.X) package on the remote host.
The Python package may be installed with apt-get install python-pymysql (Ubuntu; see M(apt)) or
yum install python2-PyMySQL (RHEL/CentOS/Fedora; see M(yum)). You can also use dnf install python2-PyMySQL
for newer versions of Fedora; see M(dnf).
- Both C(login_password) and C(login_user) are required when you are
passing credentials. If none are present, the module will attempt to read
the credentials from C(~/.my.cnf), and finally fall back to using the MySQL
default login of 'root' with no password.
- If there are problems with local connections, using I(login_unix_socket=/path/to/mysqld/socket)
instead of I(login_host=localhost) might help. As an example, the default MariaDB installation of version 10.4
and later uses the unix_socket authentication plugin by default that
without using I(login_unix_socket=/var/run/mysqld/mysqld.sock) (the default path)
causes the error ``Host '127.0.0.1' is not allowed to connect to this MariaDB server``.
'''

View File

@@ -3,9 +3,6 @@
# Copyright: (c) 2015, Peter Sprygada <psprygada@ansible.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
class ModuleDocFragment(object):
@@ -24,6 +21,7 @@ options:
- Value can also be specified using C(INFOBLOX_HOST) environment
variable.
type: str
required: true
username:
description:
- Configures the username to use to authenticate the connection to
@@ -78,24 +76,6 @@ options:
variable.
type: int
default: 1000
http_pool_connections:
description:
- Number of pools to be used by the C(infoblox_client.Connector) object.
- This is passed as-is to the underlying C(requests.adapters.HTTPAdapter) class.
type: int
default: 10
http_pool_maxsize:
description:
- Maximum number of connections per pool to be used by the C(infoblox_client.Connector) object.
- This is passed as-is to the underlying C(requests.adapters.HTTPAdapter) class.
type: int
default: 10
silent_ssl_warnings:
description:
- Disable C(urllib3) SSL warnings in the C(infoblox_client.Connector) object.
- This is passed as-is to the underlying C(requests.adapters.HTTPAdapter) class.
type: bool
default: true
notes:
- "This module must be run locally, which can be achieved by specifying C(connection: local)."
- Please read the :ref:`nios_guide` for more detailed information on how to use Infoblox with Ansible.

View File

@@ -1,51 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2020 FERREIRA Christophe <christophe.ferreira@cnaf.fr>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
class ModuleDocFragment(object):
# Standard files documentation fragment
DOCUMENTATION = r'''
options:
host:
description:
- FQDN of Nomad server.
required: true
type: str
use_ssl:
description:
- Use TLS/SSL connection.
type: bool
default: true
timeout:
description:
- Timeout (in seconds) for the request to Nomad.
type: int
default: 5
validate_certs:
description:
- Enable TLS/SSL certificate validation.
type: bool
default: true
client_cert:
description:
- Path of certificate for TLS/SSL.
type: path
client_key:
description:
- Path of certificate's private key for TLS/SSL.
type: path
namespace:
description:
- Namespace for Nomad.
type: str
token:
description:
- ACL token for authentification.
type: str
'''

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