mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-04-29 18:06:53 +00:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c01a16c1bc | ||
|
|
15c832b8d5 | ||
|
|
b104c580e1 | ||
|
|
a4e1beefe3 | ||
|
|
b0898e5c51 | ||
|
|
eca1d0191f | ||
|
|
08036e7f65 | ||
|
|
3c6c9ba425 | ||
|
|
3eeb0009cb | ||
|
|
c92215d339 | ||
|
|
1a4ae5e9aa | ||
|
|
9ecfa370ff | ||
|
|
f3828ebdd7 | ||
|
|
7b71ffa1c4 | ||
|
|
d7494bb9e4 | ||
|
|
443a1c3ed7 | ||
|
|
177e327c24 | ||
|
|
6ff4b479ab | ||
|
|
feb8d421dc | ||
|
|
d633f6c4c8 | ||
|
|
3405b24fa6 | ||
|
|
540c92fa62 | ||
|
|
8cf2358fb1 | ||
|
|
2d92ab91eb | ||
|
|
d03abae7a1 | ||
|
|
d7efa7eb13 | ||
|
|
a9a9e723e5 | ||
|
|
3d87fbf6f9 | ||
|
|
9e6960639f | ||
|
|
7074a52721 | ||
|
|
d18afe6746 | ||
|
|
ee03af599c | ||
|
|
42c643ddda | ||
|
|
a7d89fc1ee | ||
|
|
d4477615a9 | ||
|
|
c84738324e | ||
|
|
0c3ae48f85 |
@@ -53,7 +53,7 @@ variables:
|
||||
resources:
|
||||
containers:
|
||||
- container: default
|
||||
image: quay.io/ansible/azure-pipelines-test-container:3.0.0
|
||||
image: quay.io/ansible/azure-pipelines-test-container:4.0.1
|
||||
|
||||
pool: Standard
|
||||
|
||||
@@ -173,8 +173,8 @@ stages:
|
||||
targets:
|
||||
- name: Alpine 3.17
|
||||
test: alpine/3.17
|
||||
# - name: Fedora 37
|
||||
# test: fedora/37
|
||||
# - name: Fedora 38
|
||||
# test: fedora/38
|
||||
- name: Ubuntu 22.04
|
||||
test: ubuntu/22.04
|
||||
groups:
|
||||
@@ -189,8 +189,10 @@ stages:
|
||||
targets:
|
||||
- name: macOS 13.2
|
||||
test: macos/13.2
|
||||
- name: RHEL 9.1
|
||||
test: rhel/9.1
|
||||
- name: RHEL 9.2
|
||||
test: rhel/9.2
|
||||
- name: RHEL 8.8
|
||||
test: rhel/8.8
|
||||
- name: FreeBSD 13.2
|
||||
test: freebsd/13.2
|
||||
- name: FreeBSD 12.4
|
||||
@@ -207,6 +209,10 @@ stages:
|
||||
parameters:
|
||||
testFormat: 2.15/{0}
|
||||
targets:
|
||||
- name: RHEL 9.1
|
||||
test: rhel/9.1
|
||||
- name: RHEL 8.7
|
||||
test: rhel/8.7
|
||||
- name: RHEL 7.9
|
||||
test: rhel/7.9
|
||||
- name: FreeBSD 13.1
|
||||
@@ -259,8 +265,8 @@ stages:
|
||||
parameters:
|
||||
testFormat: devel/linux/{0}
|
||||
targets:
|
||||
- name: Fedora 37
|
||||
test: fedora37
|
||||
- name: Fedora 38
|
||||
test: fedora38
|
||||
- name: openSUSE 15
|
||||
test: opensuse15
|
||||
- name: Ubuntu 20.04
|
||||
@@ -281,6 +287,8 @@ stages:
|
||||
parameters:
|
||||
testFormat: 2.15/linux/{0}
|
||||
targets:
|
||||
- name: Fedora 37
|
||||
test: fedora37
|
||||
- name: CentOS 7
|
||||
test: centos7
|
||||
groups:
|
||||
|
||||
3
.github/BOTMETA.yml
vendored
3
.github/BOTMETA.yml
vendored
@@ -527,6 +527,7 @@ files:
|
||||
keywords: gitlab source_control
|
||||
maintainers: $team_gitlab
|
||||
notify: jlozadad
|
||||
ignore: dj-wasabi
|
||||
$modules/gitlab_branch.py:
|
||||
maintainers: paytroff
|
||||
$modules/gitlab_project_variable.py:
|
||||
@@ -1393,7 +1394,7 @@ macros:
|
||||
team_cyberark_conjur: jvanderhoof ryanprior
|
||||
team_e_spirit: MatrixCrawler getjack
|
||||
team_flatpak: JayKayy oolongbrothers
|
||||
team_gitlab: Lunik Shaps dj-wasabi marwatk waheedi zanssa scodeman metanovii sh0shin nejch lgatellier suukit
|
||||
team_gitlab: Lunik Shaps marwatk waheedi zanssa scodeman metanovii sh0shin nejch lgatellier suukit
|
||||
team_hpux: bcoca davx8342
|
||||
team_huawei: QijunPan TommyLike edisonxiang freesky-edward hwDCN niuzhenguo xuxiaowei0512 yanzhangi zengchen1024 zhongjun2
|
||||
team_ipa: Akasurde Nosmoht fxfitz justchris1
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.0.1
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: mixed-line-ending
|
||||
args: [--fix=lf]
|
||||
- id: fix-encoding-pragma
|
||||
- id: check-ast
|
||||
- id: check-merge-conflict
|
||||
- id: check-symlinks
|
||||
- repo: https://github.com/pre-commit/pygrep-hooks
|
||||
rev: v1.9.0
|
||||
hooks:
|
||||
- id: rst-backticks
|
||||
types: [file]
|
||||
files: changelogs/fragments/.*\.(yml|yaml)$
|
||||
@@ -6,6 +6,42 @@ Community General Release Notes
|
||||
|
||||
This changelog describes changes after version 5.0.0.
|
||||
|
||||
v6.6.3
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Regular bugfix release.
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- cobbler inventory plugin - convert Ansible unicode strings to native Python unicode strings before passing user/password to XMLRPC client (https://github.com/ansible-collections/community.general/pull/6923).
|
||||
- redfish_info - fix for ``GetVolumeInventory``, Controller name was getting populated incorrectly and duplicates were seen in the volumes retrieved (https://github.com/ansible-collections/community.general/pull/6719).
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- datadog_downtime - presence of ``rrule`` param lead to the Datadog API returning Bad Request due to a missing recurrence type (https://github.com/ansible-collections/community.general/pull/6811).
|
||||
- icinga2_host - fix a key error when updating an existing host (https://github.com/ansible-collections/community.general/pull/6748).
|
||||
- ipa_dnszone - fix 'idnsallowsyncptr' key error for reverse zone (https://github.com/ansible-collections/community.general/pull/6906, https://github.com/ansible-collections/community.general/issues/6905).
|
||||
- locale_gen - now works for locales without the underscore character such as ``C.UTF-8`` (https://github.com/ansible-collections/community.general/pull/6774, https://github.com/ansible-collections/community.general/issues/5142, https://github.com/ansible-collections/community.general/issues/4305).
|
||||
- machinectl become plugin - mark plugin as ``require_tty`` to automatically disable pipelining, with which this plugin is not compatible (https://github.com/ansible-collections/community.general/issues/6932, https://github.com/ansible-collections/community.general/pull/6935).
|
||||
- nmcli - fix support for empty list (in compare and scrape) (https://github.com/ansible-collections/community.general/pull/6769).
|
||||
- openbsd_pkg - the pkg_info(1) behavior has changed in OpenBSD >7.3. The error message ``Can't find`` should not lead to an error case (https://github.com/ansible-collections/community.general/pull/6785).
|
||||
- pacman - module recognizes the output of ``yay`` running as ``root`` (https://github.com/ansible-collections/community.general/pull/6713).
|
||||
- proxmox - fix error when a configuration had no ``template`` field (https://github.com/ansible-collections/community.general/pull/6838, https://github.com/ansible-collections/community.general/issues/5372).
|
||||
- proxmox module utils - add logic to detect whether an old Promoxer complains about the ``token_name`` and ``token_value`` parameters and provide a better error message when that happens (https://github.com/ansible-collections/community.general/pull/6839, https://github.com/ansible-collections/community.general/issues/5371).
|
||||
- proxmox_disk - fix unable to create ``cdrom`` media due to ``size`` always being appended (https://github.com/ansible-collections/community.general/pull/6770).
|
||||
- proxmox_kvm - ``absent`` state with ``force`` specified failed to stop the VM due to the ``timeout`` value not being passed to ``stop_vm`` (https://github.com/ansible-collections/community.general/pull/6827).
|
||||
- redfish_info - fix ``ListUsers`` to not show empty account slots (https://github.com/ansible-collections/community.general/issues/6771, https://github.com/ansible-collections/community.general/pull/6772).
|
||||
- refish_utils module utils - changing variable names to avoid issues occuring when fetching Volumes data (https://github.com/ansible-collections/community.general/pull/6883).
|
||||
- rhsm_repository - when using the ``purge`` option, the ``repositories``
|
||||
dictionary element in the returned JSON is now properly updated according
|
||||
to the pruning operation
|
||||
(https://github.com/ansible-collections/community.general/pull/6676).
|
||||
|
||||
v6.6.2
|
||||
======
|
||||
|
||||
|
||||
@@ -121,19 +121,3 @@ Creating new modules and plugins requires a bit more work than other Pull Reques
|
||||
listed as `maintainers` will be pinged for new issues and PRs that modify the module/plugin or its tests.
|
||||
|
||||
When you add a new plugin/module, we expect that you perform maintainer duty for at least some time after contributing it.
|
||||
|
||||
## pre-commit
|
||||
|
||||
To help ensure high-quality contributions this repository includes a [pre-commit](https://pre-commit.com) configuration which
|
||||
corrects and tests against common issues that would otherwise cause CI to fail. To begin using these pre-commit hooks see
|
||||
the [Installation](#installation) section below.
|
||||
|
||||
This is optional and not required to contribute to this repository.
|
||||
|
||||
### Installation
|
||||
|
||||
Follow the [instructions](https://pre-commit.com/#install) provided with pre-commit and run `pre-commit install` under the repository base. If for any reason you would like to disable the pre-commit hooks run `pre-commit uninstall`.
|
||||
|
||||
This is optional to run it locally.
|
||||
|
||||
You can trigger it locally with `pre-commit run --all-files` or even to run only for a given file `pre-commit run --files YOUR_FILE`.
|
||||
|
||||
@@ -24,7 +24,7 @@ If you encounter abusive behavior violating the [Ansible Code of Conduct](https:
|
||||
|
||||
## Tested with Ansible
|
||||
|
||||
Tested with the current ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, ansible-core 2.14 releases and the current development version of ansible-core. Ansible-core versions before 2.11.0 are not supported. This includes all ansible-base 2.10 and Ansible 2.9 releases.
|
||||
Tested with the current ansible-core 2.11, ansible-core 2.12, ansible-core 2.13, ansible-core 2.14, ansible-core 2.15 releases and the current development version of ansible-core. Ansible-core versions before 2.11.0 are not supported. This includes all ansible-base 2.10 and Ansible 2.9 releases.
|
||||
|
||||
Parts of this collection will not work with ansible-core 2.11 on Python 3.12+.
|
||||
|
||||
|
||||
@@ -1424,3 +1424,70 @@ releases:
|
||||
- 6712-gitlab_group-filtered-for-none-values.yml
|
||||
- ini_file-use-inactive-options-when-possible.yml
|
||||
release_date: '2023-06-19'
|
||||
6.6.3:
|
||||
changes:
|
||||
bugfixes:
|
||||
- datadog_downtime - presence of ``rrule`` param lead to the Datadog API returning
|
||||
Bad Request due to a missing recurrence type (https://github.com/ansible-collections/community.general/pull/6811).
|
||||
- icinga2_host - fix a key error when updating an existing host (https://github.com/ansible-collections/community.general/pull/6748).
|
||||
- ipa_dnszone - fix 'idnsallowsyncptr' key error for reverse zone (https://github.com/ansible-collections/community.general/pull/6906,
|
||||
https://github.com/ansible-collections/community.general/issues/6905).
|
||||
- locale_gen - now works for locales without the underscore character such as
|
||||
``C.UTF-8`` (https://github.com/ansible-collections/community.general/pull/6774,
|
||||
https://github.com/ansible-collections/community.general/issues/5142, https://github.com/ansible-collections/community.general/issues/4305).
|
||||
- machinectl become plugin - mark plugin as ``require_tty`` to automatically
|
||||
disable pipelining, with which this plugin is not compatible (https://github.com/ansible-collections/community.general/issues/6932,
|
||||
https://github.com/ansible-collections/community.general/pull/6935).
|
||||
- nmcli - fix support for empty list (in compare and scrape) (https://github.com/ansible-collections/community.general/pull/6769).
|
||||
- openbsd_pkg - the pkg_info(1) behavior has changed in OpenBSD >7.3. The error
|
||||
message ``Can't find`` should not lead to an error case (https://github.com/ansible-collections/community.general/pull/6785).
|
||||
- pacman - module recognizes the output of ``yay`` running as ``root`` (https://github.com/ansible-collections/community.general/pull/6713).
|
||||
- proxmox - fix error when a configuration had no ``template`` field (https://github.com/ansible-collections/community.general/pull/6838,
|
||||
https://github.com/ansible-collections/community.general/issues/5372).
|
||||
- proxmox module utils - add logic to detect whether an old Promoxer complains
|
||||
about the ``token_name`` and ``token_value`` parameters and provide a better
|
||||
error message when that happens (https://github.com/ansible-collections/community.general/pull/6839,
|
||||
https://github.com/ansible-collections/community.general/issues/5371).
|
||||
- proxmox_disk - fix unable to create ``cdrom`` media due to ``size`` always
|
||||
being appended (https://github.com/ansible-collections/community.general/pull/6770).
|
||||
- proxmox_kvm - ``absent`` state with ``force`` specified failed to stop the
|
||||
VM due to the ``timeout`` value not being passed to ``stop_vm`` (https://github.com/ansible-collections/community.general/pull/6827).
|
||||
- redfish_info - fix ``ListUsers`` to not show empty account slots (https://github.com/ansible-collections/community.general/issues/6771,
|
||||
https://github.com/ansible-collections/community.general/pull/6772).
|
||||
- refish_utils module utils - changing variable names to avoid issues occuring
|
||||
when fetching Volumes data (https://github.com/ansible-collections/community.general/pull/6883).
|
||||
- 'rhsm_repository - when using the ``purge`` option, the ``repositories``
|
||||
|
||||
dictionary element in the returned JSON is now properly updated according
|
||||
|
||||
to the pruning operation
|
||||
|
||||
(https://github.com/ansible-collections/community.general/pull/6676).
|
||||
|
||||
'
|
||||
minor_changes:
|
||||
- cobbler inventory plugin - convert Ansible unicode strings to native Python
|
||||
unicode strings before passing user/password to XMLRPC client (https://github.com/ansible-collections/community.general/pull/6923).
|
||||
- redfish_info - fix for ``GetVolumeInventory``, Controller name was getting
|
||||
populated incorrectly and duplicates were seen in the volumes retrieved (https://github.com/ansible-collections/community.general/pull/6719).
|
||||
release_summary: Regular bugfix release.
|
||||
fragments:
|
||||
- 6.6.3.yml
|
||||
- 6676-rhsm_repository-fix-returned-repositories-with-purge.yml
|
||||
- 6713-yay-become.yml
|
||||
- 6719-redfish-utils-fix-for-get-volume-inventory.yml
|
||||
- 6748-icinga2_host-datafix.yml
|
||||
- 6769-nmcli-fix-empty-list.yml
|
||||
- 6770-proxmox_disk_create_cdrom.yml
|
||||
- 6771-redfish-filter-empty-account-slots.yml
|
||||
- 6774-locale-gen-fix.yml
|
||||
- 6785-openbsd_pkg_pkg_info_handling.yml
|
||||
- 6811-datadog-downtime-rrule-type.yaml
|
||||
- 6827-proxmox_kvm-force-delete-bug-fix.yaml
|
||||
- 6838-proxmox-dict-template.yml
|
||||
- 6839-promoxer-tokens.yml
|
||||
- 6883-redfish-utils-changing-variable-names-in-get-volume-inventory.yml
|
||||
- 6905-ipa_dnszone-key-error-fix.yml
|
||||
- 6923-cobbler-inventory_unicode.yml
|
||||
- 6935-machinectl-become.yml
|
||||
release_date: '2023-07-16'
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
namespace: community
|
||||
name: general
|
||||
version: 6.6.2
|
||||
version: 6.6.3
|
||||
readme: README.md
|
||||
authors:
|
||||
- Ansible (https://github.com/ansible)
|
||||
|
||||
@@ -102,6 +102,7 @@ class BecomeModule(BecomeBase):
|
||||
prompt = 'Password: '
|
||||
fail = ('==== AUTHENTICATION FAILED ====',)
|
||||
success = ('==== AUTHENTICATION COMPLETE ====',)
|
||||
require_tty = True # see https://github.com/ansible-collections/community.general/issues/6932
|
||||
|
||||
@staticmethod
|
||||
def remove_ansi_codes(line):
|
||||
|
||||
@@ -48,6 +48,25 @@ DOCUMENTATION = '''
|
||||
default: chroot
|
||||
'''
|
||||
|
||||
EXAMPLES = r"""
|
||||
# Static inventory file
|
||||
#
|
||||
# [chroots]
|
||||
# /path/to/debootstrap
|
||||
# /path/to/feboostrap
|
||||
# /path/to/lxc-image
|
||||
# /path/to/chroot
|
||||
|
||||
# playbook
|
||||
---
|
||||
- hosts: chroots
|
||||
connection: community.general.chroot
|
||||
tasks:
|
||||
- debug:
|
||||
msg: "This is coming from chroot environment"
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import subprocess
|
||||
|
||||
@@ -29,11 +29,13 @@ options:
|
||||
api_token_id:
|
||||
description:
|
||||
- Specify the token ID.
|
||||
- Requires C(proxmoxer>=1.1.0) to work.
|
||||
type: str
|
||||
version_added: 1.3.0
|
||||
api_token_secret:
|
||||
description:
|
||||
- Specify the token secret.
|
||||
- Requires C(proxmoxer>=1.1.0) to work.
|
||||
type: str
|
||||
version_added: 1.3.0
|
||||
validate_certs:
|
||||
|
||||
@@ -87,6 +87,7 @@ from ansible.errors import AnsibleError
|
||||
from ansible.module_utils.common.text.converters import to_text
|
||||
from ansible.module_utils.six import iteritems
|
||||
from ansible.plugins.inventory import BaseInventoryPlugin, Cacheable, to_safe_group_name
|
||||
from ansible.module_utils.six import text_type
|
||||
|
||||
# xmlrpc
|
||||
try:
|
||||
@@ -128,7 +129,7 @@ class InventoryModule(BaseInventoryPlugin, Cacheable):
|
||||
self.connection = xmlrpc_client.Server(self.cobbler_url, allow_none=True)
|
||||
self.token = None
|
||||
if self.get_option('user') is not None:
|
||||
self.token = self.connection.login(self.get_option('user'), self.get_option('password'))
|
||||
self.token = self.connection.login(text_type(self.get_option('user')), text_type(self.get_option('password')))
|
||||
return self.connection
|
||||
|
||||
def _init_cache(self):
|
||||
|
||||
@@ -74,18 +74,18 @@ EXAMPLES = """
|
||||
|
||||
- name: Retrieve password for HAL when not signed in to 1Password
|
||||
ansible.builtin.debug:
|
||||
var: lookup('community.general.onepassword'
|
||||
'HAL 9000'
|
||||
subdomain='Discovery'
|
||||
var: lookup('community.general.onepassword',
|
||||
'HAL 9000',
|
||||
subdomain='Discovery',
|
||||
master_password=vault_master_password)
|
||||
|
||||
- name: Retrieve password for HAL when never signed in to 1Password
|
||||
ansible.builtin.debug:
|
||||
var: lookup('community.general.onepassword'
|
||||
'HAL 9000'
|
||||
subdomain='Discovery'
|
||||
master_password=vault_master_password
|
||||
username='tweety@acme.com'
|
||||
var: lookup('community.general.onepassword',
|
||||
'HAL 9000',
|
||||
subdomain='Discovery',
|
||||
master_password=vault_master_password,
|
||||
username='tweety@acme.com',
|
||||
secret_key=vault_secret_key)
|
||||
"""
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ DOCUMENTATION = r"""
|
||||
version_added: '3.2.0'
|
||||
description:
|
||||
- Generates random string based upon the given constraints.
|
||||
- Uses L(random.SystemRandom,https://docs.python.org/3/library/random.html#random.SystemRandom),
|
||||
so should be strong enough for cryptographic purposes.
|
||||
options:
|
||||
length:
|
||||
description: The length of the string.
|
||||
|
||||
@@ -98,6 +98,8 @@ class ProxmoxAnsible(object):
|
||||
if api_password:
|
||||
auth_args['password'] = api_password
|
||||
else:
|
||||
if self.version() < LooseVersion('1.1.0'):
|
||||
self.module.fail_json('Using "token_name" and "token_value" require proxmoxer>=1.1.0')
|
||||
auth_args['token_name'] = api_token_id
|
||||
auth_args['token_value'] = api_token_secret
|
||||
|
||||
|
||||
@@ -832,13 +832,13 @@ class RedfishUtils(object):
|
||||
if data.get('Members'):
|
||||
for controller in data[u'Members']:
|
||||
controller_list.append(controller[u'@odata.id'])
|
||||
for c in controller_list:
|
||||
for idx, c in enumerate(controller_list):
|
||||
uri = self.root_uri + c
|
||||
response = self.get_request(uri)
|
||||
if response['ret'] is False:
|
||||
return response
|
||||
data = response['data']
|
||||
controller_name = 'Controller 1'
|
||||
controller_name = 'Controller %s' % str(idx)
|
||||
if 'StorageControllers' in data:
|
||||
sc = data['StorageControllers']
|
||||
if sc:
|
||||
@@ -847,7 +847,26 @@ class RedfishUtils(object):
|
||||
else:
|
||||
sc_id = sc[0].get('Id', '1')
|
||||
controller_name = 'Controller %s' % sc_id
|
||||
elif 'Controllers' in data:
|
||||
response = self.get_request(self.root_uri + data['Controllers'][u'@odata.id'])
|
||||
if response['ret'] is False:
|
||||
return response
|
||||
c_data = response['data']
|
||||
|
||||
if c_data.get('Members') and c_data['Members']:
|
||||
response = self.get_request(self.root_uri + c_data['Members'][0][u'@odata.id'])
|
||||
if response['ret'] is False:
|
||||
return response
|
||||
member_data = response['data']
|
||||
|
||||
if member_data:
|
||||
if 'Name' in member_data:
|
||||
controller_name = member_data['Name']
|
||||
else:
|
||||
controller_id = member_data.get('Id', '1')
|
||||
controller_name = 'Controller %s' % controller_id
|
||||
volume_results = []
|
||||
volume_list = []
|
||||
if 'Volumes' in data:
|
||||
# Get a list of all volumes and build respective URIs
|
||||
volumes_uri = data[u'Volumes'][u'@odata.id']
|
||||
@@ -1079,6 +1098,12 @@ class RedfishUtils(object):
|
||||
if property in data:
|
||||
user[property] = data[property]
|
||||
|
||||
# Filter out empty account slots
|
||||
# An empty account slot can be detected if the username is an empty
|
||||
# string and if the account is disabled
|
||||
if user.get('UserName', '') == '' and not user.get('Enabled', False):
|
||||
continue
|
||||
|
||||
users_results.append(user)
|
||||
result["entries"] = users_results
|
||||
return result
|
||||
|
||||
@@ -248,7 +248,8 @@ def build_downtime(module):
|
||||
downtime.timezone = module.params["timezone"]
|
||||
if module.params["rrule"]:
|
||||
downtime.recurrence = DowntimeRecurrence(
|
||||
rrule=module.params["rrule"]
|
||||
rrule=module.params["rrule"],
|
||||
type="rrule",
|
||||
)
|
||||
return downtime
|
||||
|
||||
|
||||
@@ -82,8 +82,14 @@ EXAMPLES = '''
|
||||
name: Access Key for Some Machine
|
||||
token: '{{ github_access_token }}'
|
||||
pubkey: '{{ ssh_pub_key.stdout }}'
|
||||
'''
|
||||
|
||||
# Alternatively, a single task can be used reading a key from a file on the controller
|
||||
- name: Authorize key with GitHub
|
||||
community.general.github_key:
|
||||
name: Access Key for Some Machine
|
||||
token: '{{ github_access_token }}'
|
||||
pubkey: "{{ lookup('ansible.builtin.file', '/home/foo/.ssh/id_rsa.pub') }}"
|
||||
'''
|
||||
|
||||
import json
|
||||
import re
|
||||
|
||||
@@ -306,7 +306,7 @@ def main():
|
||||
module.exit_json(changed=False, name=name, data=data)
|
||||
|
||||
# Template attribute is not allowed in modification
|
||||
del data['attrs']['templates']
|
||||
del data['templates']
|
||||
|
||||
ret = icinga.modify(name, data)
|
||||
|
||||
|
||||
@@ -152,7 +152,8 @@ def ensure(module, client):
|
||||
changed = True
|
||||
if not module.check_mode:
|
||||
client.dnszone_add(zone_name=zone_name, details={'idnsallowdynupdate': dynamicupdate, 'idnsallowsyncptr': allowsyncptr})
|
||||
elif ipa_dnszone['idnsallowdynupdate'][0] != str(dynamicupdate).upper() or ipa_dnszone['idnsallowsyncptr'][0] != str(allowsyncptr).upper():
|
||||
elif ipa_dnszone['idnsallowdynupdate'][0] != str(dynamicupdate).upper() or \
|
||||
ipa_dnszone.get('idnsallowsyncptr') and ipa_dnszone['idnsallowsyncptr'][0] != str(allowsyncptr).upper():
|
||||
changed = True
|
||||
if not module.check_mode:
|
||||
client.dnszone_mod(zone_name=zone_name, details={'idnsallowdynupdate': dynamicupdate, 'idnsallowsyncptr': allowsyncptr})
|
||||
|
||||
@@ -35,6 +35,8 @@ options:
|
||||
- Whether the locale shall be present.
|
||||
choices: [ absent, present ]
|
||||
default: present
|
||||
notes:
|
||||
- This module does not support RHEL-based systems.
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
@@ -74,11 +76,10 @@ def is_available(name, ubuntuMode):
|
||||
checking either :
|
||||
* if the locale is present in /etc/locales.gen
|
||||
* or if the locale is present in /usr/share/i18n/SUPPORTED"""
|
||||
__regexp = r'^#?\s*(?P<locale>\S+[\._\S]*) (?P<charset>\S+)\s*$'
|
||||
if ubuntuMode:
|
||||
__regexp = r'^(?P<locale>\S+_\S+) (?P<charset>\S+)\s*$'
|
||||
__locales_available = '/usr/share/i18n/SUPPORTED'
|
||||
else:
|
||||
__regexp = r'^#{0,1}\s*(?P<locale>\S+_\S+) (?P<charset>\S+)\s*$'
|
||||
__locales_available = '/etc/locale.gen'
|
||||
|
||||
re_compiled = re.compile(__regexp)
|
||||
@@ -88,7 +89,8 @@ def is_available(name, ubuntuMode):
|
||||
if result and result.group('locale') == name:
|
||||
return True
|
||||
fd.close()
|
||||
return False
|
||||
# locale may be installed but not listed in the file, for example C.UTF-8 in some systems
|
||||
return is_present(name)
|
||||
|
||||
|
||||
def is_present(name):
|
||||
@@ -106,20 +108,6 @@ def fix_case(name):
|
||||
return name
|
||||
|
||||
|
||||
def replace_line(existing_line, new_line):
|
||||
"""Replaces lines in /etc/locale.gen"""
|
||||
try:
|
||||
f = open("/etc/locale.gen", "r")
|
||||
lines = [line.replace(existing_line, new_line) for line in f]
|
||||
finally:
|
||||
f.close()
|
||||
try:
|
||||
f = open("/etc/locale.gen", "w")
|
||||
f.write("".join(lines))
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
|
||||
def set_locale(name, enabled=True):
|
||||
""" Sets the state of the locale. Defaults to enabled. """
|
||||
search_string = r'#{0,1}\s*%s (?P<charset>.+)' % name
|
||||
@@ -209,7 +197,7 @@ def main():
|
||||
# We found the common way to manage locales.
|
||||
ubuntuMode = False
|
||||
else:
|
||||
module.fail_json(msg="/etc/locale.gen and /var/lib/locales/supported.d/local are missing. Is the package \"locales\" installed?")
|
||||
module.fail_json(msg="/etc/locale.gen and /var/lib/locales/supported.d/local are missing. Is the package 'locales' installed?")
|
||||
else:
|
||||
# Ubuntu created its own system to manage locales.
|
||||
ubuntuMode = True
|
||||
|
||||
@@ -2104,7 +2104,10 @@ class Nmcli(object):
|
||||
if key and len(pair) > 1:
|
||||
raw_value = pair[1].lstrip()
|
||||
if raw_value == '--':
|
||||
conn_info[key] = None
|
||||
if key_type == list:
|
||||
conn_info[key] = []
|
||||
else:
|
||||
conn_info[key] = None
|
||||
elif key == 'bond.options':
|
||||
# Aliases such as 'miimon', 'downdelay' are equivalent to the +bond.options 'option=value' syntax.
|
||||
opts = raw_value.split(',')
|
||||
@@ -2191,7 +2194,7 @@ class Nmcli(object):
|
||||
# We can't just do `if not value` because then if there's a value
|
||||
# of 0 specified as an integer it'll be interpreted as empty when
|
||||
# it actually isn't.
|
||||
if value != 0 and not value:
|
||||
if value not in (0, []) and not value:
|
||||
continue
|
||||
|
||||
if key in conn_info:
|
||||
|
||||
@@ -169,7 +169,11 @@ def get_package_state(names, pkg_spec, module):
|
||||
rc, stdout, stderr = execute_command(command, module)
|
||||
|
||||
if stderr:
|
||||
module.fail_json(msg="failed in get_package_state(): " + stderr)
|
||||
match = re.search(r"^Can't find inst:%s$" % re.escape(name), stderr)
|
||||
if match:
|
||||
pkg_spec[name]['installed_state'] = False
|
||||
else:
|
||||
module.fail_json(msg="failed in get_package_state(): " + stderr)
|
||||
|
||||
if stdout:
|
||||
# If the requested package name is just a stem, like "python", we may
|
||||
|
||||
@@ -133,6 +133,9 @@ notes:
|
||||
it is much more efficient to pass the list directly to the I(name) option.
|
||||
- To use an AUR helper (I(executable) option), a few extra setup steps might be required beforehand.
|
||||
For example, a dedicated build user with permissions to install packages could be necessary.
|
||||
- >
|
||||
In the tests, while using C(yay) as the I(executable) option, the module failed to install AUR packages
|
||||
with the error: C(error: target not found: <pkg>).
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
@@ -263,6 +266,7 @@ EXAMPLES = """
|
||||
reason_for: all
|
||||
"""
|
||||
|
||||
import re
|
||||
import shlex
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from collections import defaultdict, namedtuple
|
||||
@@ -418,7 +422,7 @@ class Pacman(object):
|
||||
for p in name_ver:
|
||||
# With Pacman v6.0.1 - libalpm v13.0.1, --upgrade outputs "loading packages..." on stdout. strip that.
|
||||
# When installing from URLs, pacman can also output a 'nothing to do' message. strip that too.
|
||||
if "loading packages" in p or "there is nothing to do" in p:
|
||||
if "loading packages" in p or "there is nothing to do" in p or 'Avoid running' in p:
|
||||
continue
|
||||
name, version = p.split()
|
||||
if name in self.inventory["installed_pkgs"]:
|
||||
@@ -706,11 +710,12 @@ class Pacman(object):
|
||||
installed_pkgs = {}
|
||||
dummy, stdout, dummy = self.m.run_command([self.pacman_path, "--query"], check_rc=True)
|
||||
# Format of a line: "pacman 6.0.1-2"
|
||||
query_re = re.compile(r'^\s*(?P<pkg>\S+)\s+(?P<ver>\S+)\s*$')
|
||||
for l in stdout.splitlines():
|
||||
l = l.strip()
|
||||
if not l:
|
||||
query_match = query_re.match(l)
|
||||
if not query_match:
|
||||
continue
|
||||
pkg, ver = l.split()
|
||||
pkg, ver = query_match.groups()
|
||||
installed_pkgs[pkg] = ver
|
||||
|
||||
installed_groups = defaultdict(set)
|
||||
@@ -721,11 +726,12 @@ class Pacman(object):
|
||||
# base-devel file
|
||||
# base-devel findutils
|
||||
# ...
|
||||
query_groups_re = re.compile(r'^\s*(?P<group>\S+)\s+(?P<pkg>\S+)\s*$')
|
||||
for l in stdout.splitlines():
|
||||
l = l.strip()
|
||||
if not l:
|
||||
query_groups_match = query_groups_re.match(l)
|
||||
if not query_groups_match:
|
||||
continue
|
||||
group, pkgname = l.split()
|
||||
group, pkgname = query_groups_match.groups()
|
||||
installed_groups[group].add(pkgname)
|
||||
|
||||
available_pkgs = {}
|
||||
@@ -747,11 +753,12 @@ class Pacman(object):
|
||||
# vim-plugins vim-airline-themes
|
||||
# vim-plugins vim-ale
|
||||
# ...
|
||||
sync_groups_re = re.compile(r'^\s*(?P<group>\S+)\s+(?P<pkg>\S+)\s*$')
|
||||
for l in stdout.splitlines():
|
||||
l = l.strip()
|
||||
if not l:
|
||||
sync_groups_match = sync_groups_re.match(l)
|
||||
if not sync_groups_match:
|
||||
continue
|
||||
group, pkg = l.split()
|
||||
group, pkg = sync_groups_match.groups()
|
||||
available_groups[group].add(pkg)
|
||||
|
||||
upgradable_pkgs = {}
|
||||
@@ -759,9 +766,14 @@ class Pacman(object):
|
||||
[self.pacman_path, "--query", "--upgrades"], check_rc=False
|
||||
)
|
||||
|
||||
stdout = stdout.splitlines()
|
||||
if stdout and "Avoid running" in stdout[0]:
|
||||
stdout = stdout[1:]
|
||||
stdout = "\n".join(stdout)
|
||||
|
||||
# non-zero exit with nothing in stdout -> nothing to upgrade, all good
|
||||
# stderr can have warnings, so not checked here
|
||||
if rc == 1 and stdout == "":
|
||||
if rc == 1 and not stdout:
|
||||
pass # nothing to upgrade
|
||||
elif rc == 0:
|
||||
# Format of lines:
|
||||
@@ -771,7 +783,7 @@ class Pacman(object):
|
||||
l = l.strip()
|
||||
if not l:
|
||||
continue
|
||||
if "[ignored]" in l:
|
||||
if "[ignored]" in l or "Avoid running" in l:
|
||||
continue
|
||||
s = l.split()
|
||||
if len(s) != 4:
|
||||
|
||||
@@ -427,7 +427,7 @@ class ProxmoxLxcAnsible(ProxmoxAnsible):
|
||||
"""Check if the specified container is a template."""
|
||||
proxmox_node = self.proxmox_api.nodes(node)
|
||||
config = getattr(proxmox_node, VZ_TYPE)(vmid).config.get()
|
||||
return config['template']
|
||||
return config.get('template', False)
|
||||
|
||||
def create_instance(self, vmid, node, disk, storage, cpus, memory, swap, timeout, clone, **kwargs):
|
||||
|
||||
|
||||
@@ -505,7 +505,9 @@ class ProxmoxDiskAnsible(ProxmoxAnsible):
|
||||
timeout_str = "Reached timeout while importing VM disk. Last line in task before timeout: %s"
|
||||
ok_str = "Disk %s imported into VM %s"
|
||||
else:
|
||||
config_str = "%s:%s" % (self.module.params["storage"], self.module.params["size"])
|
||||
config_str = self.module.params["storage"]
|
||||
if self.module.params.get("media") != "cdrom":
|
||||
config_str += ":%s" % (self.module.params["size"])
|
||||
ok_str = "Disk %s created in VM %s"
|
||||
timeout_str = "Reached timeout while creating VM disk. Last line in task before timeout: %s"
|
||||
|
||||
|
||||
@@ -763,6 +763,15 @@ EXAMPLES = '''
|
||||
node: sabrewulf
|
||||
state: absent
|
||||
|
||||
- name: Get VM current state
|
||||
community.general.proxmox_kvm:
|
||||
api_user: root@pam
|
||||
api_password: secret
|
||||
api_host: helldorado
|
||||
name: spynal
|
||||
node: sabrewulf
|
||||
state: current
|
||||
|
||||
- name: Update VM configuration
|
||||
community.general.proxmox_kvm:
|
||||
api_user: root@pam
|
||||
@@ -1404,7 +1413,7 @@ def main():
|
||||
status['status'] = vm['status']
|
||||
if vm['status'] == 'running':
|
||||
if module.params['force']:
|
||||
proxmox.stop_vm(vm, True)
|
||||
proxmox.stop_vm(vm, True, timeout=module.params['timeout'])
|
||||
else:
|
||||
module.exit_json(changed=False, vmid=vmid, msg="VM %s is running. Stop it before deletion or use force=true." % vmid)
|
||||
taskid = proxmox_node.qemu.delete(vmid)
|
||||
|
||||
@@ -222,6 +222,9 @@ def repository_modify(module, state, name, purge=False):
|
||||
diff_after.join("Repository '{repoid}' is disabled for this system\n".format(repoid=repoid))
|
||||
results.append("Repository '{repoid}' is disabled for this system".format(repoid=repoid))
|
||||
rhsm_arguments.extend(['--disable', repoid])
|
||||
for updated_repo in updated_repo_list:
|
||||
if updated_repo['id'] in difference:
|
||||
updated_repo['enabled'] = False
|
||||
|
||||
diff = {'before': diff_before,
|
||||
'after': diff_after,
|
||||
|
||||
@@ -11,5 +11,9 @@ skip/rhel8.2
|
||||
skip/rhel8.3
|
||||
skip/rhel8.4
|
||||
skip/rhel8.5
|
||||
skip/rhel8.6
|
||||
skip/rhel8.7
|
||||
skip/rhel8.8
|
||||
skip/rhel9.0
|
||||
skip/rhel9.1
|
||||
skip/rhel9.2
|
||||
|
||||
@@ -9,3 +9,4 @@ skip/osx
|
||||
skip/macos
|
||||
skip/rhel9.0 # See https://www.reddit.com/r/Fedora/comments/si7nzk/homectl/
|
||||
skip/rhel9.1 # See https://www.reddit.com/r/Fedora/comments/si7nzk/homectl/
|
||||
skip/rhel9.2 # See https://www.reddit.com/r/Fedora/comments/si7nzk/homectl/
|
||||
|
||||
7
tests/integration/targets/htpasswd/aliases
Normal file
7
tests/integration/targets/htpasswd/aliases
Normal file
@@ -0,0 +1,7 @@
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/posix/2
|
||||
destructive
|
||||
needs/root
|
||||
9
tests/integration/targets/htpasswd/handlers/main.yml
Normal file
9
tests/integration/targets/htpasswd/handlers/main.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: remove passlib
|
||||
ansible.builtin.pip:
|
||||
name: passlib
|
||||
state: absent
|
||||
7
tests/integration/targets/htpasswd/meta/main.yml
Normal file
7
tests/integration/targets/htpasswd/meta/main.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
dependencies:
|
||||
- setup_remote_tmp_dir
|
||||
83
tests/integration/targets/htpasswd/tasks/main.yml
Normal file
83
tests/integration/targets/htpasswd/tasks/main.yml
Normal file
@@ -0,0 +1,83 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: install passlib
|
||||
ansible.builtin.pip:
|
||||
name: passlib
|
||||
notify: remove passlib
|
||||
|
||||
- name: add bob (check mode)
|
||||
community.general.htpasswd:
|
||||
path: "{{ htpasswd_path }}"
|
||||
name: bob
|
||||
password: c00lbob
|
||||
check_mode: true
|
||||
register: add_bob_check
|
||||
|
||||
- name: add bob
|
||||
community.general.htpasswd:
|
||||
path: "{{ htpasswd_path }}"
|
||||
name: bob
|
||||
password: c00lbob
|
||||
register: add_bob
|
||||
|
||||
- name: add bob (idempotency)
|
||||
community.general.htpasswd:
|
||||
path: "{{ htpasswd_path }}"
|
||||
name: bob
|
||||
password: c00lbob
|
||||
register: add_bob_idempot
|
||||
|
||||
- name: add bob new password
|
||||
community.general.htpasswd:
|
||||
path: "{{ htpasswd_path }}"
|
||||
name: bob
|
||||
password: SUPERsecret
|
||||
register: add_bob_newpw
|
||||
|
||||
- name: add bob new password (idempotency)
|
||||
community.general.htpasswd:
|
||||
path: "{{ htpasswd_path }}"
|
||||
name: bob
|
||||
password: SUPERsecret
|
||||
register: add_bob_newpw_idempot
|
||||
|
||||
- name: test add bob assertions
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- add_bob_check is changed
|
||||
- add_bob is changed
|
||||
- add_bob_idempot is not changed
|
||||
- add_bob_newpw is changed
|
||||
- add_bob_newpw_idempot is not changed
|
||||
|
||||
- name: remove bob (check mode)
|
||||
community.general.htpasswd:
|
||||
path: "{{ htpasswd_path }}"
|
||||
name: bob
|
||||
state: absent
|
||||
check_mode: true
|
||||
register: del_bob_check
|
||||
|
||||
- name: remove bob
|
||||
community.general.htpasswd:
|
||||
path: "{{ htpasswd_path }}"
|
||||
name: bob
|
||||
state: absent
|
||||
register: del_bob
|
||||
|
||||
- name: remove bob (idempotency)
|
||||
community.general.htpasswd:
|
||||
path: "{{ htpasswd_path }}"
|
||||
name: bob
|
||||
state: absent
|
||||
register: del_bob_idempot
|
||||
|
||||
- name: test remove bob assertions
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- del_bob_check is changed
|
||||
- del_bob is changed
|
||||
- del_bob_idempot is not changed
|
||||
6
tests/integration/targets/htpasswd/vars/main.yml
Normal file
6
tests/integration/targets/htpasswd/vars/main.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
htpasswd_path: "{{ remote_tmp_dir }}/dot_htpasswd"
|
||||
@@ -3,3 +3,4 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
azp/posix/2
|
||||
skip/python2.6
|
||||
|
||||
@@ -9,5 +9,6 @@ skip/aix
|
||||
skip/osx # FIXME
|
||||
skip/rhel9.0 # FIXME
|
||||
skip/rhel9.1 # FIXME
|
||||
skip/rhel9.2 # FIXME
|
||||
skip/freebsd12.4 # FIXME
|
||||
skip/freebsd13.2 # FIXME
|
||||
|
||||
@@ -6,3 +6,5 @@ azp/posix/3
|
||||
destructive
|
||||
needs/root
|
||||
skip/aix
|
||||
skip/freebsd
|
||||
skip/macos
|
||||
|
||||
102
tests/integration/targets/locale_gen/tasks/basic.yml
Normal file
102
tests/integration/targets/locale_gen/tasks/basic.yml
Normal file
@@ -0,0 +1,102 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: Is the locale we're going to test against installed? {{ locale_basic.localegen }}
|
||||
command: locale -a
|
||||
register: initial_state
|
||||
ignore_errors: true
|
||||
|
||||
- name: Make sure the locale is not installed {{ locale_basic.localegen }}
|
||||
locale_gen:
|
||||
name: "{{ locale_basic.localegen }}"
|
||||
state: absent
|
||||
|
||||
- name: Is the locale present? {{ locale_basic.localegen }}
|
||||
command: locale -a
|
||||
register: cleaned
|
||||
ignore_errors: true
|
||||
|
||||
- name: Make sure the locale is not present {{ locale_basic.localegen }}
|
||||
assert:
|
||||
that:
|
||||
- locale_basic.skip_removal or locale_basic.locales | intersect(cleaned.stdout_lines) == []
|
||||
|
||||
- name: Install the locale {{ locale_basic.localegen }}
|
||||
locale_gen:
|
||||
name: "{{ locale_basic.localegen }}"
|
||||
state: present
|
||||
register: output_present
|
||||
|
||||
- name: Is the locale present? {{ locale_basic.localegen }}
|
||||
command: locale -a
|
||||
register: post_check_output_present
|
||||
ignore_errors: true
|
||||
|
||||
- name: Make sure the locale is present and we say we installed it {{ locale_basic.localegen }}
|
||||
assert:
|
||||
that:
|
||||
- locale_basic.locales | intersect(post_check_output_present.stdout_lines) != []
|
||||
- locale_basic.skip_removal or output_present is changed
|
||||
|
||||
- name: Install the locale a second time {{ locale_basic.localegen }}
|
||||
locale_gen:
|
||||
name: "{{ locale_basic.localegen }}"
|
||||
state: present
|
||||
register: output_present_idempotent
|
||||
|
||||
- name: Is the locale present? {{ locale_basic.localegen }}
|
||||
command: locale -a
|
||||
register: post_check_output_present_idempotent
|
||||
ignore_errors: true
|
||||
|
||||
- name: Make sure the locale is present and we reported no change {{ locale_basic.localegen }}
|
||||
assert:
|
||||
that:
|
||||
- locale_basic.locales | intersect(post_check_output_present_idempotent.stdout_lines) != []
|
||||
- output_present_idempotent is not changed
|
||||
|
||||
- name: Removals
|
||||
when: locale_basic.skip_removal is false
|
||||
block:
|
||||
- name: Remove the locale {{ locale_basic.localegen }}
|
||||
locale_gen:
|
||||
name: "{{ locale_basic.localegen }}"
|
||||
state: absent
|
||||
register: output_absent
|
||||
|
||||
- name: Is the locale present? {{ locale_basic.localegen }}
|
||||
command: locale -a
|
||||
register: post_check_output_absent
|
||||
ignore_errors: true
|
||||
|
||||
- name: Make sure the locale is absent and we reported a change {{ locale_basic.localegen }}
|
||||
assert:
|
||||
that:
|
||||
- locale_basic.locales | intersect(post_check_output_absent.stdout_lines) == []
|
||||
- output_absent is changed
|
||||
|
||||
- name: Remove the locale a second time {{ locale_basic.localegen }}
|
||||
locale_gen:
|
||||
name: "{{ locale_basic.localegen }}"
|
||||
state: absent
|
||||
register: output_absent_idempotent
|
||||
|
||||
- name: Is the locale present? {{ locale_basic.localegen }}
|
||||
command: locale -a
|
||||
register: post_check_output_absent_idempotent
|
||||
ignore_errors: true
|
||||
|
||||
- name: Make sure the locale is absent and we reported no change {{ locale_basic.localegen }}
|
||||
assert:
|
||||
that:
|
||||
- locale_basic.locales | intersect(post_check_output_absent_idempotent.stdout_lines) == []
|
||||
- output_absent_idempotent is not changed
|
||||
|
||||
# Cleanup
|
||||
- name: Reinstall the locale we tested against if it was initially installed {{ locale_basic.localegen }}
|
||||
locale_gen:
|
||||
name: "{{ locale_basic.localegen }}"
|
||||
state: present
|
||||
when: locale_basic.locales | intersect(initial_state.stdout_lines) != []
|
||||
@@ -1,99 +0,0 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: Is the locale we're going to test against installed?
|
||||
shell: locale -a | grep pt_BR
|
||||
register: initial_state
|
||||
ignore_errors: true
|
||||
|
||||
- name: Make sure the locale is not installed
|
||||
locale_gen:
|
||||
name: pt_BR
|
||||
state: absent
|
||||
|
||||
- name: Is the locale present?
|
||||
shell: locale -a | grep pt_BR
|
||||
register: cleaned
|
||||
ignore_errors: true
|
||||
|
||||
- name: Make sure the locale is not present
|
||||
assert:
|
||||
that:
|
||||
- "cleaned.rc == 1"
|
||||
|
||||
- name: Install the locale
|
||||
locale_gen:
|
||||
name: pt_BR
|
||||
state: present
|
||||
register: output
|
||||
|
||||
- name: Is the locale present?
|
||||
shell: locale -a | grep pt_BR
|
||||
register: post_check_output
|
||||
ignore_errors: true
|
||||
|
||||
- name: Make sure the locale is present and we say we installed it
|
||||
assert:
|
||||
that:
|
||||
- "post_check_output.rc == 0"
|
||||
- "output.changed"
|
||||
|
||||
- name: Install the locale a second time
|
||||
locale_gen:
|
||||
name: pt_BR
|
||||
state: present
|
||||
register: output
|
||||
|
||||
- name: Is the locale present?
|
||||
shell: locale -a | grep pt_BR
|
||||
register: post_check_output
|
||||
ignore_errors: true
|
||||
|
||||
- name: Make sure the locale is present and we reported no change
|
||||
assert:
|
||||
that:
|
||||
- "post_check_output.rc == 0"
|
||||
- "not output.changed"
|
||||
|
||||
- name: Remove the locale
|
||||
locale_gen:
|
||||
name: pt_BR
|
||||
state: absent
|
||||
register: output
|
||||
|
||||
- name: Is the locale present?
|
||||
shell: locale -a | grep pt_BR
|
||||
register: post_check_output
|
||||
ignore_errors: true
|
||||
|
||||
- name: Make sure the locale is absent and we reported a change
|
||||
assert:
|
||||
that:
|
||||
- "post_check_output.rc == 1"
|
||||
- "output.changed"
|
||||
|
||||
- name: Remove the locale a second time
|
||||
locale_gen:
|
||||
name: pt_BR
|
||||
state: absent
|
||||
register: output
|
||||
|
||||
- name: Is the locale present?
|
||||
shell: locale -a | grep pt_BR
|
||||
register: post_check_output
|
||||
ignore_errors: true
|
||||
|
||||
- name: Make sure the locale is absent and we reported no change
|
||||
assert:
|
||||
that:
|
||||
- "post_check_output.rc == 1"
|
||||
- "not output.changed"
|
||||
|
||||
# Cleanup
|
||||
- name: Reinstall the locale we tested against if it was initially installed
|
||||
locale_gen:
|
||||
name: pt_BR
|
||||
state: present
|
||||
when: initial_state.rc == 0
|
||||
@@ -8,5 +8,11 @@
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- include_tasks: 'locale_gen.yml'
|
||||
when: ansible_distribution in ('Ubuntu', 'Debian')
|
||||
- name: Bail out if not supported
|
||||
ansible.builtin.meta: end_play
|
||||
when: ansible_distribution not in ('Ubuntu', 'Debian')
|
||||
|
||||
- include_tasks: basic.yml
|
||||
loop: "{{ locale_list_basic }}"
|
||||
loop_control:
|
||||
loop_var: locale_basic
|
||||
|
||||
17
tests/integration/targets/locale_gen/vars/main.yml
Normal file
17
tests/integration/targets/locale_gen/vars/main.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# locale_basic: pt_BR
|
||||
|
||||
locale_list_basic:
|
||||
- localegen: pt_BR
|
||||
locales: [pt_BR]
|
||||
skip_removal: false
|
||||
- localegen: C.UTF-8
|
||||
locales: [C.utf8, C.UTF-8]
|
||||
skip_removal: true
|
||||
- localegen: eo
|
||||
locales: [eo]
|
||||
skip_removal: false
|
||||
@@ -9,4 +9,5 @@ skip/macos
|
||||
skip/rhel8.0
|
||||
skip/rhel9.0
|
||||
skip/rhel9.1
|
||||
skip/rhel9.2
|
||||
skip/freebsd
|
||||
|
||||
23
tests/integration/targets/pacman/handlers/main.yml
Normal file
23
tests/integration/targets/pacman/handlers/main.yml
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
- name: Remove user yaybuilder
|
||||
ansible.builtin.user:
|
||||
name: yaybuilder
|
||||
state: absent
|
||||
|
||||
- name: Remove yay
|
||||
ansible.builtin.package:
|
||||
name: yay
|
||||
state: absent
|
||||
|
||||
- name: Remove packages for yay-become
|
||||
ansible.builtin.package:
|
||||
name:
|
||||
- base-devel
|
||||
- yay
|
||||
- git
|
||||
- nmap
|
||||
state: absent
|
||||
@@ -17,3 +17,4 @@
|
||||
- include_tasks: 'update_cache.yml'
|
||||
- include_tasks: 'locally_installed_package.yml'
|
||||
- include_tasks: 'reason.yml'
|
||||
- include_tasks: 'yay-become.yml'
|
||||
|
||||
66
tests/integration/targets/pacman/tasks/yay-become.yml
Normal file
66
tests/integration/targets/pacman/tasks/yay-become.yml
Normal file
@@ -0,0 +1,66 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# This is more convoluted that one might expect, because:
|
||||
# - yay is not available or installation in ArchLinux (as it is in Manjaro - issue 6184 reports using it)
|
||||
# - to install yay in ArchLinux requires building the package
|
||||
# - makepkg cannot be run as root, but the user running it must have sudo to install the resulting package
|
||||
|
||||
- name: create user
|
||||
ansible.builtin.user:
|
||||
name: yaybuilder
|
||||
state: present
|
||||
notify: Remove user yaybuilder
|
||||
|
||||
- name: grant sudo powers to builder
|
||||
community.general.sudoers:
|
||||
name: yaybuilder
|
||||
user: yaybuilder
|
||||
commands: ALL
|
||||
nopassword: true
|
||||
|
||||
- name: Install base packages
|
||||
ansible.builtin.package:
|
||||
name:
|
||||
- base-devel
|
||||
- git
|
||||
- go
|
||||
state: present
|
||||
notify: Remove packages for yay-become
|
||||
|
||||
- name: Hack permssions for the remote_tmp_dir
|
||||
ansible.builtin.file:
|
||||
path: "{{ remote_tmp_dir }}"
|
||||
mode: '0777'
|
||||
|
||||
- name: Create temp directory for builder
|
||||
ansible.builtin.file:
|
||||
path: "{{ remote_tmp_dir }}/builder"
|
||||
owner: yaybuilder
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: clone yay git repo
|
||||
become: true
|
||||
become_user: yaybuilder
|
||||
ansible.builtin.git:
|
||||
repo: https://aur.archlinux.org/yay.git
|
||||
dest: "{{ remote_tmp_dir }}/builder/yay"
|
||||
depth: 1
|
||||
|
||||
- name: make package
|
||||
become: true
|
||||
become_user: yaybuilder
|
||||
ansible.builtin.command:
|
||||
chdir: "{{ remote_tmp_dir }}/builder/yay"
|
||||
cmd: makepkg -si --noconfirm
|
||||
notify: Remove yay
|
||||
|
||||
- name: Install nmap
|
||||
community.general.pacman:
|
||||
name: nmap
|
||||
state: present
|
||||
executable: yay
|
||||
extra_args: --builddir /var/cache/yay
|
||||
@@ -6,3 +6,4 @@ azp/posix/2
|
||||
destructive
|
||||
skip/python2
|
||||
skip/python3.5
|
||||
disabled # TODO
|
||||
|
||||
@@ -6,3 +6,4 @@ azp/posix/3
|
||||
destructive
|
||||
skip/python2
|
||||
skip/python3.5
|
||||
disabled # TODO
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
# Copyright (c) Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Do nothing
|
||||
1
tests/integration/targets/setup_snap/tasks/D-RedHat-9.1.yml
Symbolic link
1
tests/integration/targets/setup_snap/tasks/D-RedHat-9.1.yml
Symbolic link
@@ -0,0 +1 @@
|
||||
nothing.yml
|
||||
1
tests/integration/targets/setup_snap/tasks/D-RedHat-9.2.yml
Symbolic link
1
tests/integration/targets/setup_snap/tasks/D-RedHat-9.2.yml
Symbolic link
@@ -0,0 +1 @@
|
||||
nothing.yml
|
||||
@@ -11,6 +11,7 @@ skip/freebsd
|
||||
skip/rhel8.0 # FIXME
|
||||
skip/rhel9.0 # FIXME
|
||||
skip/rhel9.1 # FIXME
|
||||
skip/rhel9.2 # FIXME
|
||||
skip/docker
|
||||
needs/root
|
||||
needs/target/setup_epel
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
.azure-pipelines/scripts/publish-codecov.py replace-urlopen
|
||||
plugins/modules/consul.py validate-modules:doc-missing-type
|
||||
plugins/modules/consul.py validate-modules:undocumented-parameter
|
||||
plugins/modules/consul_session.py validate-modules:parameter-state-invalid-choice
|
||||
|
||||
@@ -262,6 +262,25 @@ ipv4.routes: { ip = 192.168.200.0/24, nh = 192.168.1.
|
||||
ipv4.route-metric: 10
|
||||
"""
|
||||
|
||||
TESTCASE_ETHERNET_MOD_IPV4_INT_WITH_ROUTE_AND_METRIC_CLEAR = [
|
||||
{
|
||||
'type': 'ethernet',
|
||||
'conn_name': 'non_existent_nw_device',
|
||||
'routes4': [],
|
||||
'state': 'present',
|
||||
'_ansible_check_mode': False,
|
||||
'_ansible_diff': True,
|
||||
},
|
||||
{
|
||||
'type': 'ethernet',
|
||||
'conn_name': 'non_existent_nw_device',
|
||||
'routes4_extended': [],
|
||||
'state': 'present',
|
||||
'_ansible_check_mode': False,
|
||||
'_ansible_diff': True,
|
||||
},
|
||||
]
|
||||
|
||||
TESTCASE_ETHERNET_MOD_IPV6_INT_WITH_ROUTE_AND_METRIC = [
|
||||
{
|
||||
'type': 'ethernet',
|
||||
@@ -1671,6 +1690,17 @@ def mocked_ethernet_connection_with_ipv4_static_address_static_route_metric_modi
|
||||
))
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mocked_ethernet_connection_with_ipv4_static_address_static_route_metric_clear(mocker):
|
||||
mocker_set(mocker,
|
||||
connection_exists=True,
|
||||
execute_return=None,
|
||||
execute_side_effect=(
|
||||
(0, TESTCASE_ETHERNET_MOD_IPV4_INT_WITH_ROUTE_AND_METRIC_SHOW_OUTPUT, ""),
|
||||
(0, "", ""),
|
||||
))
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mocked_ethernet_connection_with_ipv6_static_address_static_route_metric_modify(mocker):
|
||||
mocker_set(mocker,
|
||||
@@ -2991,6 +3021,38 @@ def test_ethernet_connection_static_ipv4_address_static_route_with_metric_modify
|
||||
assert not results.get('failed')
|
||||
|
||||
|
||||
@pytest.mark.parametrize('patch_ansible_module', TESTCASE_ETHERNET_MOD_IPV4_INT_WITH_ROUTE_AND_METRIC_CLEAR, indirect=['patch_ansible_module'])
|
||||
def test_ethernet_connection_static_ipv4_address_static_route_with_metric_clear(
|
||||
mocked_ethernet_connection_with_ipv4_static_address_static_route_metric_clear, capfd):
|
||||
"""
|
||||
Test : Modify ethernet connection with static IPv4 address and static route
|
||||
"""
|
||||
with pytest.raises(SystemExit):
|
||||
nmcli.main()
|
||||
|
||||
arg_list = nmcli.Nmcli.execute_command.call_args_list
|
||||
add_args, add_kw = arg_list[1]
|
||||
|
||||
assert add_args[0][0] == '/usr/bin/nmcli'
|
||||
assert add_args[0][1] == 'con'
|
||||
assert add_args[0][2] == 'modify'
|
||||
assert add_args[0][3] == 'non_existent_nw_device'
|
||||
|
||||
add_args_text = list(map(to_text, add_args[0]))
|
||||
|
||||
for param in ['ipv4.routes', '']:
|
||||
assert param in add_args_text
|
||||
|
||||
out, err = capfd.readouterr()
|
||||
results = json.loads(out)
|
||||
|
||||
assert 'ipv4.routes' in results['diff']['before']
|
||||
assert 'ipv4.routes' in results['diff']['after']
|
||||
|
||||
assert results.get('changed') is True
|
||||
assert not results.get('failed')
|
||||
|
||||
|
||||
@pytest.mark.parametrize('patch_ansible_module', TESTCASE_ETHERNET_ADD_IPV6_INT_WITH_ROUTE, indirect=['patch_ansible_module'])
|
||||
def test_ethernet_connection_static_ipv6_address_static_route_create(mocked_ethernet_connection_with_ipv6_static_address_static_route_create, capfd):
|
||||
"""
|
||||
|
||||
712
tests/unit/plugins/modules/test_rhsm_repository.py
Normal file
712
tests/unit/plugins/modules/test_rhsm_repository.py
Normal file
@@ -0,0 +1,712 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Author: Pino Toscano (ptoscano@redhat.com)
|
||||
# Largely adapted from test_rhsm_repository by
|
||||
# Jiri Hnidek (jhnidek@redhat.com)
|
||||
#
|
||||
# Copyright (c) Pino Toscano (ptoscano@redhat.com)
|
||||
# Copyright (c) Jiri Hnidek (jhnidek@redhat.com)
|
||||
#
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
import copy
|
||||
import fnmatch
|
||||
import json
|
||||
|
||||
from ansible.module_utils import basic
|
||||
from ansible_collections.community.general.plugins.modules import rhsm_repository
|
||||
|
||||
import pytest
|
||||
|
||||
TESTED_MODULE = rhsm_repository.__name__
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def patch_rhsm_repository(mocker):
|
||||
"""
|
||||
Function used for mocking some parts of rhsm_repository module
|
||||
"""
|
||||
mocker.patch('ansible_collections.community.general.plugins.modules.rhsm_repository.AnsibleModule.get_bin_path',
|
||||
return_value='/testbin/subscription-manager')
|
||||
mocker.patch('ansible_collections.community.general.plugins.modules.rhsm_repository.os.getuid',
|
||||
return_value=0)
|
||||
|
||||
|
||||
class Repos(object):
|
||||
"""
|
||||
Helper class to represent a list of repositories
|
||||
|
||||
Each repository is an object with few properties.
|
||||
"""
|
||||
|
||||
_SUBMAN_OUT_HEADER = """+----------------------------------------------------------+
|
||||
Available Repositories in /etc/yum.repos.d/redhat.repo
|
||||
+----------------------------------------------------------+
|
||||
"""
|
||||
_SUBMAN_OUT_ENTRY = """Repo ID: %s
|
||||
Repo Name: %s
|
||||
Repo URL: %s
|
||||
Enabled: %s
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, repos):
|
||||
self.repos = repos
|
||||
|
||||
def to_subman_list_output(self):
|
||||
"""
|
||||
Return a string mimicking the output of `subscription-manager repos --list`
|
||||
"""
|
||||
out = self._SUBMAN_OUT_HEADER
|
||||
for repo in self.repos:
|
||||
out += self._SUBMAN_OUT_ENTRY % (
|
||||
repo["id"],
|
||||
repo["name"],
|
||||
repo["url"],
|
||||
"1" if repo["enabled"] else "0",
|
||||
)
|
||||
|
||||
return out
|
||||
|
||||
def copy(self):
|
||||
"""
|
||||
Clone the object; used to do changes (enable(), disable()) without
|
||||
affecting the original object.
|
||||
"""
|
||||
return copy.deepcopy(self)
|
||||
|
||||
def _set_status(self, repo_id, status):
|
||||
for repo in self.repos:
|
||||
if fnmatch.fnmatch(repo['id'], repo_id):
|
||||
repo['enabled'] = status
|
||||
|
||||
def enable(self, repo_ids):
|
||||
"""
|
||||
Enable the specified IDs.
|
||||
|
||||
'repo_ids' can be either a string or a list of strings representing
|
||||
an ID (wilcard included).
|
||||
|
||||
Returns the same object, so calls to this can be chained.
|
||||
"""
|
||||
if not isinstance(repo_ids, list):
|
||||
repo_ids = [repo_ids]
|
||||
for repo_id in repo_ids:
|
||||
self._set_status(repo_id, True)
|
||||
return self
|
||||
|
||||
def disable(self, repo_ids):
|
||||
"""
|
||||
Disable the specified IDs.
|
||||
|
||||
'repo_ids' can be either a string or a list of strings representing
|
||||
an ID (wilcard included).
|
||||
|
||||
Returns the same object, so calls to this can be chained.
|
||||
"""
|
||||
if not isinstance(repo_ids, list):
|
||||
repo_ids = [repo_ids]
|
||||
for repo_id in repo_ids:
|
||||
self._set_status(repo_id, False)
|
||||
return self
|
||||
|
||||
def _filter_by_status(self, filter, status):
|
||||
return [
|
||||
repo['id']
|
||||
for repo in self.repos
|
||||
if repo['enabled'] == status and fnmatch.fnmatch(repo['id'], filter)
|
||||
]
|
||||
|
||||
def ids_enabled(self, filter='*'):
|
||||
"""
|
||||
Get a list with the enabled repositories.
|
||||
|
||||
'filter' is a wildcard expression.
|
||||
"""
|
||||
return self._filter_by_status(filter, True)
|
||||
|
||||
def ids_disabled(self, filter='*'):
|
||||
"""
|
||||
Get a list with the disabled repositories.
|
||||
|
||||
'filter' is a wildcard expression.
|
||||
"""
|
||||
return self._filter_by_status(filter, False)
|
||||
|
||||
def to_list(self):
|
||||
"""
|
||||
Get the list of repositories.
|
||||
"""
|
||||
return self.repos
|
||||
|
||||
|
||||
# List with test repositories, directly from the Candlepin test data.
|
||||
REPOS_LIST = [
|
||||
{
|
||||
"id": "never-enabled-content-801",
|
||||
"name": "never-enabled-content-801",
|
||||
"url": "https://candlepin.local/foo/path/never_enabled/801-100",
|
||||
"enabled": False,
|
||||
},
|
||||
{
|
||||
"id": "never-enabled-content-100000000000060",
|
||||
"name": "never-enabled-content-100000000000060",
|
||||
"url": "https://candlepin.local/foo/path/never_enabled/100000000000060-100",
|
||||
"enabled": False,
|
||||
},
|
||||
{
|
||||
"id": "awesomeos-x86_64-1000000000000023",
|
||||
"name": "awesomeos-x86_64-1000000000000023",
|
||||
"url": "https://candlepin.local/path/to/awesomeos/x86_64/1000000000000023-11124",
|
||||
"enabled": False,
|
||||
},
|
||||
{
|
||||
"id": "awesomeos-ppc64-100000000000011",
|
||||
"name": "awesomeos-ppc64-100000000000011",
|
||||
"url": "https://candlepin.local/path/to/awesomeos/ppc64/100000000000011-11126",
|
||||
"enabled": False,
|
||||
},
|
||||
{
|
||||
"id": "awesomeos-99000",
|
||||
"name": "awesomeos-99000",
|
||||
"url": "https://candlepin.local/path/to/generic/awesomeos/99000-11113",
|
||||
"enabled": True,
|
||||
},
|
||||
{
|
||||
"id": "content-label-27060",
|
||||
"name": "content-27060",
|
||||
"url": "https://candlepin.local/foo/path/common/27060-1111",
|
||||
"enabled": True,
|
||||
},
|
||||
{
|
||||
"id": "content-label-no-gpg-32060",
|
||||
"name": "content-nogpg-32060",
|
||||
"url": "https://candlepin.local/foo/path/no_gpg/32060-234",
|
||||
"enabled": False,
|
||||
},
|
||||
{
|
||||
"id": "awesomeos-1000000000000023",
|
||||
"name": "awesomeos-1000000000000023",
|
||||
"url": "https://candlepin.local/path/to/generic/awesomeos/1000000000000023-11113",
|
||||
"enabled": False,
|
||||
},
|
||||
{
|
||||
"id": "awesomeos-x86-100000000000020",
|
||||
"name": "awesomeos-x86-100000000000020",
|
||||
"url": "https://candlepin.local/path/to/awesomeos/x86/100000000000020-11120",
|
||||
"enabled": False,
|
||||
},
|
||||
{
|
||||
"id": "awesomeos-x86_64-99000",
|
||||
"name": "awesomeos-x86_64-99000",
|
||||
"url": "https://candlepin.local/path/to/awesomeos/x86_64/99000-11124",
|
||||
"enabled": True,
|
||||
},
|
||||
{
|
||||
"id": "awesomeos-s390x-99000",
|
||||
"name": "awesomeos-s390x-99000",
|
||||
"url": "https://candlepin.local/path/to/awesomeos/s390x/99000-11121",
|
||||
"enabled": False,
|
||||
},
|
||||
{
|
||||
"id": "awesomeos-modifier-37080",
|
||||
"name": "awesomeos-modifier-37080",
|
||||
"url": "https://candlepin.local/example.com/awesomeos-modifier/37080-1112",
|
||||
"enabled": False,
|
||||
},
|
||||
{
|
||||
"id": "awesomeos-i686-99000",
|
||||
"name": "awesomeos-i686-99000",
|
||||
"url": "https://candlepin.local/path/to/awesomeos/i686/99000-11123",
|
||||
"enabled": False,
|
||||
},
|
||||
{
|
||||
"id": "fake-content-38072",
|
||||
"name": "fake-content-38072",
|
||||
"url": "https://candlepin.local/path/to/fake-content/38072-3902",
|
||||
"enabled": True,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
# A static object with the list of repositories, used as reference to query
|
||||
# the repositories, and create (by copy()) new Repos objects.
|
||||
REPOS = Repos(REPOS_LIST)
|
||||
|
||||
# The mock string for the output of `subscription-manager repos --list`.
|
||||
REPOS_LIST_OUTPUT = REPOS.to_subman_list_output()
|
||||
|
||||
# MUST match what's in run_subscription_manager() in the module.
|
||||
SUBMAN_KWARGS = {
|
||||
'environ_update': dict(LANG='C', LC_ALL='C', LC_MESSAGES='C'),
|
||||
}
|
||||
|
||||
|
||||
TEST_CASES = [
|
||||
# enable a disabled repository
|
||||
[
|
||||
{
|
||||
'name': 'awesomeos-1000000000000023',
|
||||
},
|
||||
{
|
||||
'id': 'test_enable_single',
|
||||
'run_command.calls': [
|
||||
(
|
||||
'/testbin/subscription-manager repos --list',
|
||||
SUBMAN_KWARGS,
|
||||
(0, REPOS_LIST_OUTPUT, '')
|
||||
),
|
||||
(
|
||||
(
|
||||
'/testbin/subscription-manager repos'
|
||||
' --enable awesomeos-1000000000000023'
|
||||
),
|
||||
SUBMAN_KWARGS,
|
||||
(0, '', '')
|
||||
),
|
||||
],
|
||||
'changed': True,
|
||||
'repositories': REPOS.copy().enable('awesomeos-1000000000000023'),
|
||||
}
|
||||
],
|
||||
# enable an already enabled repository
|
||||
[
|
||||
{
|
||||
'name': 'fake-content-38072',
|
||||
},
|
||||
{
|
||||
'id': 'test_enable_already_enabled',
|
||||
'run_command.calls': [
|
||||
(
|
||||
'/testbin/subscription-manager repos --list',
|
||||
SUBMAN_KWARGS,
|
||||
(0, REPOS_LIST_OUTPUT, '')
|
||||
),
|
||||
],
|
||||
'changed': False,
|
||||
'repositories': REPOS.copy(),
|
||||
}
|
||||
],
|
||||
# enable two disabled repositories
|
||||
[
|
||||
{
|
||||
'name': ['awesomeos-1000000000000023', 'content-label-no-gpg-32060'],
|
||||
},
|
||||
{
|
||||
'id': 'test_enable_multiple',
|
||||
'run_command.calls': [
|
||||
(
|
||||
'/testbin/subscription-manager repos --list',
|
||||
SUBMAN_KWARGS,
|
||||
(0, REPOS_LIST_OUTPUT, '')
|
||||
),
|
||||
(
|
||||
(
|
||||
'/testbin/subscription-manager repos'
|
||||
' --enable awesomeos-1000000000000023'
|
||||
' --enable content-label-no-gpg-32060'
|
||||
),
|
||||
SUBMAN_KWARGS,
|
||||
(0, '', '')
|
||||
),
|
||||
],
|
||||
'changed': True,
|
||||
'repositories': REPOS.copy().enable('awesomeos-1000000000000023').enable('content-label-no-gpg-32060'),
|
||||
}
|
||||
],
|
||||
# enable two repositories, one disabled and one already enabled
|
||||
[
|
||||
{
|
||||
'name': ['awesomeos-1000000000000023', 'fake-content-38072'],
|
||||
},
|
||||
{
|
||||
'id': 'test_enable_multiple_mixed',
|
||||
'run_command.calls': [
|
||||
(
|
||||
'/testbin/subscription-manager repos --list',
|
||||
SUBMAN_KWARGS,
|
||||
(0, REPOS_LIST_OUTPUT, '')
|
||||
),
|
||||
(
|
||||
(
|
||||
'/testbin/subscription-manager repos'
|
||||
' --enable awesomeos-1000000000000023'
|
||||
' --enable fake-content-38072'
|
||||
),
|
||||
SUBMAN_KWARGS,
|
||||
(0, '', '')
|
||||
),
|
||||
],
|
||||
'changed': True,
|
||||
'repositories': REPOS.copy().enable('awesomeos-1000000000000023'),
|
||||
}
|
||||
],
|
||||
# purge everything but never-enabled-content-801 (disabled)
|
||||
[
|
||||
{
|
||||
'name': 'never-enabled-content-801',
|
||||
'purge': True,
|
||||
},
|
||||
{
|
||||
'id': 'test_purge_everything_but_one_disabled',
|
||||
'run_command.calls': [
|
||||
(
|
||||
'/testbin/subscription-manager repos --list',
|
||||
SUBMAN_KWARGS,
|
||||
(0, REPOS_LIST_OUTPUT, '')
|
||||
),
|
||||
(
|
||||
(
|
||||
'/testbin/subscription-manager repos'
|
||||
' --enable never-enabled-content-801'
|
||||
) + ''.join([' --disable ' + i for i in REPOS.ids_enabled() if i != 'never-enabled-content-801']),
|
||||
SUBMAN_KWARGS,
|
||||
(0, '', '')
|
||||
),
|
||||
],
|
||||
'changed': True,
|
||||
'repositories': REPOS.copy().disable('*').enable('never-enabled-content-801'),
|
||||
}
|
||||
],
|
||||
# purge everything but awesomeos-99000 (already enabled)
|
||||
[
|
||||
{
|
||||
'name': 'awesomeos-99000',
|
||||
'purge': True,
|
||||
},
|
||||
{
|
||||
'id': 'test_purge_everything_but_one_enabled',
|
||||
'run_command.calls': [
|
||||
(
|
||||
'/testbin/subscription-manager repos --list',
|
||||
SUBMAN_KWARGS,
|
||||
(0, REPOS_LIST_OUTPUT, '')
|
||||
),
|
||||
(
|
||||
(
|
||||
'/testbin/subscription-manager repos'
|
||||
' --enable awesomeos-99000'
|
||||
' --disable content-label-27060'
|
||||
' --disable awesomeos-x86_64-99000'
|
||||
' --disable fake-content-38072'
|
||||
),
|
||||
SUBMAN_KWARGS,
|
||||
(0, '', '')
|
||||
),
|
||||
],
|
||||
'changed': True,
|
||||
'repositories': REPOS.copy().disable('*').enable('awesomeos-99000'),
|
||||
}
|
||||
],
|
||||
# enable everything, then purge everything but content-label-27060
|
||||
[
|
||||
{
|
||||
'name': 'content-label-27060',
|
||||
'purge': True,
|
||||
},
|
||||
{
|
||||
'id': 'test_enable_everything_purge_everything_but_one_enabled',
|
||||
'run_command.calls': [
|
||||
(
|
||||
'/testbin/subscription-manager repos --list',
|
||||
SUBMAN_KWARGS,
|
||||
(0, REPOS.copy().enable('*').to_subman_list_output(), '')
|
||||
),
|
||||
(
|
||||
(
|
||||
'/testbin/subscription-manager repos'
|
||||
' --enable content-label-27060'
|
||||
' --disable never-enabled-content-801'
|
||||
' --disable never-enabled-content-100000000000060'
|
||||
' --disable awesomeos-x86_64-1000000000000023'
|
||||
' --disable awesomeos-ppc64-100000000000011'
|
||||
' --disable awesomeos-99000'
|
||||
' --disable content-label-no-gpg-32060'
|
||||
' --disable awesomeos-1000000000000023'
|
||||
' --disable awesomeos-x86-100000000000020'
|
||||
' --disable awesomeos-x86_64-99000'
|
||||
' --disable awesomeos-s390x-99000'
|
||||
' --disable awesomeos-modifier-37080'
|
||||
' --disable awesomeos-i686-99000'
|
||||
' --disable fake-content-38072'
|
||||
),
|
||||
SUBMAN_KWARGS,
|
||||
(0, '', '')
|
||||
),
|
||||
],
|
||||
'changed': True,
|
||||
'repositories': REPOS.copy().disable('*').enable('content-label-27060'),
|
||||
}
|
||||
],
|
||||
# enable all awesomeos-*
|
||||
[
|
||||
{
|
||||
'name': 'awesomeos-*',
|
||||
},
|
||||
{
|
||||
'id': 'test_enable_all_awesomeos_star',
|
||||
'run_command.calls': [
|
||||
(
|
||||
'/testbin/subscription-manager repos --list',
|
||||
SUBMAN_KWARGS,
|
||||
(0, REPOS_LIST_OUTPUT, '')
|
||||
),
|
||||
(
|
||||
(
|
||||
'/testbin/subscription-manager repos'
|
||||
' --enable awesomeos-x86_64-1000000000000023'
|
||||
' --enable awesomeos-ppc64-100000000000011'
|
||||
' --enable awesomeos-99000'
|
||||
' --enable awesomeos-1000000000000023'
|
||||
' --enable awesomeos-x86-100000000000020'
|
||||
' --enable awesomeos-x86_64-99000'
|
||||
' --enable awesomeos-s390x-99000'
|
||||
' --enable awesomeos-modifier-37080'
|
||||
' --enable awesomeos-i686-99000'
|
||||
),
|
||||
SUBMAN_KWARGS,
|
||||
(0, '', '')
|
||||
),
|
||||
],
|
||||
'changed': True,
|
||||
'repositories': REPOS.copy().enable('awesomeos-*'),
|
||||
}
|
||||
],
|
||||
# purge everything but awesomeos-*
|
||||
[
|
||||
{
|
||||
'name': REPOS.ids_enabled('awesomeos-*'),
|
||||
'purge': True,
|
||||
},
|
||||
{
|
||||
'id': 'test_purge_everything_but_awesomeos_list',
|
||||
'run_command.calls': [
|
||||
(
|
||||
'/testbin/subscription-manager repos --list',
|
||||
SUBMAN_KWARGS,
|
||||
(0, REPOS_LIST_OUTPUT, '')
|
||||
),
|
||||
(
|
||||
(
|
||||
'/testbin/subscription-manager repos'
|
||||
' --enable awesomeos-99000'
|
||||
' --enable awesomeos-x86_64-99000'
|
||||
' --disable content-label-27060'
|
||||
' --disable fake-content-38072'
|
||||
),
|
||||
SUBMAN_KWARGS,
|
||||
(0, '', '')
|
||||
),
|
||||
],
|
||||
'changed': True,
|
||||
'repositories': REPOS.copy().disable('*').enable(REPOS.ids_enabled('awesomeos-*')),
|
||||
}
|
||||
],
|
||||
# enable a repository that does not exist
|
||||
[
|
||||
{
|
||||
'name': 'repo-that-does-not-exist',
|
||||
},
|
||||
{
|
||||
'id': 'test_enable_nonexisting',
|
||||
'run_command.calls': [
|
||||
(
|
||||
'/testbin/subscription-manager repos --list',
|
||||
SUBMAN_KWARGS,
|
||||
(0, REPOS_LIST_OUTPUT, '')
|
||||
),
|
||||
],
|
||||
'failed': True,
|
||||
'msg': 'repo-that-does-not-exist is not a valid repository ID',
|
||||
}
|
||||
],
|
||||
# disable an enabled repository
|
||||
[
|
||||
{
|
||||
'name': 'awesomeos-99000',
|
||||
'state': 'disabled',
|
||||
},
|
||||
{
|
||||
'id': 'test_disable_single',
|
||||
'run_command.calls': [
|
||||
(
|
||||
'/testbin/subscription-manager repos --list',
|
||||
SUBMAN_KWARGS,
|
||||
(0, REPOS_LIST_OUTPUT, '')
|
||||
),
|
||||
(
|
||||
(
|
||||
'/testbin/subscription-manager repos'
|
||||
' --disable awesomeos-99000'
|
||||
),
|
||||
SUBMAN_KWARGS,
|
||||
(0, '', '')
|
||||
),
|
||||
],
|
||||
'changed': True,
|
||||
'repositories': REPOS.copy().disable('awesomeos-99000'),
|
||||
}
|
||||
],
|
||||
# disable an enabled repository (using state=absent)
|
||||
[
|
||||
{
|
||||
'name': 'awesomeos-99000',
|
||||
'state': 'absent',
|
||||
},
|
||||
{
|
||||
'id': 'test_disable_single_using_absent',
|
||||
'run_command.calls': [
|
||||
(
|
||||
'/testbin/subscription-manager repos --list',
|
||||
SUBMAN_KWARGS,
|
||||
(0, REPOS_LIST_OUTPUT, '')
|
||||
),
|
||||
(
|
||||
(
|
||||
'/testbin/subscription-manager repos'
|
||||
' --disable awesomeos-99000'
|
||||
),
|
||||
SUBMAN_KWARGS,
|
||||
(0, '', '')
|
||||
),
|
||||
],
|
||||
'changed': True,
|
||||
'repositories': REPOS.copy().disable('awesomeos-99000'),
|
||||
}
|
||||
],
|
||||
# disable an already disabled repository
|
||||
[
|
||||
{
|
||||
'name': 'never-enabled-content-801',
|
||||
'state': 'disabled',
|
||||
},
|
||||
{
|
||||
'id': 'test_disable_already_disabled',
|
||||
'run_command.calls': [
|
||||
(
|
||||
'/testbin/subscription-manager repos --list',
|
||||
SUBMAN_KWARGS,
|
||||
(0, REPOS_LIST_OUTPUT, '')
|
||||
),
|
||||
],
|
||||
'changed': False,
|
||||
'repositories': REPOS.copy(),
|
||||
}
|
||||
],
|
||||
# disable an already disabled repository, and purge
|
||||
[
|
||||
{
|
||||
'name': 'never-enabled-content-801',
|
||||
'state': 'disabled',
|
||||
'purge': True,
|
||||
},
|
||||
{
|
||||
'id': 'test_disable_already_disabled_and_purge',
|
||||
'run_command.calls': [
|
||||
(
|
||||
'/testbin/subscription-manager repos --list',
|
||||
SUBMAN_KWARGS,
|
||||
(0, REPOS_LIST_OUTPUT, '')
|
||||
),
|
||||
(
|
||||
(
|
||||
'/testbin/subscription-manager repos'
|
||||
' --disable never-enabled-content-801'
|
||||
) + ''.join([' --disable ' + i for i in REPOS.ids_enabled()]),
|
||||
SUBMAN_KWARGS,
|
||||
(0, '', '')
|
||||
),
|
||||
],
|
||||
'changed': True,
|
||||
'repositories': REPOS.copy().disable('*'),
|
||||
}
|
||||
],
|
||||
# disable an enabled repository, and purge
|
||||
[
|
||||
{
|
||||
'name': 'awesomeos-99000',
|
||||
'state': 'disabled',
|
||||
'purge': True,
|
||||
},
|
||||
{
|
||||
'id': 'test_disable_single_and_purge',
|
||||
'run_command.calls': [
|
||||
(
|
||||
'/testbin/subscription-manager repos --list',
|
||||
SUBMAN_KWARGS,
|
||||
(0, REPOS_LIST_OUTPUT, '')
|
||||
),
|
||||
(
|
||||
(
|
||||
'/testbin/subscription-manager repos'
|
||||
) + ''.join([' --disable ' + i for i in REPOS.ids_enabled()]),
|
||||
SUBMAN_KWARGS,
|
||||
(0, '', '')
|
||||
),
|
||||
],
|
||||
'changed': True,
|
||||
'repositories': REPOS.copy().disable('*'),
|
||||
}
|
||||
],
|
||||
# disable a repository that does not exist
|
||||
[
|
||||
{
|
||||
'name': 'repo-that-does-not-exist',
|
||||
'state': 'disabled',
|
||||
},
|
||||
{
|
||||
'id': 'test_disable_nonexisting',
|
||||
'run_command.calls': [
|
||||
(
|
||||
'/testbin/subscription-manager repos --list',
|
||||
SUBMAN_KWARGS,
|
||||
(0, REPOS_LIST_OUTPUT, '')
|
||||
),
|
||||
],
|
||||
'failed': True,
|
||||
'msg': 'repo-that-does-not-exist is not a valid repository ID',
|
||||
}
|
||||
],
|
||||
]
|
||||
|
||||
|
||||
TEST_CASES_IDS = [item[1]['id'] for item in TEST_CASES]
|
||||
|
||||
|
||||
@pytest.mark.parametrize('patch_ansible_module, testcase', TEST_CASES, ids=TEST_CASES_IDS, indirect=['patch_ansible_module'])
|
||||
@pytest.mark.usefixtures('patch_ansible_module')
|
||||
def test_rhsm_repository(mocker, capfd, patch_rhsm_repository, testcase):
|
||||
"""
|
||||
Run unit tests for test cases listen in TEST_CASES
|
||||
"""
|
||||
|
||||
# Mock function used for running commands first
|
||||
call_results = [item[2] for item in testcase['run_command.calls']]
|
||||
mock_run_command = mocker.patch.object(
|
||||
basic.AnsibleModule,
|
||||
'run_command',
|
||||
side_effect=call_results)
|
||||
|
||||
# Try to run test case
|
||||
with pytest.raises(SystemExit):
|
||||
rhsm_repository.main()
|
||||
|
||||
out, err = capfd.readouterr()
|
||||
results = json.loads(out)
|
||||
|
||||
if 'failed' in testcase:
|
||||
assert results['failed'] == testcase['failed']
|
||||
assert results['msg'] == testcase['msg']
|
||||
else:
|
||||
assert 'changed' in results
|
||||
assert results['changed'] == testcase['changed']
|
||||
assert results['repositories'] == testcase['repositories'].to_list()
|
||||
|
||||
assert basic.AnsibleModule.run_command.call_count == len(testcase['run_command.calls'])
|
||||
# FIXME ideally we need also to compare the actual calls with the expected
|
||||
# ones; the problem is that the module uses a dict to collect the repositories
|
||||
# to enable and disable, so the order of the --enable/--disable parameters to
|
||||
# `subscription-manager repos` is not stable
|
||||
@@ -19,7 +19,7 @@ wheel < 0.30.0 ; python_version < '2.7' # wheel 0.30.0 and later require python
|
||||
yamllint != 1.8.0, < 1.14.0 ; python_version < '2.7' # yamllint 1.8.0 and 1.14.0+ require python 2.7+
|
||||
pycrypto >= 2.6 # Need features found in 2.6 and greater
|
||||
ncclient >= 0.5.2 # Need features added in 0.5.2 and greater
|
||||
idna < 2.6, >= 2.5 # linode requires idna < 2.9, >= 2.5, requests requires idna < 2.6, but cryptography will cause the latest version to be installed instead
|
||||
# idna < 2.6, >= 2.5 # linode requires idna < 2.9, >= 2.5, requests requires idna < 2.6, but cryptography will cause the latest version to be installed instead
|
||||
paramiko < 2.4.0 ; python_version < '2.7' # paramiko 2.4.0 drops support for python 2.6
|
||||
python-nomad < 2.0.0 ; python_version <= '3.7' # python-nomad 2.0.0 needs Python 3.7+
|
||||
pytest < 3.3.0 ; python_version < '2.7' # pytest 3.3.0 drops support for python 2.6
|
||||
|
||||
Reference in New Issue
Block a user