mirror of
https://github.com/ansible-collections/ansible.posix.git
synced 2026-01-12 15:45:20 +01:00
Compare commits
11 commits
45c2f9bbe4
...
f35b18cba5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f35b18cba5 | ||
|
|
05ee6ebc2a | ||
|
|
c394f6778d | ||
|
|
748bad22ad | ||
|
|
6f95c8b356 | ||
|
|
85c958ccb8 | ||
|
|
ad414c87b4 | ||
|
|
34a9cf3e4d | ||
|
|
63fba50912 | ||
|
|
8ec2c261bd | ||
|
|
230e5f2a98 |
22 changed files with 227 additions and 218 deletions
|
|
@ -36,12 +36,79 @@ variables:
|
||||||
resources:
|
resources:
|
||||||
containers:
|
containers:
|
||||||
- container: default
|
- container: default
|
||||||
image: quay.io/ansible/azure-pipelines-test-container:4.0.1
|
image: quay.io/ansible/azure-pipelines-test-container:main
|
||||||
|
|
||||||
pool: Standard
|
pool: Standard
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
|
|
||||||
|
- stage: Sanity_devel
|
||||||
|
displayName: Ansible devel sanity
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
nameFormat: "{0}"
|
||||||
|
testFormat: "devel/{0}"
|
||||||
|
targets:
|
||||||
|
- name: Sanity
|
||||||
|
test: sanity
|
||||||
|
- name: Units
|
||||||
|
test: units
|
||||||
|
# - name: Lint
|
||||||
|
# test: lint
|
||||||
|
- stage: Sanity_2_16
|
||||||
|
displayName: Ansible 2.16 sanity
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
nameFormat: "{0}"
|
||||||
|
testFormat: "2.16/{0}"
|
||||||
|
targets:
|
||||||
|
- name: Sanity
|
||||||
|
test: sanity
|
||||||
|
- name: Units
|
||||||
|
test: units
|
||||||
|
- stage: Sanity_2_15
|
||||||
|
displayName: Ansible 2.15 sanity
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
nameFormat: "{0}"
|
||||||
|
testFormat: "2.15/{0}"
|
||||||
|
targets:
|
||||||
|
- name: Sanity
|
||||||
|
test: sanity
|
||||||
|
- name: Units
|
||||||
|
test: units
|
||||||
|
- stage: Sanity_2_14
|
||||||
|
displayName: Ansible 2.14 sanity
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
nameFormat: "{0}"
|
||||||
|
testFormat: "2.14/{0}"
|
||||||
|
targets:
|
||||||
|
- name: Sanity
|
||||||
|
test: sanity
|
||||||
|
- name: Units
|
||||||
|
test: units
|
||||||
|
- stage: Sanity_2_9
|
||||||
|
displayName: Ansible 2.9 sanity
|
||||||
|
dependsOn: []
|
||||||
|
jobs:
|
||||||
|
- template: templates/matrix.yml
|
||||||
|
parameters:
|
||||||
|
nameFormat: "{0}"
|
||||||
|
testFormat: "2.9/{0}"
|
||||||
|
targets:
|
||||||
|
- name: Sanity
|
||||||
|
test: sanity
|
||||||
|
- name: Units
|
||||||
|
test: units
|
||||||
## Docker
|
## Docker
|
||||||
- stage: Docker_devel
|
- stage: Docker_devel
|
||||||
displayName: Docker devel
|
displayName: Docker devel
|
||||||
|
|
@ -110,50 +177,6 @@ stages:
|
||||||
test: ubuntu2004
|
test: ubuntu2004
|
||||||
- name: Ubuntu 22.04
|
- name: Ubuntu 22.04
|
||||||
test: ubuntu2204
|
test: ubuntu2204
|
||||||
- stage: Docker_2_13
|
|
||||||
displayName: Docker 2.13
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
testFormat: 2.13/linux/{0}/1
|
|
||||||
targets:
|
|
||||||
- name: CentOS 7
|
|
||||||
test: centos7
|
|
||||||
- name: Fedora 34
|
|
||||||
test: fedora34
|
|
||||||
- name: Fedora 35
|
|
||||||
test: fedora35
|
|
||||||
- name: openSUSE 15 py3
|
|
||||||
test: opensuse15
|
|
||||||
- name: Ubuntu 18.04
|
|
||||||
test: ubuntu1804
|
|
||||||
- name: Ubuntu 20.04
|
|
||||||
test: ubuntu2004
|
|
||||||
- stage: Docker_2_12
|
|
||||||
displayName: Docker 2.12
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
testFormat: 2.12/linux/{0}/1
|
|
||||||
targets:
|
|
||||||
- name: CentOS 6
|
|
||||||
test: centos6
|
|
||||||
- name: CentOS 7
|
|
||||||
test: centos7
|
|
||||||
- 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
|
|
||||||
- stage: Docker_2_9
|
- stage: Docker_2_9
|
||||||
displayName: Docker 2.9
|
displayName: Docker 2.9
|
||||||
dependsOn: []
|
dependsOn: []
|
||||||
|
|
@ -186,6 +209,8 @@ stages:
|
||||||
targets:
|
targets:
|
||||||
- name: RHEL 9.3
|
- name: RHEL 9.3
|
||||||
test: rhel/9.3
|
test: rhel/9.3
|
||||||
|
- name: FreeBSD 13.2
|
||||||
|
test: freebsd/13.2
|
||||||
- stage: Remote_2_16
|
- stage: Remote_2_16
|
||||||
displayName: Remote 2.16
|
displayName: Remote 2.16
|
||||||
dependsOn: []
|
dependsOn: []
|
||||||
|
|
@ -198,6 +223,8 @@ stages:
|
||||||
test: rhel/8.8
|
test: rhel/8.8
|
||||||
- name: RHEL 9.2
|
- name: RHEL 9.2
|
||||||
test: rhel/9.2
|
test: rhel/9.2
|
||||||
|
- name: FreeBSD 13.2
|
||||||
|
test: freebsd/13.2
|
||||||
|
|
||||||
- stage: Remote_2_15
|
- stage: Remote_2_15
|
||||||
displayName: Remote 2.15
|
displayName: Remote 2.15
|
||||||
|
|
@ -213,6 +240,10 @@ stages:
|
||||||
test: rhel/8.7
|
test: rhel/8.7
|
||||||
- name: RHEL 9.1
|
- name: RHEL 9.1
|
||||||
test: rhel/9.1
|
test: rhel/9.1
|
||||||
|
- name: FreeBSD 13.1
|
||||||
|
test: freebsd/13.1
|
||||||
|
- name: FreeBSD 12.4
|
||||||
|
test: freebsd/12.4
|
||||||
- stage: Remote_2_14
|
- stage: Remote_2_14
|
||||||
displayName: Remote 2.14
|
displayName: Remote 2.14
|
||||||
dependsOn: []
|
dependsOn: []
|
||||||
|
|
@ -225,30 +256,10 @@ stages:
|
||||||
test: rhel/7.9
|
test: rhel/7.9
|
||||||
- name: RHEL 8.6
|
- name: RHEL 8.6
|
||||||
test: rhel/8.6
|
test: rhel/8.6
|
||||||
- stage: Remote_2_13
|
- name: FreeBSD 13.1
|
||||||
displayName: Remote 2.13
|
test: freebsd/13.1
|
||||||
dependsOn: []
|
- name: FreeBSD 12.4
|
||||||
jobs:
|
test: freebsd/12.4
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
testFormat: 2.13/{0}/1
|
|
||||||
targets:
|
|
||||||
- name: RHEL 7.9
|
|
||||||
test: rhel/7.9
|
|
||||||
- name: RHEL 8.5
|
|
||||||
test: rhel/8.5
|
|
||||||
- stage: Remote_2_12
|
|
||||||
displayName: Remote 2.12
|
|
||||||
dependsOn: []
|
|
||||||
jobs:
|
|
||||||
- template: templates/matrix.yml
|
|
||||||
parameters:
|
|
||||||
testFormat: 2.12/{0}/1
|
|
||||||
targets:
|
|
||||||
- name: RHEL 7.9
|
|
||||||
test: rhel/7.9
|
|
||||||
- name: RHEL 8.4
|
|
||||||
test: rhel/8.4
|
|
||||||
- stage: Remote_2_9
|
- stage: Remote_2_9
|
||||||
displayName: Remote 2.9
|
displayName: Remote 2.9
|
||||||
dependsOn: []
|
dependsOn: []
|
||||||
|
|
@ -267,18 +278,19 @@ stages:
|
||||||
- stage: Summary
|
- stage: Summary
|
||||||
condition: succeededOrFailed()
|
condition: succeededOrFailed()
|
||||||
dependsOn:
|
dependsOn:
|
||||||
|
- Sanity_2_9
|
||||||
- Remote_2_9
|
- Remote_2_9
|
||||||
- Docker_2_9
|
- Docker_2_9
|
||||||
- Remote_2_12
|
- Sanity_2_14
|
||||||
- Docker_2_12
|
|
||||||
- Remote_2_13
|
|
||||||
- Docker_2_13
|
|
||||||
- Remote_2_14
|
- Remote_2_14
|
||||||
- Docker_2_14
|
- Docker_2_14
|
||||||
|
- Sanity_2_15
|
||||||
- Remote_2_15
|
- Remote_2_15
|
||||||
- Docker_2_15
|
- Docker_2_15
|
||||||
|
- Sanity_2_16
|
||||||
- Remote_2_16
|
- Remote_2_16
|
||||||
- Docker_2_16
|
- Docker_2_16
|
||||||
|
- Sanity_devel
|
||||||
- Remote_devel
|
- Remote_devel
|
||||||
- Docker_devel
|
- Docker_devel
|
||||||
jobs:
|
jobs:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
minor_changes:
|
||||||
|
- synchronize - elevating privileges now works even when `sudo` requires entering the `become_pass`
|
||||||
10
changelogs/fragments/460-respawn.yaml
Normal file
10
changelogs/fragments/460-respawn.yaml
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
minor_changes:
|
||||||
|
- "seboolean - respawn module to use the system python interpreter when the ``selinux`` python module is not available for ``ansible_python_interpreter``
|
||||||
|
(https://github.com/ansible-collections/ansible.posix/pull/460)."
|
||||||
|
- "selinux - respawn module to use the system python interpreter when the ``selinux`` python module is not available for ``ansible_python_interpreter``
|
||||||
|
(https://github.com/ansible-collections/ansible.posix/pull/460)."
|
||||||
|
- "firewalld - respawn module to use the system python interpreter when the ``firewall`` python module is not available for ``ansible_python_interpreter``
|
||||||
|
(https://github.com/ansible-collections/ansible.posix/pull/460)."
|
||||||
|
- "firewalld_info - respawn module to use the system python interpreter when the ``firewall`` python module is not available for ``ansible_python_interpreter``
|
||||||
|
(https://github.com/ansible-collections/ansible.posix/pull/460)."
|
||||||
|
|
@ -580,7 +580,7 @@ Notes
|
||||||
|
|
||||||
- The user and permissions for the synchronize `dest` are those of the `remote_user` on the destination host or the `become_user` if `become=yes` is active.
|
- The user and permissions for the synchronize `dest` are those of the `remote_user` on the destination host or the `become_user` if `become=yes` is active.
|
||||||
- In Ansible 2.0 a bug in the synchronize module made become occur on the "local host". This was fixed in Ansible 2.0.1.
|
- In Ansible 2.0 a bug in the synchronize module made become occur on the "local host". This was fixed in Ansible 2.0.1.
|
||||||
- Currently, synchronize is limited to elevating permissions via passwordless sudo. This is because rsync itself is connecting to the remote machine and rsync doesn't give us a way to pass sudo credentials in.
|
- Currently, synchronize is limited to elevating permissions via sudo. This now even works when password entry is required.
|
||||||
- Currently there are only a few connection types which support synchronize (ssh, paramiko, local, and docker) because a sync strategy has been determined for those connection types. Note that the connection for these must not need a password as rsync itself is making the connection and rsync does not provide us a way to pass a password to the connection.
|
- Currently there are only a few connection types which support synchronize (ssh, paramiko, local, and docker) because a sync strategy has been determined for those connection types. Note that the connection for these must not need a password as rsync itself is making the connection and rsync does not provide us a way to pass a password to the connection.
|
||||||
- Expect that dest=~/x will be ~<remote_user>/x even if using sudo.
|
- Expect that dest=~/x will be ~<remote_user>/x even if using sudo.
|
||||||
- Inspect the verbose output to validate the destination user/host/path are what was expected.
|
- Inspect the verbose output to validate the destination user/host/path are what was expected.
|
||||||
|
|
|
||||||
|
|
@ -390,10 +390,24 @@ class ActionModule(ActionBase):
|
||||||
# If no rsync_path is set, become was originally set, and dest is
|
# If no rsync_path is set, become was originally set, and dest is
|
||||||
# remote then add privilege escalation here.
|
# remote then add privilege escalation here.
|
||||||
if self._play_context.become_method == 'sudo':
|
if self._play_context.become_method == 'sudo':
|
||||||
if self._play_context.become_user:
|
|
||||||
rsync_path = 'sudo -u %s rsync' % self._play_context.become_user
|
# if become is set, we can either rely on passwordless sudo or pass the password
|
||||||
|
if self._play_context.become_pass is None:
|
||||||
|
rsync_path = 'sudo '
|
||||||
else:
|
else:
|
||||||
rsync_path = 'sudo rsync'
|
# pass the become password using the environment so that the synchronize module
|
||||||
|
# can wrap ssh on the host with a shell script that injects the password into
|
||||||
|
# stdin, allowing for `sudo -S` on the target machine to retrieve the password
|
||||||
|
if hasattr(self._task, 'environment'):
|
||||||
|
self._task.environment = []
|
||||||
|
self._task.environment.append({'BECOME_PASS': self._play_context.become_pass})
|
||||||
|
_tmp_args['_ssh_wrapper'] = True
|
||||||
|
rsync_path = 'sudo -S '
|
||||||
|
|
||||||
|
if self._play_context.become_user:
|
||||||
|
rsync_path += '-u %s rsync' % self._play_context.become_user
|
||||||
|
else:
|
||||||
|
rsync_path += 'rsync'
|
||||||
# TODO: have to add in the rest of the become methods here
|
# TODO: have to add in the rest of the become methods here
|
||||||
|
|
||||||
# We cannot use privilege escalation on the machine running the
|
# We cannot use privilege escalation on the machine running the
|
||||||
|
|
|
||||||
45
plugins/module_utils/_respawn.py
Normal file
45
plugins/module_utils/_respawn.py
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
# Copyright (c) 2023 Maxwell G <maxwell@gtmx.me>
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
"""
|
||||||
|
Helpers to respawn a module to run using the system interpreter
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
try:
|
||||||
|
from ansible.module_utils.common import respawn
|
||||||
|
except ImportError:
|
||||||
|
HAS_RESPAWN_UTIL = False
|
||||||
|
else:
|
||||||
|
HAS_RESPAWN_UTIL = True
|
||||||
|
|
||||||
|
|
||||||
|
SYSTEM_PYTHON_INTERPRETERS = (
|
||||||
|
"/usr/bin/libexec/platform-python",
|
||||||
|
"/usr/bin/python3",
|
||||||
|
"/usr/bin/python2",
|
||||||
|
"/usr/bin/python",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def respawn_module(module):
|
||||||
|
"""
|
||||||
|
Respawn an ansible module to using the first interpreter in
|
||||||
|
SYSTEM_PYTHON_INTERPRETERS that contains `module`.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
module (str): Name of python module to search for
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Returns None if the module cannot be respawned.
|
||||||
|
"""
|
||||||
|
if respawn.has_respawned():
|
||||||
|
return
|
||||||
|
interpreter = respawn.probe_interpreters_for_module(
|
||||||
|
SYSTEM_PYTHON_INTERPRETERS, module
|
||||||
|
)
|
||||||
|
if interpreter:
|
||||||
|
respawn.respawn_module(interpreter)
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
from ansible_collections.ansible.posix.plugins.module_utils.version import LooseVersion
|
from ansible_collections.ansible.posix.plugins.module_utils.version import LooseVersion
|
||||||
|
from ansible_collections.ansible.posix.plugins.module_utils._respawn import respawn_module, HAS_RESPAWN_UTIL
|
||||||
from ansible.module_utils.basic import missing_required_lib
|
from ansible.module_utils.basic import missing_required_lib
|
||||||
|
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
@ -314,6 +315,8 @@ class FirewallTransaction(object):
|
||||||
installed version (%s) likely too old. Requires firewalld >= 0.2.11" % FW_VERSION)
|
installed version (%s) likely too old. Requires firewalld >= 0.2.11" % FW_VERSION)
|
||||||
|
|
||||||
if import_failure:
|
if import_failure:
|
||||||
|
if HAS_RESPAWN_UTIL:
|
||||||
|
respawn_module("firewall")
|
||||||
module.fail_json(
|
module.fail_json(
|
||||||
msg=missing_required_lib('firewall') + '. Version 0.2.11 or newer required (0.3.9 or newer for offline operations)'
|
msg=missing_required_lib('firewall') + '. Version 0.2.11 or newer required (0.3.9 or newer for offline operations)'
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -211,6 +211,7 @@ firewalld_info:
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||||
from ansible.module_utils._text import to_native
|
from ansible.module_utils._text import to_native
|
||||||
|
from ansible_collections.ansible.posix.plugins.module_utils._respawn import respawn_module, HAS_RESPAWN_UTIL
|
||||||
from ansible_collections.ansible.posix.plugins.module_utils.version import StrictVersion
|
from ansible_collections.ansible.posix.plugins.module_utils.version import StrictVersion
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -322,6 +323,12 @@ def main():
|
||||||
)
|
)
|
||||||
|
|
||||||
# Exit with failure message if requirements modules are not installed.
|
# Exit with failure message if requirements modules are not installed.
|
||||||
|
if not HAS_DBUS and not HAS_FIREWALLD and HAS_RESPAWN_UTIL:
|
||||||
|
# Only respawn the module if both libraries are missing.
|
||||||
|
# If only one is available, then usage of the "wrong" (i.e. not the system one)
|
||||||
|
# python interpreter is likely not the problem.
|
||||||
|
respawn_module("firewall")
|
||||||
|
|
||||||
if not HAS_DBUS:
|
if not HAS_DBUS:
|
||||||
module.fail_json(msg=missing_required_lib('python-dbus'))
|
module.fail_json(msg=missing_required_lib('python-dbus'))
|
||||||
if not HAS_FIREWALLD:
|
if not HAS_FIREWALLD:
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@ except ImportError:
|
||||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||||
from ansible.module_utils.six import binary_type
|
from ansible.module_utils.six import binary_type
|
||||||
from ansible.module_utils._text import to_bytes, to_text
|
from ansible.module_utils._text import to_bytes, to_text
|
||||||
|
from ansible_collections.ansible.posix.plugins.module_utils._respawn import respawn_module, HAS_RESPAWN_UTIL
|
||||||
|
|
||||||
|
|
||||||
def get_runtime_status(ignore_selinux_state=False):
|
def get_runtime_status(ignore_selinux_state=False):
|
||||||
|
|
@ -281,6 +282,12 @@ def main():
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if not HAVE_SELINUX and not HAVE_SEMANAGE and HAS_RESPAWN_UTIL:
|
||||||
|
# Only respawn the module if both libraries are missing.
|
||||||
|
# If only one is available, then usage of the "wrong" (i.e. not the system one)
|
||||||
|
# python interpreter is likely not the problem.
|
||||||
|
respawn_module("selinux")
|
||||||
|
|
||||||
if not HAVE_SELINUX:
|
if not HAVE_SELINUX:
|
||||||
module.fail_json(msg=missing_required_lib('libselinux-python'), exception=SELINUX_IMP_ERR)
|
module.fail_json(msg=missing_required_lib('libselinux-python'), exception=SELINUX_IMP_ERR)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,8 @@ from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||||
from ansible.module_utils.common.process import get_bin_path
|
from ansible.module_utils.common.process import get_bin_path
|
||||||
from ansible.module_utils.facts.utils import get_file_lines
|
from ansible.module_utils.facts.utils import get_file_lines
|
||||||
|
|
||||||
|
from ansible_collections.ansible.posix.plugins.module_utils._respawn import respawn_module, HAS_RESPAWN_UTIL
|
||||||
|
|
||||||
|
|
||||||
# getter subroutines
|
# getter subroutines
|
||||||
def get_config_state(configfile):
|
def get_config_state(configfile):
|
||||||
|
|
@ -236,6 +238,8 @@ def main():
|
||||||
)
|
)
|
||||||
|
|
||||||
if not HAS_SELINUX:
|
if not HAS_SELINUX:
|
||||||
|
if HAS_RESPAWN_UTIL:
|
||||||
|
respawn_module("selinux")
|
||||||
module.fail_json(msg=missing_required_lib('libselinux-python'), exception=SELINUX_IMP_ERR)
|
module.fail_json(msg=missing_required_lib('libselinux-python'), exception=SELINUX_IMP_ERR)
|
||||||
|
|
||||||
# global vars
|
# global vars
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,7 @@ notes:
|
||||||
delegate_to host when delegate_to is used).
|
delegate_to host when delegate_to is used).
|
||||||
- The user and permissions for the synchronize `dest` are those of the `remote_user` on the destination host or the `become_user` if `become=yes` is active.
|
- The user and permissions for the synchronize `dest` are those of the `remote_user` on the destination host or the `become_user` if `become=yes` is active.
|
||||||
- In Ansible 2.0 a bug in the synchronize module made become occur on the "local host". This was fixed in Ansible 2.0.1.
|
- In Ansible 2.0 a bug in the synchronize module made become occur on the "local host". This was fixed in Ansible 2.0.1.
|
||||||
- Currently, synchronize is limited to elevating permissions via passwordless sudo. This is because rsync itself is connecting to the remote machine
|
- Currently, synchronize is limited to elevating permissions via sudo. This now even works when password entry is required.
|
||||||
and rsync doesn't give us a way to pass sudo credentials in.
|
and rsync doesn't give us a way to pass sudo credentials in.
|
||||||
- Currently there are only a few connection types which support synchronize (ssh, paramiko, local, and docker) because a sync strategy has been
|
- Currently there are only a few connection types which support synchronize (ssh, paramiko, local, and docker) because a sync strategy has been
|
||||||
determined for those connection types. Note that the connection for these must not need a password as rsync itself is making the connection and
|
determined for those connection types. Note that the connection for these must not need a password as rsync itself is making the connection and
|
||||||
|
|
@ -414,6 +414,7 @@ def main():
|
||||||
rsync_opts=dict(type='list', default=[], elements='str'),
|
rsync_opts=dict(type='list', default=[], elements='str'),
|
||||||
ssh_args=dict(type='str'),
|
ssh_args=dict(type='str'),
|
||||||
ssh_connection_multiplexing=dict(type='bool', default=False),
|
ssh_connection_multiplexing=dict(type='bool', default=False),
|
||||||
|
_ssh_wrapper=dict(type='bool', default=False),
|
||||||
partial=dict(type='bool', default=False),
|
partial=dict(type='bool', default=False),
|
||||||
verify_host=dict(type='bool', default=False),
|
verify_host=dict(type='bool', default=False),
|
||||||
delay_updates=dict(type='bool', default=True),
|
delay_updates=dict(type='bool', default=True),
|
||||||
|
|
@ -456,6 +457,7 @@ def main():
|
||||||
rsync_opts = module.params['rsync_opts']
|
rsync_opts = module.params['rsync_opts']
|
||||||
ssh_args = module.params['ssh_args']
|
ssh_args = module.params['ssh_args']
|
||||||
ssh_connection_multiplexing = module.params['ssh_connection_multiplexing']
|
ssh_connection_multiplexing = module.params['ssh_connection_multiplexing']
|
||||||
|
ssh_wrapper = module.params['_ssh_wrapper']
|
||||||
verify_host = module.params['verify_host']
|
verify_host = module.params['verify_host']
|
||||||
link_dest = module.params['link_dest']
|
link_dest = module.params['link_dest']
|
||||||
delay_updates = module.params['delay_updates']
|
delay_updates = module.params['delay_updates']
|
||||||
|
|
@ -550,6 +552,13 @@ def main():
|
||||||
ssh_cmd_str = ' '.join(shlex_quote(arg) for arg in ssh_cmd)
|
ssh_cmd_str = ' '.join(shlex_quote(arg) for arg in ssh_cmd)
|
||||||
if ssh_args:
|
if ssh_args:
|
||||||
ssh_cmd_str += ' %s' % ssh_args
|
ssh_cmd_str += ' %s' % ssh_args
|
||||||
|
# When `become: yes` is set but the account on the target requires a password for sudo, we have to supply
|
||||||
|
# it from the host side by wrapping the remote shell and inserting the password into stdin.
|
||||||
|
# In the ActionPlugin, the password is assigned to the BECOME_PASS environment variable, so we will not have
|
||||||
|
# to make it visible if anyone logs the command issued by ansible.
|
||||||
|
# Adapted from https://askubuntu.com/a/1263657
|
||||||
|
if ssh_wrapper:
|
||||||
|
ssh_cmd_str = '/bin/sh -c "{ echo $BECOME_PASS; cat - ; } | ' + ssh_cmd_str + ' $0 $* &"'
|
||||||
cmd.append('--rsh=%s' % shlex_quote(ssh_cmd_str))
|
cmd.append('--rsh=%s' % shlex_quote(ssh_cmd_str))
|
||||||
|
|
||||||
if rsync_path:
|
if rsync_path:
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,6 @@
|
||||||
state: present
|
state: present
|
||||||
# This doesn't work for CentOS 6 because firewalld doesn't exist in CentOS6
|
# This doesn't work for CentOS 6 because firewalld doesn't exist in CentOS6
|
||||||
|
|
||||||
- name: Check to make sure the firewalld python module is available.
|
|
||||||
shell: "{{ansible_python.executable}} -c 'import firewall'"
|
|
||||||
register: check_output
|
|
||||||
ignore_errors: true
|
|
||||||
|
|
||||||
- name: Enable dbus-broker daemon
|
- name: Enable dbus-broker daemon
|
||||||
service:
|
service:
|
||||||
name: dbus-broker
|
name: dbus-broker
|
||||||
|
|
@ -30,7 +25,6 @@
|
||||||
state: started
|
state: started
|
||||||
|
|
||||||
- import_tasks: run_all_tests.yml
|
- import_tasks: run_all_tests.yml
|
||||||
when: check_output.rc == 0
|
|
||||||
|
|
||||||
- name: Test Offline Operations
|
- name: Test Offline Operations
|
||||||
block:
|
block:
|
||||||
|
|
@ -40,7 +34,6 @@
|
||||||
state: stopped
|
state: stopped
|
||||||
|
|
||||||
- import_tasks: run_all_tests.yml
|
- import_tasks: run_all_tests.yml
|
||||||
when: check_output.rc == 0
|
|
||||||
|
|
||||||
when:
|
when:
|
||||||
- ansible_facts.os_family == "RedHat" and ansible_facts.distribution_major_version is version('7', '>=')
|
- ansible_facts.os_family == "RedHat" and ansible_facts.distribution_major_version is version('7', '>=')
|
||||||
|
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
plugins/modules/synchronize.py pylint:blacklisted-name
|
|
||||||
plugins/modules/synchronize.py use-argspec-type-path
|
|
||||||
plugins/modules/synchronize.py validate-modules:doc-default-does-not-match-spec
|
|
||||||
plugins/modules/synchronize.py validate-modules:nonexistent-parameter-documented
|
|
||||||
plugins/modules/synchronize.py validate-modules:parameter-type-not-in-doc
|
|
||||||
plugins/modules/synchronize.py validate-modules:undocumented-parameter
|
|
||||||
tests/utils/shippable/check_matrix.py replace-urlopen
|
|
||||||
tests/utils/shippable/timing.py shebang
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
plugins/modules/synchronize.py pylint:blacklisted-name
|
|
||||||
plugins/modules/synchronize.py use-argspec-type-path
|
|
||||||
plugins/modules/synchronize.py validate-modules:doc-default-does-not-match-spec
|
|
||||||
plugins/modules/synchronize.py validate-modules:nonexistent-parameter-documented
|
|
||||||
plugins/modules/synchronize.py validate-modules:parameter-type-not-in-doc
|
|
||||||
plugins/modules/synchronize.py validate-modules:undocumented-parameter
|
|
||||||
tests/utils/shippable/check_matrix.py replace-urlopen
|
|
||||||
tests/utils/shippable/timing.py shebang
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
plugins/modules/synchronize.py pylint:disallowed-name
|
|
||||||
plugins/modules/synchronize.py use-argspec-type-path
|
|
||||||
plugins/modules/synchronize.py validate-modules:doc-default-does-not-match-spec
|
|
||||||
plugins/modules/synchronize.py validate-modules:nonexistent-parameter-documented
|
|
||||||
plugins/modules/synchronize.py validate-modules:parameter-type-not-in-doc
|
|
||||||
plugins/modules/synchronize.py validate-modules:undocumented-parameter
|
|
||||||
tests/utils/shippable/check_matrix.py replace-urlopen
|
|
||||||
tests/utils/shippable/timing.py shebang
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
|
plugins/modules/synchronize.py pylint:disallowed-name
|
||||||
plugins/modules/synchronize.py use-argspec-type-path
|
plugins/modules/synchronize.py use-argspec-type-path
|
||||||
plugins/modules/synchronize.py validate-modules:doc-default-does-not-match-spec
|
plugins/modules/synchronize.py validate-modules:doc-default-does-not-match-spec
|
||||||
plugins/modules/synchronize.py validate-modules:nonexistent-parameter-documented
|
plugins/modules/synchronize.py validate-modules:nonexistent-parameter-documented
|
||||||
plugins/modules/synchronize.py validate-modules:parameter-type-not-in-doc
|
plugins/modules/synchronize.py validate-modules:parameter-type-not-in-doc
|
||||||
plugins/modules/synchronize.py validate-modules:undocumented-parameter
|
plugins/modules/synchronize.py validate-modules:undocumented-parameter
|
||||||
|
tests/utils/shippable/timing.py shebang
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,4 @@ plugins/modules/synchronize.py validate-modules:doc-default-does-not-match-spec
|
||||||
plugins/modules/synchronize.py validate-modules:nonexistent-parameter-documented
|
plugins/modules/synchronize.py validate-modules:nonexistent-parameter-documented
|
||||||
plugins/modules/synchronize.py validate-modules:parameter-type-not-in-doc
|
plugins/modules/synchronize.py validate-modules:parameter-type-not-in-doc
|
||||||
plugins/modules/synchronize.py validate-modules:undocumented-parameter
|
plugins/modules/synchronize.py validate-modules:undocumented-parameter
|
||||||
tests/utils/shippable/check_matrix.py replace-urlopen
|
|
||||||
tests/utils/shippable/timing.py shebang
|
tests/utils/shippable/timing.py shebang
|
||||||
|
|
@ -30,7 +30,7 @@ class DictDataLoader(DataLoader):
|
||||||
|
|
||||||
def __init__(self, file_mapping=None):
|
def __init__(self, file_mapping=None):
|
||||||
file_mapping = {} if file_mapping is None else file_mapping
|
file_mapping = {} if file_mapping is None else file_mapping
|
||||||
assert type(file_mapping) == dict
|
assert isinstance(file_mapping, dict)
|
||||||
|
|
||||||
super(DictDataLoader, self).__init__()
|
super(DictDataLoader, self).__init__()
|
||||||
|
|
||||||
|
|
|
||||||
14
tests/utils/shippable/lint.sh
Executable file
14
tests/utils/shippable/lint.sh
Executable file
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -o pipefail -eux
|
||||||
|
|
||||||
|
echo "${PATH/\~/${HOME}}"
|
||||||
|
echo "${HOME}"
|
||||||
|
command -v ansible
|
||||||
|
|
||||||
|
pip install --upgrade --user pip
|
||||||
|
pip install --upgrade --user ansible-lint
|
||||||
|
|
||||||
|
PATH="${PATH/\~/${HOME}}" ansible-lint \
|
||||||
|
--exclude changelogs/ \
|
||||||
|
--profile=production
|
||||||
|
|
@ -1,7 +1,21 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Following logic in https://github.com/ansible-collections/collection_template/blob/main/.github/workflows/ansible-test.yml
|
||||||
set -o pipefail -eux
|
set -o pipefail -eux
|
||||||
|
|
||||||
|
if [ "${BASE_BRANCH:-}" ]; then
|
||||||
|
base_branch="origin/${BASE_BRANCH}"
|
||||||
|
else
|
||||||
|
base_branch=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run sanity tests inside a Docker container.
|
||||||
|
# The docker container has all the pinned dependencies that are
|
||||||
|
# required and all Python versions Ansible supports.
|
||||||
|
|
||||||
|
# See the documentation for the following GitHub action on
|
||||||
|
# https://github.com/ansible-community/ansible-test-gh-action/blob/main/README.md
|
||||||
|
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
ansible-test sanity --color -v --junit ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} \
|
ansible-test sanity --color -v --junit ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} \
|
||||||
--docker
|
--docker --base-branch "${base_branch}" --allow-disabled
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env python3.7
|
#!/usr/bin/env python3
|
||||||
from __future__ import (absolute_import, division, print_function)
|
from __future__ import (absolute_import, division, print_function)
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,109 +2,6 @@
|
||||||
|
|
||||||
set -o pipefail -eux
|
set -o pipefail -eux
|
||||||
|
|
||||||
declare -a args
|
|
||||||
IFS='/:' read -ra args <<< "$1"
|
|
||||||
|
|
||||||
version="${args[1]}"
|
|
||||||
group="${args[2]}"
|
|
||||||
|
|
||||||
if [[ "${COVERAGE:-}" == "--coverage" ]]; then
|
|
||||||
timeout=90
|
|
||||||
else
|
|
||||||
timeout=30
|
|
||||||
fi
|
|
||||||
|
|
||||||
group1=()
|
|
||||||
group2=()
|
|
||||||
group3=()
|
|
||||||
|
|
||||||
# create three groups by putting network tests into separate groups
|
|
||||||
# add or remove network platforms as needed to balance the groups
|
|
||||||
|
|
||||||
networks2=(
|
|
||||||
aireos
|
|
||||||
apconos
|
|
||||||
aruba
|
|
||||||
asa
|
|
||||||
avi
|
|
||||||
check_point
|
|
||||||
cloudengine
|
|
||||||
cloudvision
|
|
||||||
cnos
|
|
||||||
cumulus
|
|
||||||
dellos10
|
|
||||||
dellos6
|
|
||||||
dellos9
|
|
||||||
edgeos
|
|
||||||
edgeswitch
|
|
||||||
enos
|
|
||||||
eos
|
|
||||||
eric_eccli
|
|
||||||
exos
|
|
||||||
f5
|
|
||||||
fortimanager
|
|
||||||
frr
|
|
||||||
ftd
|
|
||||||
icx
|
|
||||||
ingate
|
|
||||||
ios
|
|
||||||
iosxr
|
|
||||||
ironware
|
|
||||||
itential
|
|
||||||
junos
|
|
||||||
netact
|
|
||||||
netscaler
|
|
||||||
netvisor
|
|
||||||
nos
|
|
||||||
nso
|
|
||||||
nuage
|
|
||||||
nxos
|
|
||||||
onyx
|
|
||||||
opx
|
|
||||||
ovs
|
|
||||||
radware
|
|
||||||
routeros
|
|
||||||
slxos
|
|
||||||
voss
|
|
||||||
vyos
|
|
||||||
)
|
|
||||||
|
|
||||||
networks3=(
|
|
||||||
fortios
|
|
||||||
)
|
|
||||||
|
|
||||||
for network in "${networks2[@]}"; do
|
|
||||||
test_path="test/units/modules/network/${network}/"
|
|
||||||
|
|
||||||
if [ -d "${test_path}" ]; then
|
|
||||||
group1+=(--exclude "${test_path}")
|
|
||||||
group2+=("${test_path}")
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
for network in "${networks3[@]}"; do
|
|
||||||
test_path="test/units/modules/network/${network}/"
|
|
||||||
|
|
||||||
if [ -d "${test_path}" ]; then
|
|
||||||
group1+=(--exclude "${test_path}")
|
|
||||||
group3+=("${test_path}")
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
case "${group}" in
|
|
||||||
1) options=("${group1[@]:+${group1[@]}}") ;;
|
|
||||||
2) options=("${group2[@]:+${group2[@]}}") ;;
|
|
||||||
3) options=("${group3[@]:+${group3[@]}}") ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ ${#options[@]} -eq 0 ] && [ "${group}" -gt 1 ]; then
|
|
||||||
# allow collection migration unit tests for groups other than 1 to "pass" without updating shippable.yml or this script during migration
|
|
||||||
echo "No unit tests found for group ${group}."
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
ansible-test env --timeout "${timeout}" --color -v
|
|
||||||
|
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
ansible-test units --color -v --docker default --python "${version}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} \
|
ansible-test units --color -v --docker default ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"}
|
||||||
"${options[@]:+${options[@]}}" \
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue